tahonermann created this revision.
tahonermann added reviewers: rnk, cor3ntin, shafik, erichkeane, aaron.ballman.
Herald added a project: All.
tahonermann requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Previously, if a header file and a source file used different end of line (EOL)
forms, preprocessed output generated with the -frewrite-includes option would,
in some cases, generate line control directives with the wrong line number due
to an error in how source file lines were counted.
Fixes https://github.com/llvm/llvm-project/issues/59736
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D140984
Files:
clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c
clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h
clang/test/Frontend/rewrite-includes-mixed-eol-lf.c
clang/test/Frontend/rewrite-includes-mixed-eol-lf.h
Index: clang/test/Frontend/rewrite-includes-mixed-eol-lf.h
===================================================================
--- /dev/null
+++ clang/test/Frontend/rewrite-includes-mixed-eol-lf.h
@@ -0,0 +1,11 @@
+// Note: This header file has LF line endings.
+// The indentation in some of the conditional inclusion directives below is
+// intentional and is required for this test to function as a regression test
+// for GH59736.
+_Static_assert(__LINE__ == 5, "");
+#if 1
+_Static_assert(__LINE__ == 7, "");
+ #if 1
+ _Static_assert(__LINE__ == 9, "");
+ #endif
+#endif
Index: clang/test/Frontend/rewrite-includes-mixed-eol-lf.c
===================================================================
--- /dev/null
+++ clang/test/Frontend/rewrite-includes-mixed-eol-lf.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -E -frewrite-includes %s | %clang_cc1 -
+// expected-no-diagnostics
+// Note: This source file has LF line endings.
+// This test validates that -frewrite-includes translates the end of line (EOL)
+// form used in header files to the EOL form used in the the primary source
+// file when the files use different EOL forms.
+#include "rewrite-includes-mixed-eol-crlf.h"
+#include "rewrite-includes-mixed-eol-lf.h"
Index: clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h
===================================================================
--- /dev/null
+++ clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h
@@ -0,0 +1,11 @@
+// Note: This header file has CRLF line endings.
+// The indentation in some of the conditional inclusion directives below is
+// intentional and is required for this test to function as a regression test
+// for GH59736.
+_Static_assert(__LINE__ == 5, "");
+#if 1
+_Static_assert(__LINE__ == 7, "");
+ #if 1
+ _Static_assert(__LINE__ == 9, "");
+ #endif
+#endif
Index: clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c
===================================================================
--- /dev/null
+++ clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -E -frewrite-includes %s | %clang_cc1 -
+// expected-no-diagnostics
+// Note: This source file has CRLF line endings.
+// This test validates that -frewrite-includes translates the end of line (EOL)
+// form used in header files to the EOL form used in the the primary source
+// file when the files use different EOL forms.
+#include "rewrite-includes-mixed-eol-crlf.h"
+#include "rewrite-includes-mixed-eol-lf.h"
Index: clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -281,27 +281,28 @@
StringRef TextToWrite(FromFile.getBufferStart() + WriteFrom,
WriteTo - WriteFrom);
+ // count lines manually, it's faster than getPresumedLoc()
+ Line += TextToWrite.count(LocalEOL);
if (MainEOL == LocalEOL) {
OS << TextToWrite;
- // count lines manually, it's faster than getPresumedLoc()
- Line += TextToWrite.count(LocalEOL);
- if (EnsureNewline && !TextToWrite.endswith(LocalEOL))
- OS << MainEOL;
} else {
// Output the file one line at a time, rewriting the line endings as we go.
StringRef Rest = TextToWrite;
while (!Rest.empty()) {
- StringRef LineText;
- std::tie(LineText, Rest) = Rest.split(LocalEOL);
+ size_t Idx = Rest.find(LocalEOL);
+ StringRef LineText = Rest.substr(0, Idx);
OS << LineText;
- Line++;
- if (!Rest.empty())
+ if (Idx != StringRef::npos) {
OS << MainEOL;
+ Idx += LocalEOL.size();
+ }
+ Rest = Rest.substr(Idx);
}
- if (TextToWrite.endswith(LocalEOL) || EnsureNewline)
- OS << MainEOL;
}
+ if (EnsureNewline && !TextToWrite.endswith(LocalEOL))
+ OS << MainEOL;
+
WriteFrom = WriteTo;
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits