vsk created this revision.

This patch teaches the preprocessor to report more precise source ranges for 
code that is skipped due to conditional directives.

The new behavior includes the '#' from the opening directive and the full text 
of the line containing the closing directive in the skipped area. This matches 
up clang's behavior (we don't IRGen the code between the closing "endif" and 
the end of a line).

This also affects the code coverage implementation. See llvm.org/PR34166 (this 
also happens to be rdar://problem/23224058).


https://reviews.llvm.org/D36642

Files:
  lib/Lex/PPDirectives.cpp
  test/CoverageMapping/preprocessor.c
  test/Index/skipped-ranges.c


Index: test/Index/skipped-ranges.c
===================================================================
--- test/Index/skipped-ranges.c
+++ test/Index/skipped-ranges.c
@@ -20,6 +20,6 @@
 #endif // cool
 
 // RUN: env CINDEXTEST_SHOW_SKIPPED_RANGES=1 c-index-test 
-test-annotate-tokens=%s:1:1:16:1 %s | FileCheck %s
-// CHECK: Skipping: [5:2 - 6:7]
-// CHECK: Skipping: [8:2 - 12:7]
-// CHECK: Skipping: [14:2 - 20:7]
+// CHECK: Skipping: [5:1 - 6:22]
+// CHECK: Skipping: [8:1 - 12:27]
+// CHECK: Skipping: [14:1 - 20:15]
Index: test/CoverageMapping/preprocessor.c
===================================================================
--- test/CoverageMapping/preprocessor.c
+++ test/CoverageMapping/preprocessor.c
@@ -3,7 +3,7 @@
                  // CHECK: func
 void func() {    // CHECK: File 0, [[@LINE]]:13 -> [[@LINE+5]]:2 = #0
   int i = 0;
-#ifdef MACRO     // CHECK-NEXT: Skipped,File 0, [[@LINE]]:2 -> [[@LINE+2]]:2 = 0
+#ifdef MACRO     // CHECK-NEXT: Skipped,File 0, [[@LINE]]:1 -> [[@LINE+2]]:7 = 0
   int x = i;
 #endif
 }
@@ -17,18 +17,18 @@
                  // CHECK: main
 int main() {     // CHECK-NEXT: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = #0
   int i = 0;
-#if 0            // CHECK-NEXT: Skipped,File 0, [[@LINE]]:2 -> [[@LINE+4]]:2 = 0
+#  if 0            // CHECK-NEXT: Skipped,File 0, [[@LINE]]:1 -> 
[[@LINE+4]]:29 = 0
   if(i == 0) {
     i = 1;
   }
-#endif
+#  endif // Mark me skipped!
 
 #if 1
                  // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #0
   if(i == 0) {   // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+2]]:4 = #1
     i = 1;
   }
-#else            // CHECK-NEXT: Skipped,File 0, [[@LINE]]:2 -> [[@LINE+5]]:2 = 0
+#else            // CHECK-NEXT: Skipped,File 0, [[@LINE]]:1 -> [[@LINE+5]]:7 = 0
   if(i == 1) {
     i = 0;
   }
Index: lib/Lex/PPDirectives.cpp
===================================================================
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -559,8 +559,28 @@
   CurPPLexer->LexingRawMode = false;
 
   if (Callbacks) {
+    const auto &SM = getSourceManager();
     SourceLocation BeginLoc = ElseLoc.isValid() ? ElseLoc : IfTokenLoc;
-    Callbacks->SourceRangeSkipped(SourceRange(BeginLoc, Tok.getLocation()));
+
+    // The begin loc tells us the start location of the directive, but we want
+    // to include the hash ('#') at the start of the line.
+    SourceLocation HashBeginLoc =
+        BeginLoc.getLocWithOffset(-SM.getSpellingColumnNumber(BeginLoc) + 1);
+
+    // We also want to skip the entire line containing the closing directive.
+    const char *TokStart = SM.getCharacterData(Tok.getLocation());
+    const char *EndOfLine = TokStart;
+    while (true) {
+      char C = *EndOfLine;
+      // We'll warn about reaching the end of file later.
+      if (C == '\0' || C == '\r' || C == '\n')
+        break;
+      ++EndOfLine;
+    }
+    SourceLocation DirectiveEndLoc =
+        Tok.getLocation().getLocWithOffset(EndOfLine - TokStart);
+
+    Callbacks->SourceRangeSkipped(SourceRange(HashBeginLoc, DirectiveEndLoc));
   }
 }
 


Index: test/Index/skipped-ranges.c
===================================================================
--- test/Index/skipped-ranges.c
+++ test/Index/skipped-ranges.c
@@ -20,6 +20,6 @@
 #endif // cool
 
 // RUN: env CINDEXTEST_SHOW_SKIPPED_RANGES=1 c-index-test -test-annotate-tokens=%s:1:1:16:1 %s | FileCheck %s
-// CHECK: Skipping: [5:2 - 6:7]
-// CHECK: Skipping: [8:2 - 12:7]
-// CHECK: Skipping: [14:2 - 20:7]
+// CHECK: Skipping: [5:1 - 6:22]
+// CHECK: Skipping: [8:1 - 12:27]
+// CHECK: Skipping: [14:1 - 20:15]
Index: test/CoverageMapping/preprocessor.c
===================================================================
--- test/CoverageMapping/preprocessor.c
+++ test/CoverageMapping/preprocessor.c
@@ -3,7 +3,7 @@
                  // CHECK: func
 void func() {    // CHECK: File 0, [[@LINE]]:13 -> [[@LINE+5]]:2 = #0
   int i = 0;
-#ifdef MACRO     // CHECK-NEXT: Skipped,File 0, [[@LINE]]:2 -> [[@LINE+2]]:2 = 0
+#ifdef MACRO     // CHECK-NEXT: Skipped,File 0, [[@LINE]]:1 -> [[@LINE+2]]:7 = 0
   int x = i;
 #endif
 }
@@ -17,18 +17,18 @@
                  // CHECK: main
 int main() {     // CHECK-NEXT: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = #0
   int i = 0;
-#if 0            // CHECK-NEXT: Skipped,File 0, [[@LINE]]:2 -> [[@LINE+4]]:2 = 0
+#  if 0            // CHECK-NEXT: Skipped,File 0, [[@LINE]]:1 -> [[@LINE+4]]:29 = 0
   if(i == 0) {
     i = 1;
   }
-#endif
+#  endif // Mark me skipped!
 
 #if 1
                  // CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #0
   if(i == 0) {   // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+2]]:4 = #1
     i = 1;
   }
-#else            // CHECK-NEXT: Skipped,File 0, [[@LINE]]:2 -> [[@LINE+5]]:2 = 0
+#else            // CHECK-NEXT: Skipped,File 0, [[@LINE]]:1 -> [[@LINE+5]]:7 = 0
   if(i == 1) {
     i = 0;
   }
Index: lib/Lex/PPDirectives.cpp
===================================================================
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -559,8 +559,28 @@
   CurPPLexer->LexingRawMode = false;
 
   if (Callbacks) {
+    const auto &SM = getSourceManager();
     SourceLocation BeginLoc = ElseLoc.isValid() ? ElseLoc : IfTokenLoc;
-    Callbacks->SourceRangeSkipped(SourceRange(BeginLoc, Tok.getLocation()));
+
+    // The begin loc tells us the start location of the directive, but we want
+    // to include the hash ('#') at the start of the line.
+    SourceLocation HashBeginLoc =
+        BeginLoc.getLocWithOffset(-SM.getSpellingColumnNumber(BeginLoc) + 1);
+
+    // We also want to skip the entire line containing the closing directive.
+    const char *TokStart = SM.getCharacterData(Tok.getLocation());
+    const char *EndOfLine = TokStart;
+    while (true) {
+      char C = *EndOfLine;
+      // We'll warn about reaching the end of file later.
+      if (C == '\0' || C == '\r' || C == '\n')
+        break;
+      ++EndOfLine;
+    }
+    SourceLocation DirectiveEndLoc =
+        Tok.getLocation().getLocWithOffset(EndOfLine - TokStart);
+
+    Callbacks->SourceRangeSkipped(SourceRange(HashBeginLoc, DirectiveEndLoc));
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to