From 320389e849f82403049c76ef06d11bfcef7b82e3 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Tue, 21 Jul 2020 17:57:06 -0700 Subject: [PATCH] [flang] Fix source line continuation in potential macro calls (bugzilla 46768) The prescanner looks for implicit continuation lines when there are unclosed parentheses at the end of a line, so that source preprocessing macro references with arguments that span lines are recognized. The condition that determines this implicit continuation has been put into a predicate member function and corrected to apply only when the following line is source (not a preprocessing directive, comment, &c.). Fixes bugzilla #46768. Reviewed By: sscalpone Differential Revision: https://reviews.llvm.org/D84280 --- flang/lib/Parser/prescan.cpp | 16 +++++++++++----- flang/lib/Parser/prescan.h | 1 + flang/test/Parser/continuation-in-if.f | 9 +++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 flang/test/Parser/continuation-in-if.f diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp index 68e1de1e5e44..c81d6cb50846 100644 --- a/flang/lib/Parser/prescan.cpp +++ b/flang/lib/Parser/prescan.cpp @@ -887,10 +887,8 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) { return nextLine_ + 6; } } - if (delimiterNesting_ > 0) { - if (!IsFixedFormCommentChar(col1)) { - return nextLine_; - } + if (IsImplicitContinuation()) { + return nextLine_; } } return nullptr; // not a continuation line @@ -927,7 +925,7 @@ const char *Prescanner::FreeFormContinuationLine(bool ampersand) { return p + 1; } else if (*p == '!' || *p == '\n' || *p == '#') { return nullptr; - } else if (ampersand || delimiterNesting_ > 0) { + } else if (ampersand || IsImplicitContinuation()) { if (p > nextLine_) { --p; } else { @@ -981,6 +979,14 @@ bool Prescanner::FreeFormContinuation() { return false; } +// Implicit line continuation allows a preprocessor macro call with +// arguments to span multiple lines. +bool Prescanner::IsImplicitContinuation() const { + return !inPreprocessorDirective_ && !inCharLiteral_ && + delimiterNesting_ > 0 && nextLine_ < limit_ && + ClassifyLine(nextLine_).kind == LineClassification::Kind::Source; +} + bool Prescanner::Continuation(bool mightNeedFixedFormSpace) { if (*at_ == '\n' || *at_ == '&') { if (inFixedForm_) { diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h index 393016fde369..6e492a73597b 100644 --- a/flang/lib/Parser/prescan.h +++ b/flang/lib/Parser/prescan.h @@ -166,6 +166,7 @@ private: const char *IsPreprocessorDirectiveLine(const char *) const; const char *FixedFormContinuationLine(bool mightNeedSpace); const char *FreeFormContinuationLine(bool ampersand); + bool IsImplicitContinuation() const; bool FixedFormContinuation(bool mightNeedSpace); bool FreeFormContinuation(); bool Continuation(bool mightNeedFixedFormSpace); diff --git a/flang/test/Parser/continuation-in-if.f b/flang/test/Parser/continuation-in-if.f new file mode 100644 index 000000000000..928170eb6cd5 --- /dev/null +++ b/flang/test/Parser/continuation-in-if.f @@ -0,0 +1,9 @@ +! RUN: %f18 -funparse %s 2>&1 | FileCheck %s +! CHECK: CALL foo("N","N") +#ifdef transpose + call foo('T', +#else + call foo('N', +#endif + $ 'N') + end