]> granicus.if.org Git - clang/commitdiff
[Preprocessor] Correct internal token parsing of newline characters in CRLF
authorErich Keane <erich.keane@intel.com>
Thu, 24 Aug 2017 18:36:07 +0000 (18:36 +0000)
committerErich Keane <erich.keane@intel.com>
Thu, 24 Aug 2017 18:36:07 +0000 (18:36 +0000)
Discovered due to a goofy git setup, the test system-headerline-directive.c
(and a few others) failed because the token-consumption will consume only the
'\r' in CRLF, making the preprocessor's printed value give the wrong line number
when returning from an include. For example:

(line 1):#include <noline.h>\r\n

The "file exit" code causes the printer to try to print the 'returned to the
main file' line. It looks up what the current line number is. However, since the
current 'token' is the '\n' (since only the \r was consumed), it will give the
line number as '1", not '2'. This results in a few failed tests, but more
importantly, results in error messages being incorrect when compiling a
previously preprocessed file.

Differential Revision: https://reviews.llvm.org/D37079

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@311683 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Lex/Lexer.cpp
test/Frontend/.gitattributes [new file with mode: 0644]
test/Frontend/system-header-line-directive-ms-lineendings.c [new file with mode: 0644]

index 79472961c010e64c94d2a5b5d4d9e0b2d2d64234..976a0d2fbd8c29061a42baa584174dd1765126bf 100644 (file)
@@ -3073,6 +3073,8 @@ LexNextToken:
       
   case '\n':
   case '\r':
+    if (CurPtr[0] != Char && (CurPtr[0] == '\n' || CurPtr[0] == '\r'))
+      Char = getAndAdvanceChar(CurPtr, Result);
     // If we are inside a preprocessor directive and we see the end of line,
     // we know we are done with the directive, so return an EOD token.
     if (ParsingPreprocessorDirective) {
diff --git a/test/Frontend/.gitattributes b/test/Frontend/.gitattributes
new file mode 100644 (file)
index 0000000..03f5ad0
--- /dev/null
@@ -0,0 +1,2 @@
+# Below test validates crlf line endings, so it should stay crlf.
+system-header-line-directive-ms-lineendings.c text eol=crlf
diff --git a/test/Frontend/system-header-line-directive-ms-lineendings.c b/test/Frontend/system-header-line-directive-ms-lineendings.c
new file mode 100644 (file)
index 0000000..34a7ec9
--- /dev/null
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -E -o - -I %S/Inputs -isystem %S/Inputs/SystemHeaderPrefix | FileCheck %s\r
+#include <noline.h>\r
+#include <line-directive-in-system.h>\r
+\r
+#include "line-directive.h"\r
+\r
+// This tests that the line numbers for the current file are correctly outputted\r
+// for the include-file-completed test case.  \r
+\r
+// CHECK: # 1 "{{.*}}system-header-line-directive-ms-lineendings.c" 2\r
+// CHECK: # 1 "{{.*}}noline.h" 1 3\r
+// CHECK: foo();\r
+// CHECK: # 3 "{{.*}}system-header-line-directive-ms-lineendings.c" 2\r
+// CHECK: # 1 "{{.*}}line-directive-in-system.h" 1 3\r
+//      The "3" below indicates that "foo.h" is considered a system header.\r
+// CHECK: # 1 "foo.h" 3\r
+// CHECK: foo();\r
+// CHECK: # 4 "{{.*}}system-header-line-directive-ms-lineendings.c" 2\r
+// CHECK: # 1 "{{.*}}line-directive.h" 1\r
+// CHECK: # 10 "foo.h"{{$}}\r
+// CHECK: # 6 "{{.*}}system-header-line-directive-ms-lineendings.c" 2\r