diff --git a/flang/include/flang/Parser/parsing.h b/flang/include/flang/Parser/parsing.h index 0c774decb16d3..029b5115707b5 100644 --- a/flang/include/flang/Parser/parsing.h +++ b/flang/include/flang/Parser/parsing.h @@ -19,6 +19,7 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include #include #include @@ -66,6 +67,7 @@ class Parsing { void DumpProvenance(llvm::raw_ostream &) const; void DumpParsingLog(llvm::raw_ostream &) const; void Parse(llvm::raw_ostream &debugOutput); + const char *IsCompilerDirectiveSentinel(const char *, std::size_t) const; void ClearLog(); void EmitMessage(llvm::raw_ostream &o, const char *at, @@ -87,6 +89,7 @@ class Parsing { std::optional parseTree_; ParsingLog log_; Preprocessor preprocessor_{allCooked_.allSources()}; + std::unordered_set compilerDirectiveSentinels_; }; } // namespace Fortran::parser #endif // FORTRAN_PARSER_PARSING_H_ diff --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp index 8fcac7b3cacb1..d161809bf7401 100644 --- a/flang/lib/Parser/parsing.cpp +++ b/flang/lib/Parser/parsing.cpp @@ -106,6 +106,7 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) { if (options.showColors) { allSources.setShowColors(/*showColors=*/true); } + compilerDirectiveSentinels_ = prescanner.getCompilerDirectiveSentinels(); return sourceFile; } @@ -153,7 +154,8 @@ void Parsing::EmitPreprocessedSource( return ch; }}; - if (ch == '!' && lineWasBlankBefore) { + if (ch == '!' && lineWasBlankBefore && + IsCompilerDirectiveSentinel((const char *)&atChar + 1, 4)) { // Other comment markers (C, *, D) in original fixed form source // input card column 1 will have been deleted or normalized to !, // which signifies a comment (directive) in both source forms. @@ -258,6 +260,12 @@ void Parsing::Parse(llvm::raw_ostream &out) { finalRestingPlace_ = parseState.GetLocation(); } +const char *Parsing::IsCompilerDirectiveSentinel( + const char *sentinel, std::size_t len) const { + const auto iter{compilerDirectiveSentinels_.find(std::string(sentinel, len))}; + return iter == compilerDirectiveSentinels_.end() ? nullptr : iter->c_str(); +} + void Parsing::ClearLog() { log_.clear(); } } // namespace Fortran::parser diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp index c5939a1e0b6c2..b928ed03a2493 100644 --- a/flang/lib/Parser/prescan.cpp +++ b/flang/lib/Parser/prescan.cpp @@ -511,7 +511,7 @@ bool Prescanner::MustSkipToEndOfLine() const { if (inFixedForm_ && column_ > fixedFormColumnLimit_ && !tabInCurrentLine_) { return true; // skip over ignored columns in right margin (73:80) } else if (*at_ == '!' && !inCharLiteral_) { - return !IsCompilerDirectiveSentinel(at_); + return !IsCompilerDirectiveSentinel(at_ + 1); } else { return false; } diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h index 08041f93b14b6..9099085d079cc 100644 --- a/flang/lib/Parser/prescan.h +++ b/flang/lib/Parser/prescan.h @@ -90,6 +90,9 @@ class Prescanner { template Message &Say(A &&...a) { return messages_.Say(std::forward(a)...); } + std::unordered_set getCompilerDirectiveSentinels() { + return compilerDirectiveSentinels_; + } private: struct LineClassification { diff --git a/flang/test/Preprocessing/bug126459.f90 b/flang/test/Preprocessing/bug126459.f90 new file mode 100644 index 0000000000000..95f3e792560e4 --- /dev/null +++ b/flang/test/Preprocessing/bug126459.f90 @@ -0,0 +1,8 @@ +! RUN: %flang -fopenmp -E %s 2>&1 | FileCheck %s +!CHECK: !$ NDIR=0 +program main +integer NDIR +#define BLANKMACRO + +BLANKMACRO !$ NDIR=0 +end program main