[cfe-commits] [PATCH] PR6101: Preprocessor doesn't honor #line directives

Jordy Rose jediknil at belkadan.com
Sat Apr 10 22:13:09 PDT 2010


PR6101 is a little misleading; #line directives /are/ honored, but not by
PrintPreprocessorOutput.cpp (-E mode). (Unless there is a separate problem
on PC Linux.) This patch fixes that by using presumed locations instead of
instantiation locations.

There is a bit of a hack to handle the fact that actually entering and
exiting source files looks the same as GNU linemarkers. (System header
markers and normal "renames" are always from directives.)
- Entering a file counts as a line directive if the include location is in
the same file as the file itself.
- Exiting a file counts as a line directive...if the exit doesn't happen
at the beginning of a line. This is a kludge, and takes advantage of
#include eating the newline before loading the next file, but I couldn't
think of a better test that got everything correct (including the exit
linemarkers in the predefines).

The test files are a .c/.h pair with a hodgepodge of #line and linemarker
directives.

Thanks,
Jordy
-------------- next part --------------
Index: test/Preprocessor/line-directive-output.c
===================================================================
--- test/Preprocessor/line-directive-output.c	(revision 0)
+++ test/Preprocessor/line-directive-output.c	(revision 0)
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -E %s 2>&1 | FileCheck %s -strict-whitespace
+int a;
+// CHECK: # 1 "{{.*}}line-directive-output.c"
+// CHECK: int a;
+
+// CHECK-NEXT: # 50 "{{.*}}line-directive-output.c"
+// CHECK-NEXT: int b;
+#line 50
+int b;
+
+// CHECK: # 13 "{{.*}}line-directive-output.c"
+// CHECK-NEXT: int c;
+# 13
+int c;
+
+
+// CHECK-NEXT: # 1 "A.c"
+#line 1 "A.c"
+// CHECK-NEXT: # 2 "A.c"
+#line 2
+
+// CHECK-NEXT: # 1 "B.c"
+#line 1 "B.c"
+
+// CHECK-NEXT: # 1000 "A.c"
+#line 1000 "A.c"
+
+int y;
+
+
+
+
+
+
+
+// CHECK: # 1010 "A.c"
+int z;
+
+#include "line-directive-output.h"
+// CHECK: # 1 "{{.*}}line-directive-output.h" 1
+// CHECK: # 3 "temp2.h" 1
+// CHECK: # 7 "temp.h" 2
+// CHECK: # 11 "temp.h" 3
+// (nested include)
+// CHECK: # 1 "{{.*}}line-directive-output.h" 1
+// CHECK: # 3 "temp2.h" 1
+// CHECK: # 7 "temp.h" 2
+// (end nested include)
+// CHECK: # 13 "temp.h" 2
+// CHECK-NOT: # 13 "temp.h" 2
+
+// CHECK: # 1013 "A.c" 2
+
+
+// CHECK: # 50 "C.c" 1
+# 50 "C.c" 1
+
+
+// CHECK-NEXT: # 2000 "A.c" 2
+# 2000 "A.c" 2
Index: test/Preprocessor/line-directive-output.h
===================================================================
--- test/Preprocessor/line-directive-output.h	(revision 0)
+++ test/Preprocessor/line-directive-output.h	(revision 0)
@@ -0,0 +1,14 @@
+extern int x;
+
+# 3 "temp2.h" 1
+extern int y;
+
+# 7 "temp.h" 2
+extern int z;
+
+#ifndef ENOUGH
+# 11 "temp.h" 3
+#define ENOUGH
+#include "line-directive-output.h"
+extern int q;
+#endif
Index: lib/Frontend/PrintPreprocessedOutput.cpp
===================================================================
--- lib/Frontend/PrintPreprocessedOutput.cpp	(revision 100955)
+++ lib/Frontend/PrintPreprocessedOutput.cpp	(working copy)
@@ -167,9 +167,10 @@
 /// #line directive.  This returns false if already at the specified line, true
 /// if some newlines were emitted.
 bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) {
-  unsigned LineNo = PP.getSourceManager().getInstantiationLineNumber(Loc);
+  unsigned LineNo;
 
   if (DisableLineMarkers) {
+    LineNo = PP.getSourceManager().getInstantiationLineNumber(Loc);
     if (LineNo == CurLine) return false;
 
     CurLine = LineNo;
@@ -182,6 +183,8 @@
     EmittedMacroOnThisLine = false;
     return true;
   }
+  
+  LineNo = PP.getSourceManager().getPresumedLoc(Loc).getLine();
 
   // If this line is "close enough" to the original line, just print newlines,
   // otherwise print a #line directive.
@@ -224,14 +227,30 @@
     // strange behavior.
   }
 
+  if (DisableLineMarkers) return;
+
+  bool IsLineDirective = true; // assumed for now
+
   Loc = SourceMgr.getInstantiationLoc(Loc);
-  // FIXME: Should use presumed line #!
-  CurLine = SourceMgr.getInstantiationLineNumber(Loc);
+  PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc);
+  
+  if (Reason == PPCallbacks::EnterFile) {
+    SourceLocation IncludeLoc = UserLoc.getIncludeLoc();
+    if (!IncludeLoc.isValid() || !SourceMgr.isFromSameFile(IncludeLoc, Loc))
+      IsLineDirective = false;
+  } else if (Reason == PPCallbacks::ExitFile) {
+    // FIXME replace with something more reliable
+    if (UserLoc.getColumn() == 0)
+      IsLineDirective = false;
+  }
+  // RenameFile and SystemHeaderPragma are always directives
 
-  if (DisableLineMarkers) return;
+  CurLine = UserLoc.getLine();
+  if (IsLineDirective)
+    ++CurLine;
 
   CurFilename.clear();
-  CurFilename += SourceMgr.getPresumedLoc(Loc).getFilename();
+  CurFilename += UserLoc.getFilename();
   Lexer::Stringify(CurFilename);
   FileType = NewFileType;
 


More information about the cfe-commits mailing list