[flang-commits] [flang] e12ffe6 - [flang] Honor #line and related preprocessing directives
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Jun 29 08:27:50 PDT 2023
Author: Peter Klausler
Date: 2023-06-29T08:27:37-07:00
New Revision: e12ffe6a93505e590158ddd8cc73a4f201bbf0aa
URL: https://github.com/llvm/llvm-project/commit/e12ffe6a93505e590158ddd8cc73a4f201bbf0aa
DIFF: https://github.com/llvm/llvm-project/commit/e12ffe6a93505e590158ddd8cc73a4f201bbf0aa.diff
LOG: [flang] Honor #line and related preprocessing directives
Extend the SourceFile class to take account of #line directives
when computing source file positions for error messages.
Adjust the output of #line directives to -E output so that they
reflect any #line directives that were in the input.
Differential Revision: https://reviews.llvm.org/D153910
Added:
flang/test/Parser/line-directive.f90
flang/test/Semantics/line-directive.f90
Modified:
flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
flang/include/flang/Parser/source.h
flang/lib/Frontend/FrontendActions.cpp
flang/lib/Lower/Bridge.cpp
flang/lib/Parser/parsing.cpp
flang/lib/Parser/preprocessor.cpp
flang/lib/Parser/preprocessor.h
flang/lib/Parser/prescan.cpp
flang/lib/Parser/prescan.h
flang/lib/Parser/provenance.cpp
flang/lib/Parser/source.cpp
flang/lib/Semantics/semantics.cpp
flang/test/Driver/debug-provenance.f90
Removed:
################################################################################
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
index 7382e99de1ab89..00acb14ca8bbd5 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
@@ -180,8 +180,8 @@ void OpenMPCounterVisitor::PostConstructsCommon() {
clauseStrings[curConstruct].begin(), clauseStrings[curConstruct].end());
SourcePosition s{getLocation(*curConstruct)};
- LogRecord r{s.file.path(), s.line, getName(*curConstruct),
- clauseStrings[curConstruct]};
+ LogRecord r{
+ s.path, s.line, getName(*curConstruct), clauseStrings[curConstruct]};
constructClauses.push_back(r);
auto it = clauseStrings.find(curConstruct);
diff --git a/flang/include/flang/Parser/source.h b/flang/include/flang/Parser/source.h
index 4f387bdc028893..f0ae97a3ef0485 100644
--- a/flang/include/flang/Parser/source.h
+++ b/flang/include/flang/Parser/source.h
@@ -15,10 +15,14 @@
// - A Unicode byte order mark is recognized if present.
#include "characters.h"
+#include "flang/Common/reference.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
#include <cstddef>
#include <list>
+#include <map>
#include <optional>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -36,15 +40,18 @@ std::optional<std::string> LocateSourceFile(
class SourceFile;
struct SourcePosition {
- const SourceFile &file;
+ common::Reference<const SourceFile> sourceFile;
+ common::Reference<const std::string>
+ path; // may not be sourceFile.path() when #line present
int line, column;
+ int trueLineNumber;
};
class SourceFile {
public:
explicit SourceFile(Encoding e) : encoding_{e} {}
~SourceFile();
- std::string path() const { return path_; }
+ const std::string &path() const { return path_; }
llvm::ArrayRef<char> content() const {
return buf_->getBuffer().slice(bom_end_, buf_end_ - bom_end_);
}
@@ -55,12 +62,20 @@ class SourceFile {
bool Open(std::string path, llvm::raw_ostream &error);
bool ReadStandardInput(llvm::raw_ostream &error);
void Close();
- SourcePosition FindOffsetLineAndColumn(std::size_t) const;
+ SourcePosition GetSourcePosition(std::size_t) const;
std::size_t GetLineStartOffset(int lineNumber) const {
return lineStart_.at(lineNumber - 1);
}
+ const std::string &SavePath(std::string &&);
+ void LineDirective(int trueLineNumber, const std::string &, int);
+ llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
private:
+ struct SourcePositionOrigin {
+ const std::string &path;
+ int line;
+ };
+
void ReadFile();
void IdentifyPayload();
void RecordLineStarts();
@@ -71,6 +86,8 @@ class SourceFile {
std::size_t bom_end_{0};
std::size_t buf_end_;
Encoding encoding_;
+ std::set<std::string> distinctPaths_;
+ std::map<std::size_t, SourcePositionOrigin> origins_;
};
} // namespace Fortran::parser
#endif // FORTRAN_PARSER_SOURCE_H_
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 415ce42c20d13e..00f4de4d570153 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -606,10 +606,10 @@ void GetDefinitionAction::executeAction() {
}
llvm::outs() << "Found symbol name: " << symbol->name().ToString() << "\n";
- llvm::outs() << symbol->name().ToString() << ": "
- << sourceInfo->first.file.path() << ", "
- << sourceInfo->first.line << ", " << sourceInfo->first.column
- << "-" << sourceInfo->second.column << "\n";
+ llvm::outs() << symbol->name().ToString() << ": " << sourceInfo->first.path
+ << ", " << sourceInfo->first.line << ", "
+ << sourceInfo->first.column << "-" << sourceInfo->second.column
+ << "\n";
}
void GetSymbolsSourcesAction::executeAction() {
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index bc0c13e44ed390..1bf538a0a1c8e6 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -716,7 +716,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
loc = cooked->GetSourcePositionRange(block)) {
// loc is a pair (begin, end); use the beginning position
Fortran::parser::SourcePosition &filePos = loc->first;
- llvm::SmallString<256> filePath(filePos.file.path());
+ llvm::SmallString<256> filePath(*filePos.path);
llvm::sys::fs::make_absolute(filePath);
llvm::sys::path::remove_dots(filePath);
return mlir::FileLineColLoc::get(&getMLIRContext(), filePath.str(),
diff --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp
index 1f17ed8b690673..a55d33bf6b91d6 100644
--- a/flang/lib/Parser/parsing.cpp
+++ b/flang/lib/Parser/parsing.cpp
@@ -32,7 +32,7 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
std::string buf;
llvm::raw_string_ostream fileError{buf};
- const SourceFile *sourceFile;
+ const SourceFile *sourceFile{nullptr};
if (path == "-") {
sourceFile = allSources.ReadStandardInput(fileError);
} else if (options.isModuleFile) {
@@ -109,7 +109,7 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
void Parsing::EmitPreprocessedSource(
llvm::raw_ostream &out, bool lineDirectives) const {
- const SourceFile *sourceFile{nullptr};
+ const std::string *sourcePath{nullptr};
int sourceLine{0};
int column{1};
bool inDirective{false};
@@ -162,8 +162,8 @@ void Parsing::EmitPreprocessedSource(
? allSources.GetSourcePosition(provenance->start())
: std::nullopt};
if (lineDirectives && column == 1 && position) {
- if (&position->file != sourceFile) {
- out << "#line \"" << position->file.path() << "\" " << position->line
+ if (&*position->path != sourcePath) {
+ out << "#line \"" << *position->path << "\" " << position->line
<< '\n';
} else if (position->line != sourceLine) {
if (sourceLine < position->line &&
@@ -178,7 +178,7 @@ void Parsing::EmitPreprocessedSource(
out << "#line " << position->line << '\n';
}
}
- sourceFile = &position->file;
+ sourcePath = &*position->path;
sourceLine = position->line;
}
if (column > 72) {
diff --git a/flang/lib/Parser/preprocessor.cpp b/flang/lib/Parser/preprocessor.cpp
index 1efe21ae18fe3c..9197906e79f109 100644
--- a/flang/lib/Parser/preprocessor.cpp
+++ b/flang/lib/Parser/preprocessor.cpp
@@ -434,7 +434,8 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) {
return;
}
if (IsDecimalDigit(dir.TokenAt(j)[0]) || dir.TokenAt(j)[0] == '"') {
- return; // treat like #line, ignore it
+ LineDirective(dir, j, prescanner);
+ return;
}
std::size_t dirOffset{j};
std::string dirName{ToLowerCaseLetters(dir.TokenAt(dirOffset).ToString())};
@@ -444,7 +445,7 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) {
nameToken = dir.TokenAt(j);
}
if (dirName == "line") {
- // #line is ignored
+ LineDirective(dir, j, prescanner);
} else if (dirName == "define") {
if (nameToken.empty()) {
prescanner.Say(dir.GetTokenProvenanceRange(j < tokens ? j : tokens - 1),
@@ -1122,4 +1123,57 @@ bool Preprocessor::IsIfPredicateTrue(const TokenSequence &expr,
}
return result;
}
+
+void Preprocessor::LineDirective(
+ const TokenSequence &dir, std::size_t j, Prescanner &prescanner) {
+ std::size_t tokens{dir.SizeInTokens()};
+ const std::string *linePath{nullptr};
+ std::optional<int> lineNumber;
+ SourceFile *sourceFile{nullptr};
+ std::optional<SourcePosition> pos;
+ for (; j < tokens; j = dir.SkipBlanks(j + 1)) {
+ std::string tstr{dir.TokenAt(j).ToString()};
+ Provenance provenance{dir.GetTokenProvenance(j)};
+ if (!pos) {
+ pos = allSources_.GetSourcePosition(provenance);
+ }
+ if (!sourceFile && pos) {
+ sourceFile = const_cast<SourceFile *>(&*pos->sourceFile);
+ }
+ if (tstr.front() == '"' && tstr.back() == '"') {
+ tstr = tstr.substr(1, tstr.size() - 2);
+ if (!tstr.empty() && sourceFile) {
+ linePath = &sourceFile->SavePath(std::move(tstr));
+ }
+ } else if (IsDecimalDigit(tstr[0])) {
+ if (!lineNumber) { // ignore later column number
+ int ln{0};
+ for (char c : tstr) {
+ if (IsDecimalDigit(c)) {
+ int nln{10 * ln + c - '0'};
+ if (nln / 10 == ln && nln % 10 == c - '0') {
+ ln = nln;
+ continue;
+ }
+ }
+ prescanner.Say(provenance,
+ "bad line number '%s' in #line directive"_err_en_US, tstr);
+ return;
+ }
+ lineNumber = ln;
+ }
+ } else {
+ prescanner.Say(
+ provenance, "bad token '%s' in #line directive"_err_en_US, tstr);
+ return;
+ }
+ }
+ if (lineNumber && sourceFile) {
+ CHECK(pos);
+ if (!linePath) {
+ linePath = &*pos->path;
+ }
+ sourceFile->LineDirective(pos->trueLineNumber + 1, *linePath, *lineNumber);
+ }
+}
} // namespace Fortran::parser
diff --git a/flang/lib/Parser/preprocessor.h b/flang/lib/Parser/preprocessor.h
index 8900dc3f441500..5d866ae685c89b 100644
--- a/flang/lib/Parser/preprocessor.h
+++ b/flang/lib/Parser/preprocessor.h
@@ -90,6 +90,7 @@ class Preprocessor {
const std::string &, IsElseActive, Prescanner &, ProvenanceRange);
bool IsIfPredicateTrue(const TokenSequence &expr, std::size_t first,
std::size_t exprTokens, Prescanner &);
+ void LineDirective(const TokenSequence &, std::size_t, Prescanner &);
AllSources &allSources_;
std::list<std::string> names_;
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index c42e8eaab7994c..6444c8713c722a 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -349,7 +349,7 @@ void Prescanner::EnforceStupidEndStatementRules(const TokenSequence &tokens) {
if (!start || !end) {
return;
}
- if (&start->file == &end->file && start->line == end->line) {
+ if (&*start->sourceFile == &*end->sourceFile && start->line == end->line) {
return; // no continuation
}
j += 3;
@@ -377,9 +377,11 @@ void Prescanner::EnforceStupidEndStatementRules(const TokenSequence &tokens) {
auto endOfPrefixPos{
allSources_.GetSourcePosition(tokens.GetCharProvenance(endOfPrefix))};
auto next{allSources_.GetSourcePosition(tokens.GetCharProvenance(j))};
- if (endOfPrefixPos && next && &endOfPrefixPos->file == &start->file &&
+ if (endOfPrefixPos && next &&
+ &*endOfPrefixPos->sourceFile == &*start->sourceFile &&
endOfPrefixPos->line == start->line &&
- (&next->file != &start->file || next->line != start->line)) {
+ (&*next->sourceFile != &*start->sourceFile ||
+ next->line != start->line)) {
Say(range,
"Initial line of continued statement must not appear to be a program unit END in fixed form source"_err_en_US);
}
diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h
index 69d3b590e1ec04..86fa06f1193b16 100644
--- a/flang/lib/Parser/prescan.h
+++ b/flang/lib/Parser/prescan.h
@@ -204,7 +204,7 @@ class Prescanner {
const char *nextLine_{nullptr}; // next line to process; <= limit_
const char *directiveSentinel_{nullptr}; // current compiler directive
- // This data members are state for processing the source line containing
+ // These data members are state for processing the source line containing
// "at_", which goes to up to the newline character before "nextLine_".
const char *at_{nullptr}; // next character to process; < nextLine_
int column_{1}; // card image column position of next character
diff --git a/flang/lib/Parser/provenance.cpp b/flang/lib/Parser/provenance.cpp
index 5c40ab7bb433a0..b29bc4d1e6a6c1 100644
--- a/flang/lib/Parser/provenance.cpp
+++ b/flang/lib/Parser/provenance.cpp
@@ -10,6 +10,7 @@
#include "flang/Common/idioms.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <set>
#include <utility>
namespace Fortran::parser {
@@ -251,15 +252,14 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
common::visit(
common::visitors{
[&](const Inclusion &inc) {
- o << inc.source.path();
std::size_t offset{origin.covers.MemberOffset(range->start())};
- SourcePosition pos{inc.source.FindOffsetLineAndColumn(offset)};
- o << ':' << pos.line << ':' << pos.column << ": ";
+ SourcePosition pos{inc.source.GetSourcePosition(offset)};
+ o << pos.path << ':' << pos.line << ':' << pos.column << ": ";
EmitPrefix(o, color, prefix, this->getShowColors());
o << message << '\n';
if (echoSourceLine) {
const char *text{inc.source.content().data() +
- inc.source.GetLineStartOffset(pos.line)};
+ inc.source.GetLineStartOffset(pos.trueLineNumber)};
o << " ";
for (const char *p{text}; *p != '\n'; ++p) {
o << *p;
@@ -274,7 +274,7 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
auto last{range->start() + range->size() - 1};
if (&MapToOrigin(last) == &origin) {
auto endOffset{origin.covers.MemberOffset(last)};
- auto endPos{inc.source.FindOffsetLineAndColumn(endOffset)};
+ auto endPos{inc.source.GetSourcePosition(endOffset)};
if (pos.line == endPos.line) {
for (int j{pos.column}; j < endPos.column; ++j) {
o << '^';
@@ -351,7 +351,7 @@ std::optional<SourcePosition> AllSources::GetSourcePosition(
common::visitors{
[&](const Inclusion &inc) -> std::optional<SourcePosition> {
std::size_t offset{origin.covers.MemberOffset(prov)};
- return inc.source.FindOffsetLineAndColumn(offset);
+ return inc.source.GetSourcePosition(offset);
},
[&](const Macro &) {
return GetSourcePosition(origin.replaces.start());
@@ -373,14 +373,15 @@ std::optional<ProvenanceRange> AllSources::GetFirstFileProvenance() const {
}
std::string AllSources::GetPath(Provenance at) const {
- const SourceFile *source{GetSourceFile(at)};
- return source ? source->path() : ""s;
+ std::size_t offset{0};
+ const SourceFile *source{GetSourceFile(at, &offset)};
+ return source ? *source->GetSourcePosition(offset).path : ""s;
}
int AllSources::GetLineNumber(Provenance at) const {
std::size_t offset{0};
const SourceFile *source{GetSourceFile(at, &offset)};
- return source ? source->FindOffsetLineAndColumn(offset).line : 0;
+ return source ? source->GetSourcePosition(offset).line : 0;
}
Provenance AllSources::CompilerInsertionProvenance(char ch) {
@@ -529,6 +530,7 @@ llvm::raw_ostream &AllSources::Dump(llvm::raw_ostream &o) const {
o << "AllSources range_ ";
DumpRange(o, range_);
o << '\n';
+ std::set<const SourceFile *> sources;
for (const Origin &m : origin_) {
o << " ";
DumpRange(o, m.covers);
@@ -539,6 +541,7 @@ llvm::raw_ostream &AllSources::Dump(llvm::raw_ostream &o) const {
o << "module ";
}
o << "file " << inc.source.path();
+ sources.emplace(&inc.source);
},
[&](const Macro &mac) { o << "macro " << mac.expansion; },
[&](const CompilerInsertion &ins) {
@@ -557,6 +560,9 @@ llvm::raw_ostream &AllSources::Dump(llvm::raw_ostream &o) const {
}
o << '\n';
}
+ for (const SourceFile *sf : sources) {
+ sf->Dump(o);
+ }
return o;
}
diff --git a/flang/lib/Parser/source.cpp b/flang/lib/Parser/source.cpp
index 3fbbf78517d02e..d0fe399424e139 100644
--- a/flang/lib/Parser/source.cpp
+++ b/flang/lib/Parser/source.cpp
@@ -9,34 +9,36 @@
#include "flang/Parser/source.h"
#include "flang/Common/idioms.h"
#include "flang/Parser/char-buffer.h"
+#include "flang/Parser/characters.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cstring>
#include <memory>
+#include <string>
#include <vector>
namespace Fortran::parser {
SourceFile::~SourceFile() { Close(); }
-static std::vector<std::size_t> FindLineStarts(llvm::StringRef source) {
- std::vector<std::size_t> result;
- if (source.size() > 0) {
- CHECK(source.back() == '\n' && "missing ultimate newline");
+void SourceFile::RecordLineStarts() {
+ if (std::size_t chars{bytes()}; chars > 0) {
+ origins_.emplace(1, SourcePositionOrigin{path_, 1});
+ const char *source{content().data()};
+ CHECK(source[chars - 1] == '\n' && "missing ultimate newline");
std::size_t at{0};
- do {
- result.push_back(at);
- at = source.find('\n', at) + 1;
- } while (at < source.size());
- result.shrink_to_fit();
+ do { // "at" is always at the beginning of a source line
+ lineStart_.push_back(at);
+ at = reinterpret_cast<const char *>(
+ std::memchr(source + at, '\n', chars - at)) -
+ source + 1;
+ } while (at < chars);
+ CHECK(at == chars);
+ lineStart_.shrink_to_fit();
}
- return result;
-}
-
-void SourceFile::RecordLineStarts() {
- lineStart_ = FindLineStarts({content().data(), bytes()});
}
// Check for a Unicode byte order mark (BOM).
@@ -157,14 +159,43 @@ void SourceFile::ReadFile() {
void SourceFile::Close() {
path_.clear();
buf_.reset();
+ distinctPaths_.clear();
+ origins_.clear();
}
-SourcePosition SourceFile::FindOffsetLineAndColumn(std::size_t at) const {
+SourcePosition SourceFile::GetSourcePosition(std::size_t at) const {
CHECK(at < bytes());
+ auto it{llvm::upper_bound(lineStart_, at)};
+ auto trueLineNumber{std::distance(lineStart_.begin(), it - 1) + 1};
+ auto ub{origins_.upper_bound(trueLineNumber)};
+ auto column{static_cast<int>(at - lineStart_[trueLineNumber - 1] + 1)};
+ if (ub == origins_.begin()) {
+ return {*this, path_, static_cast<int>(trueLineNumber), column,
+ static_cast<int>(trueLineNumber)};
+ } else {
+ --ub;
+ const SourcePositionOrigin &origin{ub->second};
+ auto lineNumber{
+ trueLineNumber - ub->first + static_cast<std::size_t>(origin.line)};
+ return {*this, origin.path, static_cast<int>(lineNumber), column,
+ static_cast<int>(trueLineNumber)};
+ }
+}
- auto it = llvm::upper_bound(lineStart_, at);
- auto low = std::distance(lineStart_.begin(), it - 1);
- return {*this, static_cast<int>(low + 1),
- static_cast<int>(at - lineStart_[low] + 1)};
+const std::string &SourceFile::SavePath(std::string &&path) {
+ return *distinctPaths_.emplace(std::move(path)).first;
+}
+
+void SourceFile::LineDirective(
+ int trueLineNumber, const std::string &path, int lineNumber) {
+ origins_.emplace(trueLineNumber, SourcePositionOrigin{path, lineNumber});
+}
+
+llvm::raw_ostream &SourceFile::Dump(llvm::raw_ostream &o) const {
+ o << "SourceFile '" << path_ << "'\n";
+ for (const auto &[at, spo] : origins_) {
+ o << " origin_[" << at << "] -> '" << spo.path << "' " << spo.line << '\n';
+ }
+ return o;
}
} // namespace Fortran::parser
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index d7dbe002a666c3..6626b3e9d65135 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -557,9 +557,9 @@ void Semantics::DumpSymbolsSources(llvm::raw_ostream &os) const {
for (const auto &pair : symbols) {
const Symbol &symbol{pair.second};
if (auto sourceInfo{allCooked.GetSourcePositionRange(symbol.name())}) {
- os << symbol.name().ToString() << ": " << sourceInfo->first.file.path()
- << ", " << sourceInfo->first.line << ", " << sourceInfo->first.column
- << "-" << sourceInfo->second.column << "\n";
+ os << symbol.name().ToString() << ": " << sourceInfo->first.path << ", "
+ << sourceInfo->first.line << ", " << sourceInfo->first.column << "-"
+ << sourceInfo->second.column << "\n";
} else if (symbol.has<semantics::UseDetails>()) {
os << symbol.name().ToString() << ": "
<< symbol.GetUltimate().owner().symbol()->name().ToString() << "\n";
diff --git a/flang/test/Driver/debug-provenance.f90 b/flang/test/Driver/debug-provenance.f90
index c96eebfce2c424..28563569b5000f 100644
--- a/flang/test/Driver/debug-provenance.f90
+++ b/flang/test/Driver/debug-provenance.f90
@@ -9,6 +9,8 @@
! CHECK-NEXT: [3..3] (1 bytes) -> compiler '\'(0x5c)
! CHECK-NEXT: [{{[0-9]*}}..{{[0-9]*}}] ({{[0-9]*}} bytes) -> file {{.*[/\\]}}debug-provenance.f90
! CHECK-NEXT: [{{[0-9]*}}..{{[0-9]*}}] ({{[0-9]*}} bytes) -> compiler '(after end of source)'
+! CHECK-NEXT: SourceFile '{{.*[/\\]}}debug-provenance.f90'
+! CHECK-NEXT: origin_[1] -> '{{.*[/\\]}}debug-provenance.f90' 1
! CHECK-NEXT: CookedSource::provenanceMap_:
! CHECK-NEXT: offsets [{{[0-9]*}}..{{[0-9]*}}] -> provenances [{{[0-9]*}}..{{[0-9]*}}] ({{[0-9]*}} bytes)
! CHECK-NEXT: CookedSource::invertedMap_:
diff --git a/flang/test/Parser/line-directive.f90 b/flang/test/Parser/line-directive.f90
new file mode 100644
index 00000000000000..e22b106745cc41
--- /dev/null
+++ b/flang/test/Parser/line-directive.f90
@@ -0,0 +1,18 @@
+! RUN: %flang_fc1 -E %s 2>&1 | FileCheck %s
+!CHECK: #line "{{.*[/\\]}}line-directive.f90" 3
+subroutine s
+ implicit none
+ a = 1.
+#line 100
+!CHECK: #line 101
+ b = 2.
+#line "sourceFile.cobol" 200
+!CHECK: #line "sourceFile.cobol" 201
+ c = 3.
+# 300
+!CHECK: #line 301
+ d = 4.
+# "/dev/random" 400
+!CHECK: #line "/dev/random" 401
+ e = 5.
+end
diff --git a/flang/test/Semantics/line-directive.f90 b/flang/test/Semantics/line-directive.f90
new file mode 100644
index 00000000000000..62fde017d12104
--- /dev/null
+++ b/flang/test/Semantics/line-directive.f90
@@ -0,0 +1,18 @@
+!RUN: not %flang -fsyntax-only %s 2>&1 | FileCheck %s
+subroutine s
+ implicit none
+!CHECK: line-directive.f90:5:3: error: No explicit type declared for 'a'
+ a = 1.
+#line 100
+!CHECK: line-directive.f90:101:3: error: No explicit type declared for 'b'
+ b = 2.
+#line "sourceFile.cobol" 200
+!CHECK: sourceFile.cobol:201:3: error: No explicit type declared for 'c'
+ c = 3.
+# 300
+!CHECK: sourceFile.cobol:301:3: error: No explicit type declared for 'd'
+ d = 4.
+# "/dev/random" 400
+!CHECK: random:401:3: error: No explicit type declared for 'e'
+ e = 5.
+end
More information about the flang-commits
mailing list