[flang-commits] [flang] [flang] Accept C-style comments in label fields (PR #207012)

Leandro Lupori via flang-commits flang-commits at lists.llvm.org
Fri Sep 18 11:13:56 PDT 2026


https://github.com/luporl updated https://github.com/llvm/llvm-project/pull/207012

>From 08ecad840aea161892c6b22ebf9abda0453eb209 Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Mon, 29 Jun 2026 19:35:59 -0300
Subject: [PATCH 01/14] [flang] Accept C-style comments in label fields

The main goal of this patch is to make multi-language header files
easier to write and use in fixed format sources. For this reason, and
for simplicity, C-style comments after labels, directives and OpenMP
conditional compilation sentinels are not supported.

Fixes #127426
---
 flang/lib/Parser/prescan.cpp               | 117 ++++++++++++++-------
 flang/test/Preprocessing/fixed-c-comment.F |  62 +++++++++++
 2 files changed, 141 insertions(+), 38 deletions(-)
 create mode 100644 flang/test/Preprocessing/fixed-c-comment.F

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index db4b50a4920028..24a0f72df5a127 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -70,6 +70,15 @@ static inline constexpr bool IsFixedFormCommentChar(char ch) {
   return ch == '!' || ch == '*' || ch == 'C' || ch == 'c';
 }
 
+static bool HasTabInLabelField(const char *col1) {
+  for (int i{0}; i < 6; ++i) {
+    if (col1[i] == '\t') {
+      return true;
+    }
+  }
+  return false;
+}
+
 static void NormalizeCompilerDirectiveCommentMarker(TokenSequence &dir) {
   char *p{dir.GetMutableCharData()};
   char *limit{p + dir.SizeInChars()};
@@ -436,6 +445,30 @@ void Prescanner::LabelField(TokenSequence &token) {
   int colOffset{column_ - 1};
   const char *start{at_};
   std::optional<int> badColumn;
+
+  // Skip C-style comments.
+  const char *p{SkipWhiteSpace(start)};
+  long spaces{HasTabInLabelField(start - colOffset) ? 6 : p - start};
+  if (spaces < 6 && IsCComment(p)) {
+    at_ += spaces;
+    column_ += spaces;
+    if (features_.ShouldWarn(LanguageFeature::ClassicCComments)) {
+      Say(LanguageFeature::ClassicCComments, GetCurrentProvenance(),
+          "nonstandard usage: C-style comment"_port_en_US);
+    }
+    SkipCComments();
+    // Fix `column_`, which may be incorrect after multi-line comments.
+    p = at_ - 1;
+    while (p > start && *p != '\n') {
+      --p;
+    }
+    if (*p == '\n') {
+      column_ = at_ - p;
+    }
+    colOffset = column_ - 1;
+    start = at_;
+  }
+
   for (; *at_ != '\n' && column_ <= 6; ++at_) {
     if (*at_ == '\t') {
       ++at_;
@@ -766,39 +799,39 @@ void Prescanner::UpdateSourcePositionAfterSkip(const char *after) {
 
 bool Prescanner::NextToken(TokenSequence &tokens) {
   CHECK(at_ >= start_ && at_ < limit_);
-  if (InFixedFormSource() && !preprocessingOnly_) {
+  bool compilingFixedForm{InFixedFormSource() && !preprocessingOnly_};
+  if (compilingFixedForm) {
     SkipSpaces();
-  } else {
-    if (*at_ == '/' && IsCComment(at_)) {
-      // Recognize and skip over classic C style /*comments*/ when
-      // outside a character literal.
-      WarnCComment(at_);
-      SkipCComments();
-    }
-    if (IsSpaceOrTab(at_)) {
-      // Compress free-form white space into a single space character.
-      const auto theSpace{at_};
-      char previous{at_ <= start_ ? ' ' : at_[-1]};
-      NextChar();
-      SkipSpaces();
-      if (*at_ == '\n' && !omitNewline_) {
-        // Discard white space at the end of a line.
-      } else if (!inPreprocessorDirective_ &&
-          (previous == '(' || *at_ == '(' || *at_ == ')')) {
-        // Discard white space before/after '(' and before ')', unless in a
-        // preprocessor directive.  This helps yield space-free contiguous
-        // names for generic interfaces like OPERATOR( + ) and
-        // READ ( UNFORMATTED ), without misinterpreting #define f (notAnArg).
-        // This has the effect of silently ignoring the illegal spaces in
-        // the array constructor ( /1,2/ ) but that seems benign; it's
-        // hard to avoid that while still removing spaces from OPERATOR( / )
-        // and OPERATOR( // ).
-      } else {
-        // Preserve the squashed white space as a single space character.
-        tokens.PutNextTokenChar(' ', GetProvenance(theSpace));
-        tokens.CloseToken();
-        return true;
-      }
+  }
+  if (*at_ == '/' && IsCComment(at_)) {
+    // Recognize and skip over classic C style /*comments*/ when
+    // outside a character literal.
+    WarnCComment(at_);
+    SkipCComments();
+  }
+  if (!compilingFixedForm && IsSpaceOrTab(at_)) {
+    // Compress free-form white space into a single space character.
+    const auto theSpace{at_};
+    char previous{at_ <= start_ ? ' ' : at_[-1]};
+    NextChar();
+    SkipSpaces();
+    if (*at_ == '\n' && !omitNewline_) {
+      // Discard white space at the end of a line.
+    } else if (!inPreprocessorDirective_ &&
+        (previous == '(' || *at_ == '(' || *at_ == ')')) {
+      // Discard white space before/after '(' and before ')', unless in a
+      // preprocessor directive.  This helps yield space-free contiguous
+      // names for generic interfaces like OPERATOR( + ) and
+      // READ ( UNFORMATTED ), without misinterpreting #define f (notAnArg).
+      // This has the effect of silently ignoring the illegal spaces in
+      // the array constructor ( /1,2/ ) but that seems benign; it's
+      // hard to avoid that while still removing spaces from OPERATOR( / )
+      // and OPERATOR( // ).
+    } else {
+      // Preserve the squashed white space as a single space character.
+      tokens.PutNextTokenChar(' ', GetProvenance(theSpace));
+      tokens.CloseToken();
+      return true;
     }
   }
   brokenToken_ = false;
@@ -1430,12 +1463,19 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
   }
   tabInCurrentLine_ = false;
   char col1{*nextLine_};
+  int trailingSpaces{0};
+  for (int i{4}; i > 0 && nextLine_[i] == ' '; --i) {
+    ++trailingSpaces;
+  }
+  bool CCommentAndSpaces{!HasTabInLabelField(nextLine_) &&
+      SkipCComment(SkipWhiteSpace(nextLine_)) - nextLine_ + trailingSpaces ==
+          5};
   bool canBeNonDirectiveContinuation{
-      (col1 == ' ' ||
-          ((col1 == 'D' || col1 == 'd') &&
-              features_.IsEnabled(LanguageFeature::OldDebugLines))) &&
-      nextLine_[1] == ' ' && nextLine_[2] == ' ' && nextLine_[3] == ' ' &&
-      nextLine_[4] == ' '};
+      ((col1 == ' ' ||
+           ((col1 == 'D' || col1 == 'd') &&
+               features_.IsEnabled(LanguageFeature::OldDebugLines))) &&
+          trailingSpaces == 4) ||
+      CCommentAndSpaces};
   if (InCompilerDirective() && !(InConditionalLine() && !preprocessingOnly_)) {
     // !$ under -E is not continued, but deferred to later compilation
     if (IsFixedFormCommentChar(col1) &&
@@ -1499,7 +1539,8 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
     }
     if (canBeNonDirectiveContinuation) {
       const char *col6{nextLine_ + 5};
-      if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
+      if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6) &&
+          !IsCComment(col6)) {
         if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) {
           // It's an INCLUDE line, not a continuation
         } else {
diff --git a/flang/test/Preprocessing/fixed-c-comment.F b/flang/test/Preprocessing/fixed-c-comment.F
new file mode 100644
index 00000000000000..82db6f7b43fa0e
--- /dev/null
+++ b/flang/test/Preprocessing/fixed-c-comment.F
@@ -0,0 +1,62 @@
+! RUN: %flang_fc1 -fsyntax-only %s 2>&1
+! RUN: %flang -E %s 2>&1 | FileCheck %s
+! RUN: not %flang_fc1 -pedantic -Werror -fdebug-dump-parse-tree-no-sema %s 2>&1 | FileCheck %s --check-prefix=ERROR
+
+      integer :: i
+
+! CHECK-NOT: C comment
+! CHECK: i = 1
+! ERROR: portability: nonstandard usage: C-style comment
+/* Old style C comments
+ *comments
+ */
+#define VAL 1
+
+! ERROR: portability: nonstandard usage: C-style comment
+/* Single-line C comment */
+ /* Single-line C comment */
+  /* Single-line C comment */
+   /* Single-line C comment */
+    /* Single-line C comment */
+     /* Single-line C comment */
+      /* Single-line C comment */
+       /* Single-line C comment */
+      i = VAL
+
+! CHECK-NOT: /*
+! CHECK-NOT: Multi
+! CHECK-NOT: C comment
+! CHECK-NOT: */
+! CHECK: i = 2
+/*
+ * Multi-line C comment
+ * comment
+ */
+  /* Multi-line
+C comment */
+      i = 2
+
+! CHECK: i = 3
+! CHECK: i = 4
+! CHECK: 9 i = 5+ 6
+/* C comment + statement */ i = 3
+      /* C comment + statement */ i = 4
+/**/90i = 5
+/**/ + + 6
+
+! CHECK-NOT: /*
+! CHECK-NOT: C comment
+! CHECK-NOT: */
+! CHECK: 100 i = 7
+/* Multi-line C comment + statement
+*/100 i = 7
+
+! CHECK: i = 8
+! CHECK-NOT: C comment
+      i = 8 /* C comment after statement */
+
+! CHECK: print
+! CHECK-NOT: C comment
+	print *, "TAB"
+	/* C comment after tab */
+      end

>From 02c6085727ae4cc51828628b54363edda9e79f5d Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Wed, 1 Jul 2026 17:05:34 +0000
Subject: [PATCH 02/14] Fix Windows build

---
 flang/lib/Parser/prescan.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 24a0f72df5a127..ed314acef43a33 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -448,7 +448,8 @@ void Prescanner::LabelField(TokenSequence &token) {
 
   // Skip C-style comments.
   const char *p{SkipWhiteSpace(start)};
-  long spaces{HasTabInLabelField(start - colOffset) ? 6 : p - start};
+  int spaces{
+      HasTabInLabelField(start - colOffset) ? 6 : static_cast<int>(p - start)};
   if (spaces < 6 && IsCComment(p)) {
     at_ += spaces;
     column_ += spaces;

>From 03062a666ff7e676be559665cdfe0d66612cae45 Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Thu, 2 Jul 2026 17:40:31 -0300
Subject: [PATCH 03/14] Address review's comments

---
 flang/lib/Parser/prescan.cpp               | 8 ++++----
 flang/test/Preprocessing/fixed-c-comment.F | 8 +++++++-
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index ed314acef43a33..4814071f4d9f95 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -71,7 +71,7 @@ static inline constexpr bool IsFixedFormCommentChar(char ch) {
 }
 
 static bool HasTabInLabelField(const char *col1) {
-  for (int i{0}; i < 6; ++i) {
+  for (int i{0}; i < 6 && col1[i] != '\n'; ++i) {
     if (col1[i] == '\t') {
       return true;
     }
@@ -1468,9 +1468,9 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
   for (int i{4}; i > 0 && nextLine_[i] == ' '; --i) {
     ++trailingSpaces;
   }
-  bool CCommentAndSpaces{!HasTabInLabelField(nextLine_) &&
-      SkipCComment(SkipWhiteSpace(nextLine_)) - nextLine_ + trailingSpaces ==
-          5};
+  const char *afterCComment{SkipCComment(SkipWhiteSpace(nextLine_))};
+  bool CCommentAndSpaces{!HasTabInLabelField(nextLine_) && afterCComment &&
+      afterCComment - nextLine_ + trailingSpaces == 5};
   bool canBeNonDirectiveContinuation{
       ((col1 == ' ' ||
            ((col1 == 'D' || col1 == 'd') &&
diff --git a/flang/test/Preprocessing/fixed-c-comment.F b/flang/test/Preprocessing/fixed-c-comment.F
index 82db6f7b43fa0e..1d00528804e7e4 100644
--- a/flang/test/Preprocessing/fixed-c-comment.F
+++ b/flang/test/Preprocessing/fixed-c-comment.F
@@ -1,6 +1,7 @@
 ! RUN: %flang_fc1 -fsyntax-only %s 2>&1
 ! RUN: %flang -E %s 2>&1 | FileCheck %s
-! RUN: not %flang_fc1 -pedantic -Werror -fdebug-dump-parse-tree-no-sema %s 2>&1 | FileCheck %s --check-prefix=ERROR
+! RUN: not %flang_fc1 -pedantic -Werror -fdebug-dump-parse-tree-no-sema \
+! RUN:        -DTEST_ERRORS=1 %s 2>&1 | FileCheck %s --check-prefix=ERROR
 
       integer :: i
 
@@ -59,4 +60,9 @@
 ! CHECK-NOT: C comment
 	print *, "TAB"
 	/* C comment after tab */
+
+! ERROR: error: Character in fixed-form label field must be a digit
+#if TEST_ERRORS
+/* Not-terminated C comment
+#endif
       end

>From 67063aa210545e30628155de1149589ed341839d Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Fri, 3 Jul 2026 10:52:18 -0300
Subject: [PATCH 04/14] Fix regression and improve efficiency

---
 flang/lib/Parser/prescan.cpp               | 8 +++++---
 flang/test/Preprocessing/fixed-c-comment.F | 5 +++++
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 4814071f4d9f95..966f91a8ea54af 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -1468,15 +1468,17 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
   for (int i{4}; i > 0 && nextLine_[i] == ' '; --i) {
     ++trailingSpaces;
   }
-  const char *afterCComment{SkipCComment(SkipWhiteSpace(nextLine_))};
-  bool CCommentAndSpaces{!HasTabInLabelField(nextLine_) && afterCComment &&
+  const char *afterWhiteSpace{SkipWhiteSpace(nextLine_)};
+  const char *afterCComment{
+      IsCComment(afterWhiteSpace) ? SkipCComment(afterWhiteSpace) : nullptr};
+  bool cCommentAndSpaces{afterCComment && !HasTabInLabelField(nextLine_) &&
       afterCComment - nextLine_ + trailingSpaces == 5};
   bool canBeNonDirectiveContinuation{
       ((col1 == ' ' ||
            ((col1 == 'D' || col1 == 'd') &&
                features_.IsEnabled(LanguageFeature::OldDebugLines))) &&
           trailingSpaces == 4) ||
-      CCommentAndSpaces};
+      cCommentAndSpaces};
   if (InCompilerDirective() && !(InConditionalLine() && !preprocessingOnly_)) {
     // !$ under -E is not continued, but deferred to later compilation
     if (IsFixedFormCommentChar(col1) &&
diff --git a/flang/test/Preprocessing/fixed-c-comment.F b/flang/test/Preprocessing/fixed-c-comment.F
index 1d00528804e7e4..97ad59dd54546a 100644
--- a/flang/test/Preprocessing/fixed-c-comment.F
+++ b/flang/test/Preprocessing/fixed-c-comment.F
@@ -56,6 +56,11 @@
 ! CHECK-NOT: C comment
       i = 8 /* C comment after statement */
 
+! CHECK: i = 9
+! CHECK-NOT: 8
+      i = 9
+* */ 88
+
 ! CHECK: print
 ! CHECK-NOT: C comment
 	print *, "TAB"

>From 426699b410f25b47995e2cb0c8d915b3075f804f Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Wed, 8 Jul 2026 14:29:10 -0300
Subject: [PATCH 05/14] Fix out of bounds read

---
 flang/lib/Parser/prescan.cpp | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 966f91a8ea54af..f4664bf70466c2 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -70,8 +70,10 @@ static inline constexpr bool IsFixedFormCommentChar(char ch) {
   return ch == '!' || ch == '*' || ch == 'C' || ch == 'c';
 }
 
-static bool HasTabInLabelField(const char *col1) {
-  for (int i{0}; i < 6 && col1[i] != '\n'; ++i) {
+static bool HasTabInLabelField(const char *col1, const char *limit) {
+  std::uint64_t len{static_cast<std::uint64_t>(limit - col1)};
+  int n{len < 6 ? static_cast<int>(len) : 6};
+  for (int i{0}; i < n && col1[i] != '\n'; ++i) {
     if (col1[i] == '\t') {
       return true;
     }
@@ -448,8 +450,9 @@ void Prescanner::LabelField(TokenSequence &token) {
 
   // Skip C-style comments.
   const char *p{SkipWhiteSpace(start)};
-  int spaces{
-      HasTabInLabelField(start - colOffset) ? 6 : static_cast<int>(p - start)};
+  std::uint64_t spaces{HasTabInLabelField(start - colOffset, limit_)
+          ? 6
+          : static_cast<std::uint64_t>(p - start)};
   if (spaces < 6 && IsCComment(p)) {
     at_ += spaces;
     column_ += spaces;
@@ -1464,15 +1467,18 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
   }
   tabInCurrentLine_ = false;
   char col1{*nextLine_};
-  int trailingSpaces{0};
-  for (int i{4}; i > 0 && nextLine_[i] == ' '; --i) {
-    ++trailingSpaces;
-  }
   const char *afterWhiteSpace{SkipWhiteSpace(nextLine_)};
   const char *afterCComment{
       IsCComment(afterWhiteSpace) ? SkipCComment(afterWhiteSpace) : nullptr};
-  bool cCommentAndSpaces{afterCComment && !HasTabInLabelField(nextLine_) &&
-      afterCComment - nextLine_ + trailingSpaces == 5};
+  int trailingSpaces{0};
+  for (std::uint64_t i{afterCComment
+               ? static_cast<std::uint64_t>(afterCComment - nextLine_)
+               : 1};
+      i <= 4 && nextLine_[i] == ' '; ++i) {
+    ++trailingSpaces;
+  }
+  bool cCommentAndSpaces{
+      afterCComment && afterCComment - nextLine_ + trailingSpaces == 5};
   bool canBeNonDirectiveContinuation{
       ((col1 == ' ' ||
            ((col1 == 'D' || col1 == 'd') &&

>From 900f4326dee860706847a1a5b4b871f785238c4a Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Wed, 8 Jul 2026 18:01:05 -0300
Subject: [PATCH 06/14] Avoid out of bounds reads when determining
 trailingSpaces

---
 flang/lib/Parser/prescan.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index f4664bf70466c2..bc93292e9dce24 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -1470,11 +1470,13 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
   const char *afterWhiteSpace{SkipWhiteSpace(nextLine_)};
   const char *afterCComment{
       IsCComment(afterWhiteSpace) ? SkipCComment(afterWhiteSpace) : nullptr};
+  std::uint64_t maxLineLength{static_cast<std::uint64_t>(limit_ - nextLine_)};
+  std::uint64_t n{maxLineLength < 5 ? maxLineLength - 1 : 4};
   int trailingSpaces{0};
   for (std::uint64_t i{afterCComment
                ? static_cast<std::uint64_t>(afterCComment - nextLine_)
                : 1};
-      i <= 4 && nextLine_[i] == ' '; ++i) {
+      i <= n && nextLine_[i] == ' '; ++i) {
     ++trailingSpaces;
   }
   bool cCommentAndSpaces{

>From f9937c28891a48763156dff2bfd821ebd0406af8 Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Tue, 14 Jul 2026 16:25:18 -0300
Subject: [PATCH 07/14] Fix issues from last review

---
 flang/lib/Parser/prescan.cpp               | 36 +++++++++++++---------
 flang/test/Preprocessing/fixed-c-comment.F | 13 ++++++--
 2 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index bc93292e9dce24..b4d6e9bfb313a5 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -456,21 +456,23 @@ void Prescanner::LabelField(TokenSequence &token) {
   if (spaces < 6 && IsCComment(p)) {
     at_ += spaces;
     column_ += spaces;
-    if (features_.ShouldWarn(LanguageFeature::ClassicCComments)) {
-      Say(LanguageFeature::ClassicCComments, GetCurrentProvenance(),
-          "nonstandard usage: C-style comment"_port_en_US);
-    }
     SkipCComments();
-    // Fix `column_`, which may be incorrect after multi-line comments.
-    p = at_ - 1;
-    while (p > start && *p != '\n') {
-      --p;
-    }
-    if (*p == '\n') {
-      column_ = at_ - p;
+    if (at_ > start + spaces) {
+      if (features_.ShouldWarn(LanguageFeature::ClassicCComments)) {
+        Say(LanguageFeature::ClassicCComments, GetCurrentProvenance(),
+            "nonstandard usage: C-style comment"_port_en_US);
+      }
+      // Fix `column_`, which may be incorrect after multi-line comments.
+      p = at_ - 1;
+      while (p > start && *p != '\n') {
+        --p;
+      }
+      if (*p == '\n') {
+        column_ = at_ - p;
+      }
+      colOffset = column_ - 1;
+      start = at_;
     }
-    colOffset = column_ - 1;
-    start = at_;
   }
 
   for (; *at_ != '\n' && column_ <= 6; ++at_) {
@@ -812,6 +814,9 @@ bool Prescanner::NextToken(TokenSequence &tokens) {
     // outside a character literal.
     WarnCComment(at_);
     SkipCComments();
+    if (compilingFixedForm) {
+      SkipSpaces();
+    }
   }
   if (!compilingFixedForm && IsSpaceOrTab(at_)) {
     // Compress free-form white space into a single space character.
@@ -1479,8 +1484,9 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
       i <= n && nextLine_[i] == ' '; ++i) {
     ++trailingSpaces;
   }
-  bool cCommentAndSpaces{
-      afterCComment && afterCComment - nextLine_ + trailingSpaces == 5};
+  bool cCommentAndSpaces{afterCComment &&
+      afterCComment - nextLine_ + trailingSpaces == 5 &&
+      std::memchr(nextLine_, '\n', n + 1) == nullptr};
   bool canBeNonDirectiveContinuation{
       ((col1 == ' ' ||
            ((col1 == 'D' || col1 == 'd') &&
diff --git a/flang/test/Preprocessing/fixed-c-comment.F b/flang/test/Preprocessing/fixed-c-comment.F
index 97ad59dd54546a..f4bb91fe92fb66 100644
--- a/flang/test/Preprocessing/fixed-c-comment.F
+++ b/flang/test/Preprocessing/fixed-c-comment.F
@@ -3,7 +3,8 @@
 ! RUN: not %flang_fc1 -pedantic -Werror -fdebug-dump-parse-tree-no-sema \
 ! RUN:        -DTEST_ERRORS=1 %s 2>&1 | FileCheck %s --check-prefix=ERROR
 
-      integer :: i
+      implicit none
+      integer :: i, foobar
 
 ! CHECK-NOT: C comment
 ! CHECK: i = 1
@@ -61,13 +62,21 @@
       i = 9
 * */ 88
 
+! When compiling, the line below should become: foobar = 123
+      foo/* c */ bar = 123
+
 ! CHECK: print
 ! CHECK-NOT: C comment
 	print *, "TAB"
 	/* C comment after tab */
 
-! ERROR: error: Character in fixed-form label field must be a digit
 #if TEST_ERRORS
+! ERROR: error: Character in fixed-form label field must be a digit
+      i = 90
+/*
+*/+1
+
+! ERROR: error: Character in fixed-form label field must be a digit
 /* Not-terminated C comment
 #endif
       end

>From 8d1af78dcccf99d2d164109fd2e92eef9b6a14d6 Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Tue, 21 Jul 2026 18:11:58 +0000
Subject: [PATCH 08/14] Check for not-terminated C comments in continuation
 lines

---
 flang/lib/Parser/prescan.cpp               | 2 +-
 flang/test/Preprocessing/fixed-c-comment.F | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index b4d6e9bfb313a5..dd0706fba4bee7 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -1557,7 +1557,7 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
     if (canBeNonDirectiveContinuation) {
       const char *col6{nextLine_ + 5};
       if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6) &&
-          !IsCComment(col6)) {
+          !(IsCComment(col6) && afterCComment > afterWhiteSpace)) {
         if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) {
           // It's an INCLUDE line, not a continuation
         } else {
diff --git a/flang/test/Preprocessing/fixed-c-comment.F b/flang/test/Preprocessing/fixed-c-comment.F
index f4bb91fe92fb66..2c0c35dad718c9 100644
--- a/flang/test/Preprocessing/fixed-c-comment.F
+++ b/flang/test/Preprocessing/fixed-c-comment.F
@@ -79,4 +79,8 @@
 ! ERROR: error: Character in fixed-form label field must be a digit
 /* Not-terminated C comment
 #endif
+
+! CHECK: i = 10* 2
+      i = 10
+     /* 2
       end

>From d32c12f35943d43890dca19bf3f0a84c8cc146af Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Wed, 22 Jul 2026 20:37:24 +0000
Subject: [PATCH 09/14] Fix check for not-terminated C comments in continuation
 lines

---
 flang/lib/Parser/prescan.cpp               |  2 +-
 flang/test/Preprocessing/fixed-c-comment.F | 11 ++++++++---
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index dd0706fba4bee7..7247ad72751da6 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -1557,7 +1557,7 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
     if (canBeNonDirectiveContinuation) {
       const char *col6{nextLine_ + 5};
       if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6) &&
-          !(IsCComment(col6) && afterCComment > afterWhiteSpace)) {
+          !(IsCComment(col6) && SkipCComment(col6) > col6)) {
         if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) {
           // It's an INCLUDE line, not a continuation
         } else {
diff --git a/flang/test/Preprocessing/fixed-c-comment.F b/flang/test/Preprocessing/fixed-c-comment.F
index 2c0c35dad718c9..4ba307dd707e5d 100644
--- a/flang/test/Preprocessing/fixed-c-comment.F
+++ b/flang/test/Preprocessing/fixed-c-comment.F
@@ -75,12 +75,17 @@
       i = 90
 /*
 */+1
-
-! ERROR: error: Character in fixed-form label field must be a digit
-/* Not-terminated C comment
 #endif
 
+! CHECK: i = 10* 2
+      i = 10
+/**/ /* 2
 ! CHECK: i = 10* 2
       i = 10
      /* 2
+
+#if TEST_ERRORS
+! ERROR: error: Character in fixed-form label field must be a digit
+/* Not-terminated C comment
+#endif
       end

>From 45982d0587c12372d8fe0c27b80c18af3a9f2e66 Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Wed, 22 Jul 2026 22:04:29 +0000
Subject: [PATCH 10/14] Document possible issues with the C-style comments
 extension

---
 flang/docs/Extensions.md | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 2a0afbb0cd3c01..b1f7cc2faa27fd 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -277,6 +277,20 @@ end
   need not begin with a comment marker (!).
 * Classic C-style `/*comments*/` are skipped, so multi-language header
   files are easier to write and use.
+* Classic C-style `/*comments*/` can cause an otherwise valid Fortran program
+  to be rejected. For example:
+```fortran
+      write(*,10) n, n+1, n+2
+   10 format(1x,i2/*(i3))
+      print *, 'tail */'
+```
+  The last two lines become `10 format(1x,i2'` after prescan. This issue can
+  be avoided by not omitting the commas around the first slash, as in:
+```fortran
+      write(*,10) n, n+1, n+2
+   10 format(1x,i2,/,*(i3))
+      print *, 'tail */'
+```
 * $ and \ edit descriptors are supported in FORMAT to suppress newline
   output on user prompts.
 * Tabs in format strings (not `FORMAT` statements) are allowed on output.

>From 3d1535d99ee9138ed636927b61e21c3e1e9b286e Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Fri, 4 Sep 2026 15:34:52 -0300
Subject: [PATCH 11/14] Parse C-style comments for label fields only when
 preprocessing is enabled

TODO:
- Add more tests
- Update flang/docs/Extensions.md

Assisted-by: Claude Opus 5
---
 flang/include/flang/Parser/options.h          |   1 +
 flang/lib/Frontend/FrontendAction.cpp         |   7 +-
 flang/lib/Parser/parsing.cpp                  |   1 +
 flang/lib/Parser/prescan.cpp                  | 114 ++++++++++++------
 flang/lib/Parser/prescan.h                    |  10 +-
 ...{fixed-c-comment.F => fixed-c-comment01.F} |  23 ----
 flang/test/Preprocessing/fixed-c-comment02.F  |  29 +++++
 flang/tools/bbc/bbc.cpp                       |   1 +
 8 files changed, 121 insertions(+), 65 deletions(-)
 rename flang/test/Preprocessing/{fixed-c-comment.F => fixed-c-comment01.F} (68%)
 create mode 100644 flang/test/Preprocessing/fixed-c-comment02.F

diff --git a/flang/include/flang/Parser/options.h b/flang/include/flang/Parser/options.h
index e65f253748d26f..e5bb515419c3b0 100644
--- a/flang/include/flang/Parser/options.h
+++ b/flang/include/flang/Parser/options.h
@@ -34,6 +34,7 @@ struct Options {
   bool needProvenanceRangeToCharBlockMappings{false};
   Fortran::parser::Encoding encoding{Fortran::parser::Encoding::UTF_8};
   bool prescanAndReformat{false}; // -E
+  bool preprocessingEnabled{false};
   bool expandIncludeLinesInPreprocessedOutput{true};
   bool showColors{false};
   std::vector<std::string> compilerDirectiveSentinels;
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index a385e639a6d679..f1e5eb27867048 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -83,13 +83,16 @@ bool FrontendAction::beginSourceFile(CompilerInstance &ci,
   //  * `-cpp/-nocpp`, or
   //  * the file extension (if the user didn't express any preference)
   // to decide whether to include them or not.
-  if ((invoc.getPreprocessorOpts().macrosFlag == PPMacrosFlag::Include) ||
+  bool preprocessingEnabled =
+      (invoc.getPreprocessorOpts().macrosFlag == PPMacrosFlag::Include) ||
       (invoc.getPreprocessorOpts().showMacros) ||
       (invoc.getPreprocessorOpts().macrosFlag == PPMacrosFlag::Unknown &&
-       getCurrentInput().getMustBePreprocessed())) {
+       getCurrentInput().getMustBePreprocessed());
+  if (preprocessingEnabled) {
     invoc.setDefaultPredefinitions();
     invoc.collectMacroDefinitions();
   }
+  invoc.getFortranOpts().preprocessingEnabled = preprocessingEnabled;
 
   if (!invoc.getFortranOpts().features.IsEnabled(
           Fortran::common::LanguageFeature::CUDA)) {
diff --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp
index 6dc38dc8cfd8da..391416c8ba25b4 100644
--- a/flang/lib/Parser/parsing.cpp
+++ b/flang/lib/Parser/parsing.cpp
@@ -75,6 +75,7 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
       messages_, *currentCooked_, preprocessor_, options.features};
   prescanner.set_fixedForm(options.isFixedForm)
       .set_fixedFormColumnLimit(options.fixedFormColumns)
+      .set_preprocessingEnabled(options.preprocessingEnabled)
       .set_preprocessingOnly(options.prescanAndReformat)
       .set_expandIncludeLines(!options.prescanAndReformat ||
           options.expandIncludeLinesInPreprocessedOutput)
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 7247ad72751da6..ade5979f34a900 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -35,6 +35,7 @@ Prescanner::Prescanner(const Prescanner &that, Preprocessor &prepro,
     bool isNestedInIncludeDirective)
     : messages_{that.messages_}, cooked_{that.cooked_}, preprocessor_{prepro},
       allSources_{that.allSources_}, features_{that.features_},
+      preprocessingEnabled_{that.preprocessingEnabled_},
       preprocessingOnly_{that.preprocessingOnly_},
       expandIncludeLines_{that.expandIncludeLines_},
       isNestedInIncludeDirective_{isNestedInIncludeDirective},
@@ -449,29 +450,28 @@ void Prescanner::LabelField(TokenSequence &token) {
   std::optional<int> badColumn;
 
   // Skip C-style comments.
-  const char *p{SkipWhiteSpace(start)};
-  std::uint64_t spaces{HasTabInLabelField(start - colOffset, limit_)
-          ? 6
-          : static_cast<std::uint64_t>(p - start)};
-  if (spaces < 6 && IsCComment(p)) {
-    at_ += spaces;
-    column_ += spaces;
-    SkipCComments();
-    if (at_ > start + spaces) {
-      if (features_.ShouldWarn(LanguageFeature::ClassicCComments)) {
-        Say(LanguageFeature::ClassicCComments, GetCurrentProvenance(),
-            "nonstandard usage: C-style comment"_port_en_US);
-      }
-      // Fix `column_`, which may be incorrect after multi-line comments.
-      p = at_ - 1;
-      while (p > start && *p != '\n') {
-        --p;
-      }
-      if (*p == '\n') {
-        column_ = at_ - p;
+  if (preprocessingEnabled_) {
+    const char *p{SkipWhiteSpace(start)};
+    std::uint64_t spaces{HasTabInLabelField(start - colOffset, limit_)
+            ? 6
+            : static_cast<std::uint64_t>(p - start)};
+    if (spaces < 6 && IsCComment(p)) {
+      at_ += spaces;
+      column_ += spaces;
+      SkipCComments(/*noError=*/false);
+      if (at_ > start + spaces) {
+        WarnCComment(p);
+        // Fix `column_`, which may be incorrect after multi-line comments.
+        p = at_ - 1;
+        while (p > start && *p != '\n') {
+          --p;
+        }
+        if (*p == '\n') {
+          column_ = at_ - p;
+        }
+        colOffset = column_ - 1;
+        start = at_;
       }
-      colOffset = column_ - 1;
-      start = at_;
     }
   }
 
@@ -641,7 +641,7 @@ void Prescanner::NextChar() {
 // fixed form, and all forms of line continuation.
 bool Prescanner::SkipToNextSignificantCharacter() {
   if (inPreprocessorDirective_) {
-    SkipCComments();
+    SkipCComments(/*noError=*/true);
     return false;
   } else {
     auto anyContinuationLine{false};
@@ -665,15 +665,22 @@ bool Prescanner::SkipToNextSignificantCharacter() {
   }
 }
 
-void Prescanner::SkipCComments() {
+void Prescanner::SkipCComments(bool noError) {
   while (true) {
     if (IsCComment(at_)) {
       if (const char *after{SkipCComment(at_)}) {
         UpdateSourcePositionAfterSkip(after);
       } else {
-        // Don't emit any messages about unclosed C-style comments, because
-        // the sequence /* can appear legally in a FORMAT statement.  There's
-        // no ambiguity, since the sequence */ cannot appear legally.
+        // Error messages for unterminated C-style comments should be emitted
+        // only when preprocessing is enabled, since the sequence /* can
+        // appear legally in a FORMAT statement.
+        // At the moment, errors are emitted only for some code paths, such as
+        // when processing label fields, while others keep the old behavior of
+        // ignoring unterminated C-style comments.
+        // TODO Always emit an error when preprocessing is enabled.
+        if (preprocessingEnabled_ && !noError) {
+          Say(GetProvenance(at_), "unterminated C-style comment"_err_en_US);
+        }
         break;
       }
     } else if (inPreprocessorDirective_ && at_[0] == '\\' && at_ + 2 < limit_ &&
@@ -813,7 +820,7 @@ bool Prescanner::NextToken(TokenSequence &tokens) {
     // Recognize and skip over classic C style /*comments*/ when
     // outside a character literal.
     WarnCComment(at_);
-    SkipCComments();
+    SkipCComments(/*noError=*/true);
     if (compilingFixedForm) {
       SkipSpaces();
     }
@@ -1466,15 +1473,25 @@ bool Prescanner::SkipCommentLine(bool afterAmpersand) {
   return false;
 }
 
-const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
+const char *Prescanner::FixedFormContinuationLine(
+    bool atNewline, const char *&cComment, const char *&unterminatedCComment) {
+  cComment = nullptr;
+  unterminatedCComment = nullptr;
   if (IsAtEnd()) {
     return nullptr;
   }
   tabInCurrentLine_ = false;
   char col1{*nextLine_};
   const char *afterWhiteSpace{SkipWhiteSpace(nextLine_)};
-  const char *afterCComment{
-      IsCComment(afterWhiteSpace) ? SkipCComment(afterWhiteSpace) : nullptr};
+  const char *afterCComment{nullptr};
+  if (preprocessingEnabled_ && IsCComment(afterWhiteSpace)) {
+    afterCComment = SkipCComment(afterWhiteSpace);
+    if (afterCComment == nullptr) {
+      unterminatedCComment = afterWhiteSpace;
+    } else {
+      cComment = afterWhiteSpace;
+    }
+  }
   std::uint64_t maxLineLength{static_cast<std::uint64_t>(limit_ - nextLine_)};
   std::uint64_t n{maxLineLength < 5 ? maxLineLength - 1 : 4};
   int trailingSpaces{0};
@@ -1556,12 +1573,23 @@ const char *Prescanner::FixedFormContinuationLine(bool atNewline) {
     }
     if (canBeNonDirectiveContinuation) {
       const char *col6{nextLine_ + 5};
-      if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6) &&
-          !(IsCComment(col6) && SkipCComment(col6) > col6)) {
-        if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) {
-          // It's an INCLUDE line, not a continuation
-        } else {
-          return nextLine_ + 6;
+      if (*col6 != '\n' && *col6 != '0' && !IsSpaceOrTab(col6)) {
+        const char *afterCol6CComment{nullptr};
+        if (preprocessingEnabled_ && IsCComment(col6) &&
+            !unterminatedCComment) {
+          afterCol6CComment = SkipCComment(col6);
+          if (afterCol6CComment == nullptr) {
+            unterminatedCComment = col6;
+          } else if (!cComment) {
+            cComment = col6;
+          }
+        }
+        if (afterCol6CComment == nullptr) {
+          if ((*col6 == 'i' || *col6 == 'I') && IsIncludeLine(nextLine_)) {
+            // It's an INCLUDE line, not a continuation
+          } else {
+            return nextLine_ + 6;
+          }
         }
       }
     }
@@ -1691,7 +1719,17 @@ bool Prescanner::FixedFormContinuation(bool atNewline) {
     return false;
   }
   do {
-    if (const char *cont{FixedFormContinuationLine(atNewline)}) {
+    const char *cComment;
+    const char *unterminatedCComment;
+    if (const char *cont{FixedFormContinuationLine(
+            atNewline, cComment, unterminatedCComment)}) {
+      if (cComment) {
+        WarnCComment(cComment);
+      }
+      if (unterminatedCComment) {
+        Say(GetProvenance(unterminatedCComment),
+            "unterminated C-style comment"_err_en_US);
+      }
       BeginSourceLine(cont);
       column_ = 7;
       NextLine();
diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h
index 656b3c98b6c739..63b1f32d130811 100644
--- a/flang/lib/Parser/prescan.h
+++ b/flang/lib/Parser/prescan.h
@@ -48,6 +48,10 @@ class Prescanner {
   Preprocessor &preprocessor() { return preprocessor_; }
   common::LanguageFeatureControl &features() { return features_; }
 
+  Prescanner &set_preprocessingEnabled(bool yes) {
+    preprocessingEnabled_ = yes;
+    return *this;
+  }
   Prescanner &set_preprocessingOnly(bool yes) {
     preprocessingOnly_ = yes;
     return *this;
@@ -228,7 +232,7 @@ class Prescanner {
   void NextChar();
   // True when input flowed to a continuation line
   bool SkipToNextSignificantCharacter();
-  void SkipCComments();
+  void SkipCComments(bool noError);
   void WarnCComment(const char *at);
   void SkipSpaces();
   static const char *SkipWhiteSpace(const char *);
@@ -250,7 +254,8 @@ class Prescanner {
   std::optional<std::size_t> IsIncludeLine(const char *) const;
   void FortranInclude(const char *quote);
   const char *IsPreprocessorDirectiveLine(const char *) const;
-  const char *FixedFormContinuationLine(bool atNewline);
+  const char *FixedFormContinuationLine(
+      bool atNewline, const char *&cComment, const char *&unterminatedCComment);
   const char *GetFreeFormContinuationLine(bool ampersand, const char *p);
   const char *FreeFormContinuationLine(bool ampersand);
   bool IsImplicitContinuation() const;
@@ -275,6 +280,7 @@ class Prescanner {
   Preprocessor &preprocessor_;
   AllSources &allSources_;
   common::LanguageFeatureControl features_;
+  bool preprocessingEnabled_{false};
   bool preprocessingOnly_{false};
   bool expandIncludeLines_{true};
   bool isNestedInIncludeDirective_{false};
diff --git a/flang/test/Preprocessing/fixed-c-comment.F b/flang/test/Preprocessing/fixed-c-comment01.F
similarity index 68%
rename from flang/test/Preprocessing/fixed-c-comment.F
rename to flang/test/Preprocessing/fixed-c-comment01.F
index 4ba307dd707e5d..947d3a5fda42da 100644
--- a/flang/test/Preprocessing/fixed-c-comment.F
+++ b/flang/test/Preprocessing/fixed-c-comment01.F
@@ -1,20 +1,16 @@
 ! RUN: %flang_fc1 -fsyntax-only %s 2>&1
 ! RUN: %flang -E %s 2>&1 | FileCheck %s
-! RUN: not %flang_fc1 -pedantic -Werror -fdebug-dump-parse-tree-no-sema \
-! RUN:        -DTEST_ERRORS=1 %s 2>&1 | FileCheck %s --check-prefix=ERROR
 
       implicit none
       integer :: i, foobar
 
 ! CHECK-NOT: C comment
 ! CHECK: i = 1
-! ERROR: portability: nonstandard usage: C-style comment
 /* Old style C comments
  *comments
  */
 #define VAL 1
 
-! ERROR: portability: nonstandard usage: C-style comment
 /* Single-line C comment */
  /* Single-line C comment */
   /* Single-line C comment */
@@ -69,23 +65,4 @@
 ! CHECK-NOT: C comment
 	print *, "TAB"
 	/* C comment after tab */
-
-#if TEST_ERRORS
-! ERROR: error: Character in fixed-form label field must be a digit
-      i = 90
-/*
-*/+1
-#endif
-
-! CHECK: i = 10* 2
-      i = 10
-/**/ /* 2
-! CHECK: i = 10* 2
-      i = 10
-     /* 2
-
-#if TEST_ERRORS
-! ERROR: error: Character in fixed-form label field must be a digit
-/* Not-terminated C comment
-#endif
       end
diff --git a/flang/test/Preprocessing/fixed-c-comment02.F b/flang/test/Preprocessing/fixed-c-comment02.F
new file mode 100644
index 00000000000000..520a39bf66e64c
--- /dev/null
+++ b/flang/test/Preprocessing/fixed-c-comment02.F
@@ -0,0 +1,29 @@
+! RUN: not %flang_fc1 -fsyntax-only -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=ERROR
+
+      implicit none
+      integer :: i
+
+! ERROR: fixed-c-comment02.F:9:1: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:10:3: error: Character in fixed-form label field must be a digit
+      i = 11
+/*
+*/+1
+
+! ERROR: fixed-c-comment02.F:13:1: portability: nonstandard usage: C-style comment
+/* Single-line C comment */
+! ERROR: fixed-c-comment02.F:15:1: portability: nonstandard usage: C-style comment
+/* Multi-line
+ * C comment
+ */
+
+! ERROR: fixed-c-comment02.F:22:1: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:22:6: error: unterminated C-style comment
+      i = 21
+/**/ /* 2
+! ERROR: fixed-c-comment02.F:25:6: error: unterminated C-style comment
+      i = 22
+     /* 2
+! ERROR: fixed-c-comment02.F:29:1: error: unterminated C-style comment
+! ERROR: fixed-c-comment02.F:29:1: error: Character in fixed-form label field must be a digit
+! ERROR: fixed-c-comment02.F:29:1: portability: nonstandard usage: C-style comment
+/* Not-terminated C comment
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 50742eb1064216..7d0c0f6644a0d5 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -658,6 +658,7 @@ int main(int argc, char **argv) {
   }
 
   Fortran::parser::Options options;
+  options.preprocessingEnabled = true;
   options.predefinitions.emplace_back("__flang__"s, "1"s);
   options.predefinitions.emplace_back("__flang_major__"s,
                                       std::string{FLANG_VERSION_MAJOR_STRING});

>From 16dd953dccdf7f7d4749d89fc53cbb1c55002a31 Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Tue, 15 Sep 2026 16:43:37 -0300
Subject: [PATCH 12/14] Add more tests and update flang/docs/Extensions.md

---
 flang/docs/Extensions.md                     | 18 +++++----------
 flang/test/Preprocessing/fixed-c-comment02.F | 23 ++++++++++++++------
 flang/test/Preprocessing/fixed-c-comment03.f | 10 +++++++++
 3 files changed, 32 insertions(+), 19 deletions(-)
 create mode 100644 flang/test/Preprocessing/fixed-c-comment03.f

diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index b1f7cc2faa27fd..c1b088dca7c7de 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -277,19 +277,13 @@ end
   need not begin with a comment marker (!).
 * Classic C-style `/*comments*/` are skipped, so multi-language header
   files are easier to write and use.
-* Classic C-style `/*comments*/` can cause an otherwise valid Fortran program
-  to be rejected. For example:
+* Classic C-style `/*comments*/` in fixed source form label fields are
+  skipped only when preprocessing is enabled. Otherwise, valid Fortran
+  programs could be rejected. For example:
 ```fortran
-      write(*,10) n, n+1, n+2
-   10 format(1x,i2/*(i3))
-      print *, 'tail */'
-```
-  The last two lines become `10 format(1x,i2'` after prescan. This issue can
-  be avoided by not omitting the commas around the first slash, as in:
-```fortran
-      write(*,10) n, n+1, n+2
-   10 format(1x,i2,/,*(i3))
-      print *, 'tail */'
+      x = x
+     /* 2
+      print *, x, 'tail */ text'
 ```
 * $ and \ edit descriptors are supported in FORMAT to suppress newline
   output on user prompts.
diff --git a/flang/test/Preprocessing/fixed-c-comment02.F b/flang/test/Preprocessing/fixed-c-comment02.F
index 520a39bf66e64c..5805e767f3fb68 100644
--- a/flang/test/Preprocessing/fixed-c-comment02.F
+++ b/flang/test/Preprocessing/fixed-c-comment02.F
@@ -16,14 +16,23 @@
  * C comment
  */
 
-! ERROR: fixed-c-comment02.F:22:1: portability: nonstandard usage: C-style comment
-! ERROR: fixed-c-comment02.F:22:6: error: unterminated C-style comment
+! ERROR: fixed-c-comment02.F:23:6: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:25:29: error: Incomplete character literal
       i = 21
+      i = i
+     /* 2
+      print *, i
+      print *, 'tail */ text'
+
+! ERROR: fixed-c-comment02.F:30:1: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:30:6: error: unterminated C-style comment
+      i = 31
 /**/ /* 2
-! ERROR: fixed-c-comment02.F:25:6: error: unterminated C-style comment
-      i = 22
+! ERROR: fixed-c-comment02.F:33:6: error: unterminated C-style comment
+      i = 32
      /* 2
-! ERROR: fixed-c-comment02.F:29:1: error: unterminated C-style comment
-! ERROR: fixed-c-comment02.F:29:1: error: Character in fixed-form label field must be a digit
-! ERROR: fixed-c-comment02.F:29:1: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:37:1: error: unterminated C-style comment
+! ERROR: fixed-c-comment02.F:37:1: error: Character in fixed-form label field must be a digit
+! ERROR: fixed-c-comment02.F:37:1: portability: nonstandard usage: C-style comment
 /* Not-terminated C comment
+      end
diff --git a/flang/test/Preprocessing/fixed-c-comment03.f b/flang/test/Preprocessing/fixed-c-comment03.f
new file mode 100644
index 00000000000000..80d0c19ec264d1
--- /dev/null
+++ b/flang/test/Preprocessing/fixed-c-comment03.f
@@ -0,0 +1,10 @@
+! RUN: %flang_fc1 -fsyntax-only %s 2>&1
+
+      program p
+      integer :: y, x
+      y = 3
+      x = y
+     /* 2
+      print *, x
+      print *, 'tail */ text'
+      end

>From a34f50008e38e39776970a3ac2dd780f05ef71f0 Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Wed, 16 Sep 2026 15:12:09 -0300
Subject: [PATCH 13/14] Skip C comments on NextToken only when preprocessing is
 enabled

This fixes the regression with the following program:
```
      write(*,10) n, n+1, n+2
   10 format(1x,i2/*(i3))
      print *, 'tail */ text'
```

This commit also includes other minor fixes and improvements:
- Set preprocessingEnabled to true when -E is specified.
- Remove the code that adjusts column_. It is unnecessary, since
  UpdateSourcePositionAfterSkip in SkipCComments already adjusts
  column_.
- Consider colOffset when looking for C comments in LabelField. Even
  though C comments are not currently supported after conditional
  sentinels, this makes the code ready for future support.
- In NextToken, warn only when a C comment is consumed, to avoid
  spurious warnings in some cases.
- Add tests for -cpp/-nocpp/-E and the changes listed above.

Assisted-by: Claude Opus 5
---
 flang/docs/Extensions.md                      |  9 +++---
 flang/lib/Frontend/FrontendAction.cpp         | 11 +++++--
 flang/lib/Parser/prescan.cpp                  | 32 ++++++++-----------
 flang/lib/Parser/prescan.h                    |  2 +-
 flang/test/Preprocessing/fixed-c-comment01.F  |  2 +-
 flang/test/Preprocessing/fixed-c-comment02.F  | 26 ++++++++-------
 flang/test/Preprocessing/fixed-c-comment03.f  | 14 +++++++-
 flang/test/Preprocessing/fixed-c-comment04.f  | 10 ++++++
 flang/test/Preprocessing/free-c-comment01.f90 |  8 +++++
 flang/tools/bbc/bbc.cpp                       |  1 +
 10 files changed, 74 insertions(+), 41 deletions(-)
 create mode 100644 flang/test/Preprocessing/fixed-c-comment04.f
 create mode 100644 flang/test/Preprocessing/free-c-comment01.f90

diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index c1b088dca7c7de..de73a9468bfd34 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -276,13 +276,12 @@ end
 * Outside a character literal, a comment after a continuation marker (&)
   need not begin with a comment marker (!).
 * Classic C-style `/*comments*/` are skipped, so multi-language header
-  files are easier to write and use.
-* Classic C-style `/*comments*/` in fixed source form label fields are
-  skipped only when preprocessing is enabled. Otherwise, valid Fortran
-  programs could be rejected. For example:
+  files are easier to write and use. In fixed source form label fields, C
+  comments are skipped only when preprocessing is enabled. Otherwise, valid
+  Fortran programs could be rejected. For example:
 ```fortran
       x = x
-     /* 2
+     /* 2                           ! fixed-form continuation line
       print *, x, 'tail */ text'
 ```
 * $ and \ edit descriptors are supported in FORMAT to suppress newline
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index f1e5eb27867048..4e9f496b6268ca 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -83,16 +83,21 @@ bool FrontendAction::beginSourceFile(CompilerInstance &ci,
   //  * `-cpp/-nocpp`, or
   //  * the file extension (if the user didn't express any preference)
   // to decide whether to include them or not.
-  bool preprocessingEnabled =
+  bool includeMacros =
       (invoc.getPreprocessorOpts().macrosFlag == PPMacrosFlag::Include) ||
       (invoc.getPreprocessorOpts().showMacros) ||
       (invoc.getPreprocessorOpts().macrosFlag == PPMacrosFlag::Unknown &&
        getCurrentInput().getMustBePreprocessed());
-  if (preprocessingEnabled) {
+  if (includeMacros) {
     invoc.setDefaultPredefinitions();
     invoc.collectMacroDefinitions();
   }
-  invoc.getFortranOpts().preprocessingEnabled = preprocessingEnabled;
+  // Preprocessing is enabled if macros are included or if `-E` is specified
+  // and `-nocpp` is not.
+  invoc.getFortranOpts().preprocessingEnabled =
+      includeMacros ||
+      (invoc.getPreprocessorOpts().macrosFlag == PPMacrosFlag::Unknown &&
+       invoc.getFrontendOpts().programAction == PrintPreprocessedInput);
 
   if (!invoc.getFortranOpts().features.IsEnabled(
           Fortran::common::LanguageFeature::CUDA)) {
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index ade5979f34a900..a6a928f9110cbb 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -455,20 +455,12 @@ void Prescanner::LabelField(TokenSequence &token) {
     std::uint64_t spaces{HasTabInLabelField(start - colOffset, limit_)
             ? 6
             : static_cast<std::uint64_t>(p - start)};
-    if (spaces < 6 && IsCComment(p)) {
+    if (colOffset + spaces < 6 && IsCComment(p)) {
       at_ += spaces;
       column_ += spaces;
-      SkipCComments(/*noError=*/false);
+      SkipCComments(/*reportUnterminated=*/true);
       if (at_ > start + spaces) {
         WarnCComment(p);
-        // Fix `column_`, which may be incorrect after multi-line comments.
-        p = at_ - 1;
-        while (p > start && *p != '\n') {
-          --p;
-        }
-        if (*p == '\n') {
-          column_ = at_ - p;
-        }
         colOffset = column_ - 1;
         start = at_;
       }
@@ -641,7 +633,7 @@ void Prescanner::NextChar() {
 // fixed form, and all forms of line continuation.
 bool Prescanner::SkipToNextSignificantCharacter() {
   if (inPreprocessorDirective_) {
-    SkipCComments(/*noError=*/true);
+    SkipCComments(/*reportUnterminated=*/false);
     return false;
   } else {
     auto anyContinuationLine{false};
@@ -665,7 +657,7 @@ bool Prescanner::SkipToNextSignificantCharacter() {
   }
 }
 
-void Prescanner::SkipCComments(bool noError) {
+void Prescanner::SkipCComments(bool reportUnterminated) {
   while (true) {
     if (IsCComment(at_)) {
       if (const char *after{SkipCComment(at_)}) {
@@ -678,7 +670,7 @@ void Prescanner::SkipCComments(bool noError) {
         // when processing label fields, while others keep the old behavior of
         // ignoring unterminated C-style comments.
         // TODO Always emit an error when preprocessing is enabled.
-        if (preprocessingEnabled_ && !noError) {
+        if (preprocessingEnabled_ && reportUnterminated) {
           Say(GetProvenance(at_), "unterminated C-style comment"_err_en_US);
         }
         break;
@@ -816,11 +808,15 @@ bool Prescanner::NextToken(TokenSequence &tokens) {
   if (compilingFixedForm) {
     SkipSpaces();
   }
-  if (*at_ == '/' && IsCComment(at_)) {
+  if (*at_ == '/' && IsCComment(at_) &&
+      (!compilingFixedForm || preprocessingEnabled_)) {
     // Recognize and skip over classic C style /*comments*/ when
     // outside a character literal.
-    WarnCComment(at_);
-    SkipCComments(/*noError=*/true);
+    const char *before{at_};
+    SkipCComments(/*reportUnterminated=*/false);
+    if (at_ > before) {
+      WarnCComment(before);
+    }
     if (compilingFixedForm) {
       SkipSpaces();
     }
@@ -1719,8 +1715,8 @@ bool Prescanner::FixedFormContinuation(bool atNewline) {
     return false;
   }
   do {
-    const char *cComment;
-    const char *unterminatedCComment;
+    const char *cComment{nullptr};
+    const char *unterminatedCComment{nullptr};
     if (const char *cont{FixedFormContinuationLine(
             atNewline, cComment, unterminatedCComment)}) {
       if (cComment) {
diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h
index 63b1f32d130811..e0ccfb67291cf2 100644
--- a/flang/lib/Parser/prescan.h
+++ b/flang/lib/Parser/prescan.h
@@ -232,7 +232,7 @@ class Prescanner {
   void NextChar();
   // True when input flowed to a continuation line
   bool SkipToNextSignificantCharacter();
-  void SkipCComments(bool noError);
+  void SkipCComments(bool reportUnterminated);
   void WarnCComment(const char *at);
   void SkipSpaces();
   static const char *SkipWhiteSpace(const char *);
diff --git a/flang/test/Preprocessing/fixed-c-comment01.F b/flang/test/Preprocessing/fixed-c-comment01.F
index 947d3a5fda42da..24a81f8cdb01b7 100644
--- a/flang/test/Preprocessing/fixed-c-comment01.F
+++ b/flang/test/Preprocessing/fixed-c-comment01.F
@@ -1,4 +1,4 @@
-! RUN: %flang_fc1 -fsyntax-only %s 2>&1
+! RUN: %flang_fc1 -fsyntax-only %s
 ! RUN: %flang -E %s 2>&1 | FileCheck %s
 
       implicit none
diff --git a/flang/test/Preprocessing/fixed-c-comment02.F b/flang/test/Preprocessing/fixed-c-comment02.F
index 5805e767f3fb68..c5cf0e112945d8 100644
--- a/flang/test/Preprocessing/fixed-c-comment02.F
+++ b/flang/test/Preprocessing/fixed-c-comment02.F
@@ -1,38 +1,40 @@
 ! RUN: not %flang_fc1 -fsyntax-only -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=ERROR
+! RUN: not %flang_fc1 -nocpp -fsyntax-only -pedantic -Werror %s 2>&1 | \
+! RUN:    FileCheck %s --check-prefix=NOCPP-ERROR
 
       implicit none
       integer :: i
 
-! ERROR: fixed-c-comment02.F:9:1: portability: nonstandard usage: C-style comment
-! ERROR: fixed-c-comment02.F:10:3: error: Character in fixed-form label field must be a digit
+! ERROR: fixed-c-comment02.F:11:1: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:12:3: error: Character in fixed-form label field must be a digit
       i = 11
 /*
 */+1
 
-! ERROR: fixed-c-comment02.F:13:1: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:16:1: portability: nonstandard usage: C-style comment
+! NOCPP-ERROR: fixed-c-comment02.F:16:1: error: Character in fixed-form label field must be a digit
 /* Single-line C comment */
-! ERROR: fixed-c-comment02.F:15:1: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:18:1: portability: nonstandard usage: C-style comment
 /* Multi-line
  * C comment
  */
 
-! ERROR: fixed-c-comment02.F:23:6: portability: nonstandard usage: C-style comment
-! ERROR: fixed-c-comment02.F:25:29: error: Incomplete character literal
+! ERROR: fixed-c-comment02.F:26:6: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:28:29: error: Incomplete character literal
       i = 21
       i = i
      /* 2
       print *, i
       print *, 'tail */ text'
 
-! ERROR: fixed-c-comment02.F:30:1: portability: nonstandard usage: C-style comment
-! ERROR: fixed-c-comment02.F:30:6: error: unterminated C-style comment
+! ERROR: fixed-c-comment02.F:33:1: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:33:6: error: unterminated C-style comment
       i = 31
 /**/ /* 2
-! ERROR: fixed-c-comment02.F:33:6: error: unterminated C-style comment
+! ERROR: fixed-c-comment02.F:36:6: error: unterminated C-style comment
       i = 32
      /* 2
-! ERROR: fixed-c-comment02.F:37:1: error: unterminated C-style comment
-! ERROR: fixed-c-comment02.F:37:1: error: Character in fixed-form label field must be a digit
-! ERROR: fixed-c-comment02.F:37:1: portability: nonstandard usage: C-style comment
+! ERROR: fixed-c-comment02.F:39:1: error: unterminated C-style comment
+! ERROR: fixed-c-comment02.F:39:1: error: Character in fixed-form label field must be a digit
 /* Not-terminated C comment
       end
diff --git a/flang/test/Preprocessing/fixed-c-comment03.f b/flang/test/Preprocessing/fixed-c-comment03.f
index 80d0c19ec264d1..a6823061afab70 100644
--- a/flang/test/Preprocessing/fixed-c-comment03.f
+++ b/flang/test/Preprocessing/fixed-c-comment03.f
@@ -1,10 +1,22 @@
-! RUN: %flang_fc1 -fsyntax-only %s 2>&1
+! RUN: %flang_fc1 -fsyntax-only %s
+! RUN: not %flang_fc1 -cpp -fsyntax-only -pedantic -Werror %s 2>&1 | \
+! RUN:    FileCheck %s --check-prefix=CPP-ERROR
 
       program p
       integer :: y, x
       y = 3
       x = y
+! CPP-ERROR: fixed-c-comment03.f:11:6: portability: nonstandard usage: C-style comment
+! CPP-ERROR: fixed-c-comment03.f:13:29: error: Incomplete character literal
      /* 2
       print *, x
       print *, 'tail */ text'
+
+      x = 7
+      write(*,10) x, x+1, x+2
+! CPP-ERROR: fixed-c-comment03.f:20:13: error: Unmatched '('
+! CPP-ERROR: fixed-c-comment03.f:20:19: portability: nonstandard usage: C-style comment
+! CPP-ERROR: fixed-c-comment03.f:21:29: error: Incomplete character literal
+   10 format(1x,i2/*(i3))
+      print *, 'tail */ text'
       end
diff --git a/flang/test/Preprocessing/fixed-c-comment04.f b/flang/test/Preprocessing/fixed-c-comment04.f
new file mode 100644
index 00000000000000..7033fa41f2dd5f
--- /dev/null
+++ b/flang/test/Preprocessing/fixed-c-comment04.f
@@ -0,0 +1,10 @@
+! Check that -E also enables preprocessing.
+! RUN: %flang_fc1 -cpp -fsyntax-only %s
+! RUN: %flang -E %s 2>&1 | FileCheck %s
+! RUN: %flang -E -nocpp %s 2>&1 | FileCheck %s --check-prefix=NOCPP
+
+! CHECK: print *, "hello", "world"
+! NOCPP: /*c*/ print *, /* comment */ "hello"
+/*c*/ print *, /* comment */ "hello"
+/*d*/+, "world"
+      end
diff --git a/flang/test/Preprocessing/free-c-comment01.f90 b/flang/test/Preprocessing/free-c-comment01.f90
new file mode 100644
index 00000000000000..2520b57860139e
--- /dev/null
+++ b/flang/test/Preprocessing/free-c-comment01.f90
@@ -0,0 +1,8 @@
+! Check that "/*" doesn't trigger a C-style comment warning.
+! RUN: %flang_fc1 -fsyntax-only -pedantic -Werror %s
+
+    integer :: x
+    x = 1
+    write(*,10) x, x+1, x+2
+10  format(1x,i2/*(i3))
+end
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 7d0c0f6644a0d5..5671decf3f531f 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -658,6 +658,7 @@ int main(int argc, char **argv) {
   }
 
   Fortran::parser::Options options;
+  // bbc always preprocesses the input.
   options.preprocessingEnabled = true;
   options.predefinitions.emplace_back("__flang__"s, "1"s);
   options.predefinitions.emplace_back("__flang_major__"s,

>From 2e1eacf4d897bb2ad482d0752b2dd139e4d57557 Mon Sep 17 00:00:00 2001
From: Leandro Lupori <leandro.lupori at linaro.org>
Date: Fri, 18 Sep 2026 14:52:28 -0300
Subject: [PATCH 14/14] Address the review issues

---
 flang/lib/Frontend/FrontendAction.cpp         |  7 +------
 flang/lib/Parser/prescan.cpp                  |  3 ++-
 flang/test/Preprocessing/fixed-c-comment03.f  |  2 +-
 flang/test/Preprocessing/fixed-c-comment04.f  | 17 +++++++++--------
 flang/test/Preprocessing/fixed-c-comment05.f  |  6 ++++++
 flang/tools/f18-parse-demo/f18-parse-demo.cpp |  2 ++
 6 files changed, 21 insertions(+), 16 deletions(-)
 create mode 100644 flang/test/Preprocessing/fixed-c-comment05.f

diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index 4e9f496b6268ca..5dfb5a6c617de9 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -92,12 +92,7 @@ bool FrontendAction::beginSourceFile(CompilerInstance &ci,
     invoc.setDefaultPredefinitions();
     invoc.collectMacroDefinitions();
   }
-  // Preprocessing is enabled if macros are included or if `-E` is specified
-  // and `-nocpp` is not.
-  invoc.getFortranOpts().preprocessingEnabled =
-      includeMacros ||
-      (invoc.getPreprocessorOpts().macrosFlag == PPMacrosFlag::Unknown &&
-       invoc.getFrontendOpts().programAction == PrintPreprocessedInput);
+  invoc.getFortranOpts().preprocessingEnabled = includeMacros;
 
   if (!invoc.getFortranOpts().features.IsEnabled(
           Fortran::common::LanguageFeature::CUDA)) {
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index a6a928f9110cbb..715fb45f6bd4a7 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -1480,7 +1480,8 @@ const char *Prescanner::FixedFormContinuationLine(
   char col1{*nextLine_};
   const char *afterWhiteSpace{SkipWhiteSpace(nextLine_)};
   const char *afterCComment{nullptr};
-  if (preprocessingEnabled_ && IsCComment(afterWhiteSpace)) {
+  if (preprocessingEnabled_ && IsCComment(afterWhiteSpace) &&
+      !HasTabInLabelField(nextLine_, limit_)) {
     afterCComment = SkipCComment(afterWhiteSpace);
     if (afterCComment == nullptr) {
       unterminatedCComment = afterWhiteSpace;
diff --git a/flang/test/Preprocessing/fixed-c-comment03.f b/flang/test/Preprocessing/fixed-c-comment03.f
index a6823061afab70..e05acacd5245a5 100644
--- a/flang/test/Preprocessing/fixed-c-comment03.f
+++ b/flang/test/Preprocessing/fixed-c-comment03.f
@@ -3,7 +3,7 @@
 ! RUN:    FileCheck %s --check-prefix=CPP-ERROR
 
       program p
-      integer :: y, x
+      integer :: x, y
       y = 3
       x = y
 ! CPP-ERROR: fixed-c-comment03.f:11:6: portability: nonstandard usage: C-style comment
diff --git a/flang/test/Preprocessing/fixed-c-comment04.f b/flang/test/Preprocessing/fixed-c-comment04.f
index 7033fa41f2dd5f..721bfc1619e913 100644
--- a/flang/test/Preprocessing/fixed-c-comment04.f
+++ b/flang/test/Preprocessing/fixed-c-comment04.f
@@ -1,10 +1,11 @@
-! Check that -E also enables preprocessing.
-! RUN: %flang_fc1 -cpp -fsyntax-only %s
-! RUN: %flang -E %s 2>&1 | FileCheck %s
-! RUN: %flang -E -nocpp %s 2>&1 | FileCheck %s --check-prefix=NOCPP
+! RUN: not %flang_fc1 -cpp -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=ERROR
 
-! CHECK: print *, "hello", "world"
-! NOCPP: /*c*/ print *, /* comment */ "hello"
-/*c*/ print *, /* comment */ "hello"
-/*d*/+, "world"
+      implicit none
+      integer :: x, y
+      y = 3
+! The lines below should be parsed as distinct lines, with no continuation.
+! ERROR: error: obsolete legacy extension is not supported
+      x = y
+	/**/+2
+      print *, x
       end
diff --git a/flang/test/Preprocessing/fixed-c-comment05.f b/flang/test/Preprocessing/fixed-c-comment05.f
new file mode 100644
index 00000000000000..4ac128a3f54bd1
--- /dev/null
+++ b/flang/test/Preprocessing/fixed-c-comment05.f
@@ -0,0 +1,6 @@
+! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=ERROR
+
+      integer :: i
+! ERROR: error: expected end of statement
+      i = 8 /* comment */
+      end
diff --git a/flang/tools/f18-parse-demo/f18-parse-demo.cpp b/flang/tools/f18-parse-demo/f18-parse-demo.cpp
index 07280da15d7d93..b41b9cdd8b9783 100644
--- a/flang/tools/f18-parse-demo/f18-parse-demo.cpp
+++ b/flang/tools/f18-parse-demo/f18-parse-demo.cpp
@@ -297,6 +297,8 @@ int main(int argc, char *const argv[]) {
   driver.prefix = prefix.data();
 
   Fortran::parser::Options options;
+  // f18-parse-demo always preprocesses the input.
+  options.preprocessingEnabled = true;
   options.predefinitions.emplace_back("__F18", "1");
   options.predefinitions.emplace_back("__F18_MAJOR__", "1");
   options.predefinitions.emplace_back("__F18_MINOR__", "1");



More information about the flang-commits mailing list