[flang-commits] [flang] 21725d2 - [flang] Treat a bare carriage return as whitespace outside literals (#206171)

via flang-commits flang-commits at lists.llvm.org
Mon Jun 29 09:53:49 PDT 2026


Author: Eugene Epshteyn
Date: 2026-06-29T12:53:44-04:00
New Revision: 21725d26dee4a527a99ec43fefd4b60ca319a14a

URL: https://github.com/llvm/llvm-project/commit/21725d26dee4a527a99ec43fefd4b60ca319a14a
DIFF: https://github.com/llvm/llvm-project/commit/21725d26dee4a527a99ec43fefd4b60ca319a14a.diff

LOG: [flang] Treat a bare carriage return as whitespace outside literals (#206171)

Free-form (and fixed-form) source files authored or transferred on
Windows can contain a stray carriage return (0x0d or \r) in the interior
of a line, for example between a token and a trailing '&' continuation
marker:

    COMMON/CM1/<CR>       &

flang rejected such files with "bad character (0x0d) in Fortran token",
whereas the other compilers accept them. Carriage returns that form a
clean CRLF line ending were already tolerated; only a CR in the
significant part of a line tripped the error.

The fix is to skip over the stray <CR> outside of character literals.

Assisted-by: AI

Added: 
    flang/test/Preprocessing/carriage-return.f90

Modified: 
    flang/docs/Extensions.md
    flang/lib/Parser/prescan.cpp

Removed: 
    


################################################################################
diff  --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index e05b0cf423101..054e38c623bca 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -203,6 +203,10 @@ end
 ## Extensions, deletions, and legacy features supported by default
 
 * Tabs in source
+* A bare carriage return (CR, 0x0d) in the interior of a source line -- e.g.
+  from a file with Windows line endings that has been mishandled -- is treated
+  as a blank, except within a character or Hollerith literal where it is
+  retained.
 * `<>` as synonym for `.NE.` and `/=`
 * `$` and `@` as legal characters in names
 * Initialization in type declaration statements using `/values/`

diff  --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index c1dd17400012a..0aed9545f6dbc 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -56,6 +56,8 @@ static inline int IsSpace(const char *p) {
     return 1;
   } else if (p[0] == '\xc2' && p[1] == '\xa0') { // UTF-8 NBSP
     return 2;
+  } else if (*p == '\r') { // bare carriage return retained in line
+    return 1;
   } else {
     return 0;
   }

diff  --git a/flang/test/Preprocessing/carriage-return.f90 b/flang/test/Preprocessing/carriage-return.f90
new file mode 100644
index 0000000000000..9c7795fee0877
--- /dev/null
+++ b/flang/test/Preprocessing/carriage-return.f90
@@ -0,0 +1,25 @@
+! Tests that a bare carriage return (0x0d) appearing in the interior of a
+! source line -- i.e. not as part of a CRLF/CR line ending -- is treated as
+! insignificant whitespace outside of character literals, while still being
+! preserved verbatim inside character literals.
+!
+! The carriage returns are generated with printf so that no literal CR byte is
+! committed into the repository.
+
+! A mid-line CR before a free-form '&' continuation must compile cleanly.
+! RUN: printf 'program p\n  integer :: i, j\n  common /blk/\r &\n    i, j\nend\n' > %t-free.f90
+! RUN: %flang_fc1 -fsyntax-only %t-free.f90
+
+! A mid-line CR in fixed-form source must compile cleanly.
+! RUN: printf '      program p\n      integer i, j\n      common /blk/ i\r, j\n      end\n' > %t-fixed.f
+! RUN: %flang_fc1 -fsyntax-only -ffixed-form %t-fixed.f
+
+! A CR inside a character literal must be preserved: the literal stays three
+! characters long and its middle byte remains 0x0d (decimal 13). The quote
+! characters around the literal are emitted with printf's octal escape \047 so
+! the whole format string stays single-quoted and portable to lit's internal
+! shell on all platforms.
+! RUN: printf 'module m\n  character(*), parameter :: s = \047a\rb\047\n  integer, parameter :: slen = len(s)\n  integer, parameter :: midval = iachar(s(2:2))\nend module\n' > %t-literal.f90
+! RUN: %flang_fc1 -fdebug-unparse %t-literal.f90 | FileCheck %s
+! CHECK: slen = 3_4
+! CHECK: midval = 13_4


        


More information about the flang-commits mailing list