[flang-commits] [flang] [flang] Handle continuation line edge case (PR #74751)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Thu Dec 7 11:21:36 PST 2023


https://github.com/klausler created https://github.com/llvm/llvm-project/pull/74751

For repeated quote marks in a character literal that are separated by free form line continuation without a leading ampersand character on the continuation line, also handle the case of spaces at the beginning of the continuation line.

For example,

PRINT *, 'don'&
 't poke the bear'

now prints "don't poke the bear", like nearly all other Fortran compilers do.

This is not strictly standard conforming behavior, and the compiler emits a portability warning with -pedantic.

Fixes llvm-test-suite/Fortran/gfortran/regression/continuation_12.f90 and .../continuation_13.f90.

>From 5f064bce4eb448fbe6961f6a7272c9b019969eee Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Thu, 7 Dec 2023 11:14:18 -0800
Subject: [PATCH] [flang] Handle continuation line edge case

For repeated quote marks in a character literal that are
separated by free form line continuation without a leading
ampersand character on the continuation line, also handle
the case of spaces at the beginning of the continuation line.

For example,

PRINT *, 'don'&
 't poke the bear'

now prints "don't poke the bear", like nearly all other Fortran
compilers do.

This is not strictly standard conforming behavior, and the compiler
emits a portability warning with -pedantic.

Fixes llvm-test-suite/Fortran/gfortran/regression/continuation_12.f90
and .../continuation_13.f90.
---
 flang/lib/Parser/prescan.cpp                  | 20 ++++++++++---------
 flang/lib/Parser/prescan.h                    |  3 ++-
 .../test/Parser/continuation-before-quote.f90 |  3 +++
 3 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 449ea60144424a..ac68b54a50ca18 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -706,6 +706,7 @@ void Prescanner::QuotedCharacterLiteral(
   char quote{*at_};
   const char *end{at_ + 1};
   inCharLiteral_ = true;
+  charLiteralQuote_ = quote;
   const auto emit{[&](char ch) { EmitChar(tokens, ch); }};
   const auto insert{[&](char ch) { EmitInsertedChar(tokens, ch); }};
   bool isEscaped{false};
@@ -749,17 +750,10 @@ void Prescanner::QuotedCharacterLiteral(
         break;
       }
       inCharLiteral_ = true;
-      if (insertASpace_) {
-        if (features_.ShouldWarn(
-                common::LanguageFeature::MiscSourceExtensions)) {
-          Say(GetProvenanceRange(at_, end),
-              "Repeated quote mark in character literal continuation line should have been preceded by '&'"_port_en_US);
-        }
-        insertASpace_ = false;
-      }
     }
   }
   inCharLiteral_ = false;
+  charLiteralQuote_.reset();
 }
 
 void Prescanner::Hollerith(
@@ -1122,7 +1116,15 @@ const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
     } else if (*p == '!' || *p == '\n' || *p == '#') {
       return nullptr;
     } else if (ampersand || IsImplicitContinuation()) {
-      if (p > nextLine_) {
+      if (charLiteralQuote_ && *p == *charLiteralQuote_) {
+        // 'a'&            -> 'a''b' == "a'b"
+        //   'b'
+        if (features_.ShouldWarn(
+                common::LanguageFeature::MiscSourceExtensions)) {
+          Say(GetProvenanceRange(p, p + 1),
+              "Repeated quote mark in character literal continuation line should have been preceded by '&'"_port_en_US);
+        }
+      } else if (p > nextLine_) {
         --p;
       } else {
         insertASpace_ = true;
diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h
index 16b2c6165f611c..efeda592813ea7 100644
--- a/flang/lib/Parser/prescan.h
+++ b/flang/lib/Parser/prescan.h
@@ -217,7 +217,8 @@ class Prescanner {
   bool tabInCurrentLine_{false};
   bool slashInCurrentStatement_{false};
   bool preventHollerith_{false}; // CHARACTER*4HIMOM not Hollerith
-  bool inCharLiteral_{false};
+  bool inCharLiteral_;
+  std::optional<char> charLiteralQuote_;
   bool inPreprocessorDirective_{false};
 
   // In some edge cases of compiler directive continuation lines, it
diff --git a/flang/test/Parser/continuation-before-quote.f90 b/flang/test/Parser/continuation-before-quote.f90
index 66252010d89c46..1cc44d29c87463 100644
--- a/flang/test/Parser/continuation-before-quote.f90
+++ b/flang/test/Parser/continuation-before-quote.f90
@@ -4,6 +4,9 @@ subroutine test
 !CHECK: portability: Repeated quote mark in character literal continuation line should have been preceded by '&'
   print *, 'needs an '&
 'ampersand'''
+!CHECK: portability: Repeated quote mark in character literal continuation line should have been preceded by '&'
+  print *, 'also needs an '&
+ 'ampersand'''
 !CHECK-NOT: portability: Repeated quote mark in character literal continuation line should have been preceded by '&'
   print *, 'has an '&
 &'ampersand'''



More information about the flang-commits mailing list