[flang] Allow conditional compilation directives to affect continuation lines (again).
authorpeter klausler <pklausler@nvidia.com>
Wed, 2 May 2018 23:09:12 +0000 (16:09 -0700)
committerpeter klausler <pklausler@nvidia.com>
Fri, 4 May 2018 16:35:09 +0000 (09:35 -0700)
Original-commit: flang-compiler/f18@9b9fd356ddfdd4934ddd7de9e3ce8cd0ebe606c7
Reviewed-on: https://github.com/flang-compiler/f18/pull/81
Tree-same-pre-rewrite: false

flang/lib/parser/prescan.cc
flang/lib/parser/prescan.h

index 61107d79e78dfaeadbb5851b18417c6929a8503f..8ce27364e30a4e484c6e69fd0c2d5fbaaef055d2 100644 (file)
@@ -98,6 +98,7 @@ void Prescanner::Statement() {
     FortranInclude(lineStart_ + line.payloadOffset);
     NextLine();
     return;
+  case LineClassification::Kind::ConditionalCompilationDirective:
   case LineClassification::Kind::PreprocessorDirective:
     preprocessor_.Directive(TokenizePreprocessorDirective(), this);
     return;
@@ -147,6 +148,7 @@ void Prescanner::Statement() {
     case LineClassification::Kind::Include:
       FortranInclude(ppd + ppl.payloadOffset);
       break;
+    case LineClassification::Kind::ConditionalCompilationDirective:
     case LineClassification::Kind::PreprocessorDirective:
       Say("preprocessed line looks like a preprocessor directive"_en_US,
           preprocessed->GetProvenanceRange());
@@ -617,26 +619,44 @@ void Prescanner::FortranInclude(const char *firstQuote) {
   }
 }
 
-bool Prescanner::IsPreprocessorDirectiveLine(const char *start) const {
+const char *Prescanner::IsPreprocessorDirectiveLine(const char *start) const {
   const char *p{start};
   for (; *p == ' '; ++p) {
   }
   if (*p == '#') {
-    return !inFixedForm_ || p != start + 5;
+    if (inFixedForm_ && p == start + 5) {
+      return nullptr;
+    }
+  } else {
+    for (; *p == ' ' || *p == '\t'; ++p) {
+    }
+    if (*p != '#') {
+      return nullptr;
+    }
   }
-  for (; *p == ' ' || *p == '\t'; ++p) {
+  for (++p; *p == ' ' || *p == '\t'; ++p) {
   }
-  return *p == '#';
+  return p;
 }
 
 bool Prescanner::IsNextLinePreprocessorDirective() const {
-  return IsPreprocessorDirectiveLine(lineStart_);
+  return IsPreprocessorDirectiveLine(lineStart_) != nullptr;
 }
 
 void Prescanner::SkipCommentLines() {
-  while (lineStart_ < limit_ &&
-      ClassifyLine(lineStart_).kind == LineClassification::Kind::Comment) {
-    NextLine();
+  while (lineStart_ < limit_) {
+    auto lineClass = ClassifyLine(lineStart_);
+    if (lineClass.kind == LineClassification::Kind::Comment) {
+      NextLine();
+    } else if (!inPreprocessorDirective_ &&
+        lineClass.kind ==
+            LineClassification::Kind::ConditionalCompilationDirective) {
+      // Allow conditional compilation directives (e.g., #ifdef) to affect
+      // continuation lines.
+      preprocessor_.Directive(TokenizePreprocessorDirective(), this);
+    } else {
+      break;
+    }
   }
 }
 
@@ -873,8 +893,13 @@ Prescanner::LineClassification Prescanner::ClassifyLine(
   if (std::optional<std::size_t> quoteOffset{IsIncludeLine(start)}) {
     return {LineClassification::Kind::Include, *quoteOffset};
   }
-  if (IsPreprocessorDirectiveLine(start)) {
-    return {LineClassification::Kind::PreprocessorDirective};
+  if (const char *dir{IsPreprocessorDirectiveLine(start)}) {
+    if (std::memcmp(dir, "if", 2) == 0 || std::memcmp(dir, "elif", 4) == 0 ||
+        std::memcmp(dir, "else", 4) == 0 || std::memcmp(dir, "endif", 5) == 0) {
+      return {LineClassification::Kind::ConditionalCompilationDirective};
+    } else {
+      return {LineClassification::Kind::PreprocessorDirective};
+    }
   }
   return {LineClassification::Kind::Source};
 }
index 44d5a207f639727d167528c31680bbf357070538..f57fa82508e0d7249db84f7124a5a7f14cbec820 100644 (file)
@@ -88,6 +88,7 @@ private:
   struct LineClassification {
     enum class Kind {
       Comment,
+      ConditionalCompilationDirective,
       PreprocessorDirective,
       Include,
       CompilerDirective,
@@ -153,7 +154,7 @@ private:
   bool IsFreeFormComment(const char *) const;
   std::optional<std::size_t> IsIncludeLine(const char *) const;
   void FortranInclude(const char *quote);
-  bool IsPreprocessorDirectiveLine(const char *) const;
+  const char *IsPreprocessorDirectiveLine(const char *) const;
   const char *FixedFormContinuationLine();
   bool FixedFormContinuation();
   bool FreeFormContinuation();