]> granicus.if.org Git - clang/commitdiff
Improve the printing of ranges when macros are involved.
authorRichard Trieu <rtrieu@google.com>
Thu, 24 Sep 2015 01:21:01 +0000 (01:21 +0000)
committerRichard Trieu <rtrieu@google.com>
Thu, 24 Sep 2015 01:21:01 +0000 (01:21 +0000)
Trace the ranges through the macro backtrace better.  This allows better
range highlighting through all levels of the macro bracktrace.  Also some
improvements to backtrace printer for omitting different backtraces.

Patch by Zhengkai Wu.

Differential Revision: http://reviews.llvm.org/D12379

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

include/clang/Basic/SourceManager.h
lib/Basic/SourceManager.cpp
lib/Frontend/DiagnosticRenderer.cpp
test/Index/fix-its.m
test/Misc/caret-diags-macros.c
test/Misc/diag-macro-backtrace2.c
test/Misc/reduced-diags-macros.cpp
test/Misc/serialized-diags.c

index ec8903e139322a867e6ece5cdcb791f4f4b22ffb..8efcd79cbcd04c6e993998eeb61cf16f1471f786 100644 (file)
@@ -1146,10 +1146,14 @@ public:
   /// \brief Tests whether the given source location represents a macro
   /// argument's expansion into the function-like macro definition.
   ///
+  /// \param StartLoc If non-null and function returns true, it is set to the
+  /// start location of the macro argument expansion.
+  ///
   /// Such source locations only appear inside of the expansion
   /// locations representing where a particular function-like macro was
   /// expanded.
-  bool isMacroArgExpansion(SourceLocation Loc) const;
+  bool isMacroArgExpansion(SourceLocation Loc,
+                           SourceLocation *StartLoc = nullptr) const;
 
   /// \brief Tests whether the given source location represents the expansion of
   /// a macro body.
index 32894f2eb5642712cd9fd423bdd72b78a0eb2ada..5e408c98d3277bfad5ead43ee7663756385fe2c4 100644 (file)
@@ -1004,12 +1004,17 @@ SourceManager::getExpansionRange(SourceLocation Loc) const {
   return Res;
 }
 
-bool SourceManager::isMacroArgExpansion(SourceLocation Loc) const {
+bool SourceManager::isMacroArgExpansion(SourceLocation Loc,
+                                        SourceLocation *StartLoc) const {
   if (!Loc.isMacroID()) return false;
 
   FileID FID = getFileID(Loc);
   const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
-  return Expansion.isMacroArgExpansion();
+  if (!Expansion.isMacroArgExpansion()) return false;
+
+  if (StartLoc)
+    *StartLoc = Expansion.getExpansionLocStart();
+  return true;
 }
 
 bool SourceManager::isMacroBodyExpansion(SourceLocation Loc) const {
index 0c94083051daae5fedd675ef12839664e2cfda74..923d5e97c139d546469e5b7628b6660525890ded 100644 (file)
@@ -306,6 +306,38 @@ void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
   }
 }
 
+/// A recursive function to trace all possible backtrace locations
+/// to match the \p CaretLocFileID.
+static SourceLocation retrieveMacroLocation(SourceLocation Loc,
+                                            FileID MacroFileID,
+                                            FileID CaretFileID,
+                                            bool getBeginLoc,
+                                            const SourceManager *SM) {
+  if (MacroFileID == CaretFileID) return Loc;
+  if (!Loc.isMacroID()) return SourceLocation();
+
+  SourceLocation MacroLocation, MacroArgLocation;
+
+  if (SM->isMacroArgExpansion(Loc)) {
+    MacroLocation = SM->getImmediateSpellingLoc(Loc);
+    MacroArgLocation = getBeginLoc ? SM->getImmediateExpansionRange(Loc).first
+                                   : SM->getImmediateExpansionRange(Loc).second;
+  } else {
+    MacroLocation = getBeginLoc ? SM->getImmediateExpansionRange(Loc).first
+                                : SM->getImmediateExpansionRange(Loc).second;
+    MacroArgLocation = SM->getImmediateSpellingLoc(Loc);
+  }
+
+  MacroFileID = SM->getFileID(MacroLocation);
+  MacroLocation = retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID,
+                                        getBeginLoc, SM);
+  if (MacroLocation.isValid()) return MacroLocation;
+
+  MacroFileID = SM->getFileID(MacroArgLocation);
+  return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID,
+                               getBeginLoc, SM);
+}
+
 // Helper function to fix up source ranges.  It takes in an array of ranges,
 // and outputs an array of ranges where we want to draw the range highlighting
 // around the location specified by CaretLoc.
@@ -323,9 +355,9 @@ static void mapDiagnosticRanges(
     const SourceManager *SM) {
   FileID CaretLocFileID = SM->getFileID(CaretLoc);
 
-  for (ArrayRef<CharSourceRange>::const_iterator I = Ranges.begin(),
-       E = Ranges.end();
-       I != E; ++I) {
+  for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
+    if (I->isInvalid()) continue;
+
     SourceLocation Begin = I->getBegin(), End = I->getEnd();
     bool IsTokenRange = I->isTokenRange();
 
@@ -354,27 +386,17 @@ static void mapDiagnosticRanges(
       }
     }
 
-    while (Begin.isMacroID() && BeginFileID != CaretLocFileID) {
-      if (SM->isMacroArgExpansion(Begin)) {
-        Begin = SM->getImmediateSpellingLoc(Begin);
-        End = SM->getImmediateSpellingLoc(End);
-      } else {
-        Begin = SM->getImmediateExpansionRange(Begin).first;
-        End = SM->getImmediateExpansionRange(End).second;
-      }
-      BeginFileID = SM->getFileID(Begin);
-      if (BeginFileID != SM->getFileID(End)) {
-        // FIXME: Ugly hack to stop a crash; this code is making bad
-        // assumptions and it's too complicated for me to reason
-        // about.
-        Begin = End = SourceLocation();
-        break;
-      }
-    }
+    // Do the backtracking.
+    Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
+                                  true /*getBeginLoc*/, SM);
+    End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
+                                false /*getBeginLoc*/, SM);
+    if (Begin.isInvalid() || End.isInvalid()) continue;
 
     // Return the spelling location of the beginning and end of the range.
     Begin = SM->getSpellingLoc(Begin);
     End = SM->getSpellingLoc(End);
+
     SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End),
                                              IsTokenRange));
   }
@@ -417,20 +439,37 @@ void DiagnosticRenderer::emitSingleMacroExpansion(
                  SpellingRanges, None, &SM);
 }
 
+/// Check that the macro argument location of Loc starts with ArgumentLoc.
+/// The starting location of the macro expansions is used to differeniate
+/// different macro expansions.
+static bool checkLocForMacroArgExpansion(SourceLocation Loc,
+                                         const SourceManager &SM,
+                                         SourceLocation ArgumentLoc) {
+  SourceLocation MacroLoc;
+  if (SM.isMacroArgExpansion(Loc, &MacroLoc)) {
+    if (ArgumentLoc == MacroLoc) return true;
+  }
+
+  return false;
+}
+
+/// Check if all the locations in the range have the same macro argument
+/// expansion, and that that expansion starts with ArgumentLoc.
 static bool checkRangeForMacroArgExpansion(CharSourceRange Range,
-                                           const SourceManager &SM) {
+                                           const SourceManager &SM,
+                                           SourceLocation ArgumentLoc) {
   SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd();
   while (BegLoc != EndLoc) {
-    if (!SM.isMacroArgExpansion(BegLoc))
+    if (!checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc))
       return false;
     BegLoc.getLocWithOffset(1);
   }
 
-  return SM.isMacroArgExpansion(BegLoc);
+  return checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc);
 }
 
-/// A helper function to check if the current ranges are all inside
-/// the macro expansions.
+/// A helper function to check if the current ranges are all inside the same
+/// macro argument expansion as Loc.
 static bool checkRangesForMacroArgExpansion(SourceLocation Loc,
                                             ArrayRef<CharSourceRange> Ranges,
                                             const SourceManager &SM) {
@@ -439,12 +478,26 @@ static bool checkRangesForMacroArgExpansion(SourceLocation Loc,
   SmallVector<CharSourceRange, 4> SpellingRanges;
   mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
 
-  if (!SM.isMacroArgExpansion(Loc))
+  /// Count all valid ranges.
+  unsigned ValidCount = 0;
+  for (auto I : Ranges)
+    if (I.isValid()) ValidCount++;
+
+  if (ValidCount > SpellingRanges.size())
     return false;
 
-  for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I)
-    if (!checkRangeForMacroArgExpansion(*I, SM))
+  /// To store the source location of the argument location.
+  SourceLocation ArgumentLoc;
+
+  /// Set the ArgumentLoc to the beginning location of the expansion of Loc
+  /// so to check if the ranges expands to the same beginning location.
+  if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc))
+    return false;
+
+  for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) {
+    if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc))
       return false;
+  }
 
   return true;
 }
index fabcdb2905f66bddba6fb7a5d7426c2a7cb259ea..65aa81dc8663880675a5813dee9d87f489965d95 100644 (file)
@@ -20,7 +20,3 @@ void _rdar_12584554_A (volatile const void * object, volatile const void * selec
 @end
 
 // CHECK: FIX-IT: Insert "@" at 18:22
-// CHECK: fix-its.m:9:28: note: expanded from macro '_rdar_12584554_C'
-// CHECK: Number FIX-ITs = 0
-// CHECK: fix-its.m:7:77: note: expanded from macro '_rdar_12584554_B'
-// CHECK: Number FIX-ITs = 0
index 316454c513b648d1f72864a5a061c5fc45e14e84..d499400b286f410527b1a592670dc0f84eaf0039 100644 (file)
@@ -16,9 +16,6 @@ void foo() {
 void bar() {
   C(1);
   // CHECK: {{.*}}:17:5: warning: expression result unused
-  // CHECK: {{.*}}:15:16: note: expanded from macro 'C'
-  // CHECK: {{.*}}:14:16: note: expanded from macro 'B'
-  // CHECK: {{.*}}:13:14: note: expanded from macro 'A'
 }
 
 // rdar://7597492
@@ -41,48 +38,45 @@ void baz(char *Msg) {
 
 void test() {
   macro_args3(11);
-  // CHECK: {{.*}}:43:15: warning: expression result unused
+  // CHECK: {{.*}}:40:15: warning: expression result unused
   // Also check that the 'caret' printing agrees with the location here where
   // its easy to FileCheck.
   // CHECK-NEXT:      macro_args3(11);
   // CHECK-NEXT: {{^              \^~}}
-  // CHECK: {{.*}}:36:36: note: expanded from macro 'macro_args3'
-  // CHECK: {{.*}}:35:36: note: expanded from macro 'macro_args2'
-  // CHECK: {{.*}}:34:24: note: expanded from macro 'macro_args1'
 
   macro_many_args3(
     1,
     2,
     3);
-  // CHECK: {{.*}}:55:5: warning: expression result unused
-  // CHECK: {{.*}}:40:55: note: expanded from macro 'macro_many_args3'
-  // CHECK: {{.*}}:39:55: note: expanded from macro 'macro_many_args2'
-  // CHECK: {{.*}}:38:35: note: expanded from macro 'macro_many_args1'
+  // CHECK: {{.*}}:49:5: warning: expression result unused
+  // CHECK: {{.*}}:37:55: note: expanded from macro 'macro_many_args3'
+  // CHECK: {{.*}}:36:55: note: expanded from macro 'macro_many_args2'
+  // CHECK: {{.*}}:35:35: note: expanded from macro 'macro_many_args1'
 
   macro_many_args3(
     1,
     M2,
     3);
-  // CHECK: {{.*}}:64:5: warning: expression result unused
+  // CHECK: {{.*}}:58:5: warning: expression result unused
   // CHECK: {{.*}}:4:12: note: expanded from macro 'M2'
-  // CHECK: {{.*}}:40:55: note: expanded from macro 'macro_many_args3'
-  // CHECK: {{.*}}:39:55: note: expanded from macro 'macro_many_args2'
-  // CHECK: {{.*}}:38:35: note: expanded from macro 'macro_many_args1'
+  // CHECK: {{.*}}:37:55: note: expanded from macro 'macro_many_args3'
+  // CHECK: {{.*}}:36:55: note: expanded from macro 'macro_many_args2'
+  // CHECK: {{.*}}:35:35: note: expanded from macro 'macro_many_args1'
 
   macro_many_args3(
     1,
     macro_args2(22),
     3);
-  // CHECK: {{.*}}:74:17: warning: expression result unused
+  // CHECK: {{.*}}:68:17: warning: expression result unused
   // This caret location needs to be printed *inside* a different macro's
   // arguments.
   // CHECK-NEXT:        macro_args2(22),
   // CHECK-NEXT: {{^                \^~}}
-  // CHECK: {{.*}}:35:36: note: expanded from macro 'macro_args2'
-  // CHECK: {{.*}}:34:24: note: expanded from macro 'macro_args1'
-  // CHECK: {{.*}}:40:55: note: expanded from macro 'macro_many_args3'
-  // CHECK: {{.*}}:39:55: note: expanded from macro 'macro_many_args2'
-  // CHECK: {{.*}}:38:35: note: expanded from macro 'macro_many_args1'
+  // CHECK: {{.*}}:32:36: note: expanded from macro 'macro_args2'
+  // CHECK: {{.*}}:31:24: note: expanded from macro 'macro_args1'
+  // CHECK: {{.*}}:37:55: note: expanded from macro 'macro_many_args3'
+  // CHECK: {{.*}}:36:55: note: expanded from macro 'macro_many_args2'
+  // CHECK: {{.*}}:35:35: note: expanded from macro 'macro_many_args1'
 }
 
 #define variadic_args1(x, y, ...) y
@@ -91,12 +85,12 @@ void test() {
 
 void test2() {
   variadic_args3(1, 22, 3, 4);
-  // CHECK: {{.*}}:93:21: warning: expression result unused
+  // CHECK: {{.*}}:87:21: warning: expression result unused
   // CHECK-NEXT:      variadic_args3(1, 22, 3, 4);
   // CHECK-NEXT: {{^                    \^~}}
-  // CHECK: {{.*}}:90:53: note: expanded from macro 'variadic_args3'
-  // CHECK: {{.*}}:89:50: note: expanded from macro 'variadic_args2'
-  // CHECK: {{.*}}:88:35: note: expanded from macro 'variadic_args1'
+  // CHECK: {{.*}}:84:53: note: expanded from macro 'variadic_args3'
+  // CHECK: {{.*}}:83:50: note: expanded from macro 'variadic_args2'
+  // CHECK: {{.*}}:82:35: note: expanded from macro 'variadic_args1'
 }
 
 #define variadic_pasting_args1(x, y, z) y
@@ -107,35 +101,35 @@ void test2() {
 
 void test3() {
   variadic_pasting_args3(1, 2, 3, 4);
-  // CHECK: {{.*}}:109:32: warning: expression result unused
-  // CHECK: {{.*}}:105:72: note: expanded from macro 'variadic_pasting_args3'
-  // CHECK: {{.*}}:103:68: note: expanded from macro 'variadic_pasting_args2'
-  // CHECK: {{.*}}:102:41: note: expanded from macro 'variadic_pasting_args1'
+  // CHECK: {{.*}}:103:32: warning: expression result unused
+  // CHECK: {{.*}}:99:72: note: expanded from macro 'variadic_pasting_args3'
+  // CHECK: {{.*}}:97:68: note: expanded from macro 'variadic_pasting_args2'
+  // CHECK: {{.*}}:96:41: note: expanded from macro 'variadic_pasting_args1'
 
   variadic_pasting_args3a(1, 2, 3, 4);
-  // CHECK:        {{.*}}:115:3: warning: expression result unused
+  // CHECK:        {{.*}}:109:3: warning: expression result unused
   // CHECK-NEXT:     variadic_pasting_args3a(1, 2, 3, 4);
-  // CHECK-NEXT: {{  \^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}}
-  // CHECK:        {{.*}}:106:44: note: expanded from macro 'variadic_pasting_args3a'
+  // CHECK-NEXT: {{  \^~~~~~~~~~~~~~~~~~~~~~~}}
+  // CHECK:        {{.*}}:100:44: note: expanded from macro 'variadic_pasting_args3a'
   // CHECK-NEXT:   #define variadic_pasting_args3a(x, y, ...) variadic_pasting_args2a(x, y, __VA_ARGS__)
-  // CHECK-NEXT: {{                                           \^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}}
-  // CHECK:        {{.*}}:104:70: note: expanded from macro 'variadic_pasting_args2a'
+  // CHECK-NEXT: {{                                           \^~~~~~~~~~~~~~~~~~~~~~~}}
+  // CHECK:        {{.*}}:98:70: note: expanded from macro 'variadic_pasting_args2a'
   // CHECK-NEXT:   #define variadic_pasting_args2a(x, y, ...) variadic_pasting_args1(x, y ## __VA_ARGS__)
   // CHECK-NEXT: {{                                                                     \^~~~~~~~~~~~~~~~}}
-  // CHECK:        {{.*}}:102:41: note: expanded from macro 'variadic_pasting_args1'
+  // CHECK:        {{.*}}:96:41: note: expanded from macro 'variadic_pasting_args1'
   // CHECK-NEXT:   #define variadic_pasting_args1(x, y, z) y
   // CHECK-NEXT: {{                                        \^}}
 }
 
 #define BAD_CONDITIONAL_OPERATOR (2<3)?2:3
 int test4 = BAD_CONDITIONAL_OPERATOR+BAD_CONDITIONAL_OPERATOR;
-// CHECK:         {{.*}}:130:39: note: expanded from macro 'BAD_CONDITIONAL_OPERATOR'
+// CHECK:         {{.*}}:124:39: note: expanded from macro 'BAD_CONDITIONAL_OPERATOR'
 // CHECK-NEXT:    #define BAD_CONDITIONAL_OPERATOR (2<3)?2:3
 // CHECK-NEXT: {{^                                      \^}}
-// CHECK:         {{.*}}:130:39: note: expanded from macro 'BAD_CONDITIONAL_OPERATOR'
+// CHECK:         {{.*}}:124:39: note: expanded from macro 'BAD_CONDITIONAL_OPERATOR'
 // CHECK-NEXT:    #define BAD_CONDITIONAL_OPERATOR (2<3)?2:3
 // CHECK-NEXT: {{^                                      \^}}
-// CHECK:         {{.*}}:130:39: note: expanded from macro 'BAD_CONDITIONAL_OPERATOR'
+// CHECK:         {{.*}}:124:39: note: expanded from macro 'BAD_CONDITIONAL_OPERATOR'
 // CHECK-NEXT:    #define BAD_CONDITIONAL_OPERATOR (2<3)?2:3
 // CHECK-NEXT: {{^                                 ~~~~~\^~~~}}
 
@@ -143,32 +137,32 @@ int test4 = BAD_CONDITIONAL_OPERATOR+BAD_CONDITIONAL_OPERATOR;
 #define TWOL (2<
 #define X 1+TWOL 3) QMARK 4:5
 int x = X;
-// CHECK:         {{.*}}:145:9: note: place parentheses around the '+' expression to silence this warning
+// CHECK:         {{.*}}:139:9: note: place parentheses around the '+' expression to silence this warning
 // CHECK-NEXT:    int x = X;
 // CHECK-NEXT: {{^        \^}}
-// CHECK-NEXT:    {{.*}}:144:21: note: expanded from macro 'X'
+// CHECK-NEXT:    {{.*}}:138:21: note: expanded from macro 'X'
 // CHECK-NEXT:    #define X 1+TWOL 3) QMARK 4:5
 // CHECK-NEXT: {{^          ~~~~~~~~~ \^}}
-// CHECK-NEXT:    {{.*}}:142:15: note: expanded from macro 'QMARK'
+// CHECK-NEXT:    {{.*}}:136:15: note: expanded from macro 'QMARK'
 // CHECK-NEXT:    #define QMARK ?
 // CHECK-NEXT: {{^              \^}}
-// CHECK-NEXT:    {{.*}}:145:9: note: place parentheses around the '?:' expression to evaluate it first
+// CHECK-NEXT:    {{.*}}:139:9: note: place parentheses around the '?:' expression to evaluate it first
 // CHECK-NEXT:    int x = X;
 // CHECK-NEXT: {{^        \^}}
-// CHECK-NEXT:    {{.*}}:144:21: note: expanded from macro 'X'
+// CHECK-NEXT:    {{.*}}:138:21: note: expanded from macro 'X'
 // CHECK-NEXT:    #define X 1+TWOL 3) QMARK 4:5
 // CHECK-NEXT: {{^            ~~~~~~~~\^~~~~~~~~}}
 
 #define ONEPLUS 1+
 #define Y ONEPLUS (2<3) QMARK 4:5
 int y = Y;
-// CHECK:         {{.*}}:164:9: warning: operator '?:' has lower precedence than '+'; '+' will be evaluated first
+// CHECK:         {{.*}}:158:9: warning: operator '?:' has lower precedence than '+'; '+' will be evaluated first
 // CHECK-NEXT:    int y = Y;
 // CHECK-NEXT: {{^        \^}}
-// CHECK-NEXT:    {{.*}}:163:25: note: expanded from macro 'Y'
+// CHECK-NEXT:    {{.*}}:157:25: note: expanded from macro 'Y'
 // CHECK-NEXT:    #define Y ONEPLUS (2<3) QMARK 4:5
 // CHECK-NEXT: {{^          ~~~~~~~~~~~~~ \^}}
-// CHECK-NEXT:    {{.*}}:142:15: note: expanded from macro 'QMARK'
+// CHECK-NEXT:    {{.*}}:136:15: note: expanded from macro 'QMARK'
 // CHECK-NEXT:    #define QMARK ?
 // CHECK-NEXT: {{^              \^}}
 
@@ -179,10 +173,10 @@ void foo_aa(char* s)
 #define /* */ BARC(c, /* */b, a) (a + b ? c : c)
   iequals(__LINE__, BARC(123, (456 < 345), 789), 8);
 }
-// CHECK:         {{.*}}:180:21: warning: operator '?:' has lower precedence than '+'
+// CHECK:         {{.*}}:174:21: warning: operator '?:' has lower precedence than '+'
 // CHECK-NEXT:      iequals(__LINE__, BARC(123, (456 < 345), 789), 8);
 // CHECK-NEXT: {{^                    \^~~~~~~~~~~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT:    {{.*}}:179:41: note: expanded from macro 'BARC'
+// CHECK-NEXT:    {{.*}}:173:41: note: expanded from macro 'BARC'
 // CHECK-NEXT:    #define /* */ BARC(c, /* */b, a) (a + b ? c : c)
 // CHECK-NEXT: {{^                                  ~~~~~ \^}}
 
@@ -193,16 +187,16 @@ void foo_aa(char* s)
 #if UTARG_MAX_U
 #endif
 
-// CHECK:         {{.*}}:193:5: warning: left side of operator converted from negative value to unsigned: -1 to 18446744073709551615
+// CHECK:         {{.*}}:187:5: warning: left side of operator converted from negative value to unsigned: -1 to 18446744073709551615
 // CHECK-NEXT:    #if UTARG_MAX_U
 // CHECK-NEXT: {{^    \^~~~~~~~~~~}}
-// CHECK-NEXT:    {{.*}}:191:21: note: expanded from macro 'UTARG_MAX_U'
+// CHECK-NEXT:    {{.*}}:185:21: note: expanded from macro 'UTARG_MAX_U'
 // CHECK-NEXT:    #define UTARG_MAX_U APPEND (MAX_UINT, UL)
 // CHECK-NEXT: {{^                    \^~~~~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT:    {{.*}}:190:27: note: expanded from macro 'APPEND'
+// CHECK-NEXT:    {{.*}}:184:27: note: expanded from macro 'APPEND'
 // CHECK-NEXT:    #define APPEND(NUM, SUFF) APPEND2(NUM, SUFF)
 // CHECK-NEXT: {{^                          \^~~~~~~~~~~~~~~~~~}}
-// CHECK-NEXT:    {{.*}}:189:31: note: expanded from macro 'APPEND2'
+// CHECK-NEXT:    {{.*}}:183:31: note: expanded from macro 'APPEND2'
 // CHECK-NEXT:    #define APPEND2(NUM, SUFF) -1 != NUM ## SUFF
 // CHECK-NEXT: {{^                           ~~ \^  ~~~~~~~~~~~}}
 
@@ -213,15 +207,16 @@ unsigned long strlen_test(const char *s);
 #define Cstrlen(a)  strlen_test(a)
 #define Csprintf    sprintf2
 void f(char* pMsgBuf, char* pKeepBuf) {
-Csprintf(pMsgBuf,"\nEnter minimum anagram length (2-%1d): ", Cstrlen(pKeepBuf));
+Csprintf(pMsgBuf,"\nEnter minimum anagram length (2-%1d): ", strlen_test(pKeepBuf));
+// FIXME: Change test to use 'Cstrlen' instead of 'strlen_test' when macro printing is fixed.
 }
-// CHECK:         {{.*}}:216:62: warning: format specifies type 'int' but the argument has type 'unsigned long'
-// CHECK-NEXT:    Csprintf(pMsgBuf,"\nEnter minimum anagram length (2-%1d): ", Cstrlen(pKeepBuf));
-// CHECK-NEXT: {{^                                                    ~~~      \^}}
+// CHECK:         {{.*}}:210:62: warning: format specifies type 'int' but the argument has type 'unsigned long'
+// CHECK-NEXT:    Csprintf(pMsgBuf,"\nEnter minimum anagram length (2-%1d): ", strlen_test(pKeepBuf));
+// CHECK-NEXT: {{^                                                    ~~~      \^~~~~~~~~~~~~~~~~~~~~}}
 // CHECK-NEXT: {{^                                                    %1lu}}
-// CHECK-NEXT:    {{.*}}:213:21: note: expanded from macro 'Cstrlen'
-// CHECK-NEXT:    #define Cstrlen(a)  strlen_test(a)
+// CHECK-NEXT:    {{.*}}:208:21: note: expanded from macro 'Csprintf'
+// CHECK-NEXT:    #define Csprintf    sprintf2
 // CHECK-NEXT: {{^                    \^}}
-// CHECK-NEXT:    {{.*}}:212:56: note: expanded from macro 'sprintf2'
+// CHECK-NEXT:    {{.*}}:206:56: note: expanded from macro 'sprintf2'
 // CHECK-NEXT:      __builtin___sprintf_chk (str, 0, __darwin_obsz(str), __VA_ARGS__)
-// CHECK-NEXT: {{^                                                       \^}}
+// CHECK-NEXT: {{^                                                       \^~~~~~~~~~~}}
index b5be0ae2fef7c92ab87658443ac95f4999cd2b8d..af79bbde6009bdf0901f5d624c408c012a919e80 100644 (file)
@@ -16,7 +16,7 @@ void PR16799() {
   // CHECK: :15:3: error: invalid operands to binary expression
   // CHECK:       ('const char *' and 'int')
   // CHECK:   a(str);
-  // CHECK:   ^ ~~~
+  // CHECK:   ^~~~~~
   // CHECK: :3:11: note: expanded from macro 'a'
   // CHECK: #define a b
   // CHECK:           ^
@@ -28,7 +28,7 @@ void PR16799() {
   // CHECK:              ^~~~
   // CHECK: :6:15: note: expanded from macro 'd'
   // CHECK: #define d(x) x*1
-  // CHECK:               ^~
+  // CHECK:              ~^~
 
   e(str);
   // CHECK: :33:5: warning: expression result unused
index d64c267a9e46950a11e13abc611f7607a0db7de2..1ee6311d1980e7ade71159750c474dd06db8f0fc 100644 (file)
@@ -11,7 +11,7 @@ NO_DEFINITION(b);
 // CHECK-NEXT: ~~~~~~~~~~~~~~^~
 // CHECK-NEXT: {{.*}}:3:34: note: expanded from macro 'NO_INITIATION'
 // CHECK-NEXT: #define NO_INITIATION(x) int a = x * 2
-// CHECK-NEXT:                                  ^
+// CHECK-NEXT:                              ~   ^
 
 // CHECK: {{.*}}:7:15: error: use of undeclared identifier 'b'
 // CHECK-NEXT: NO_DEFINITION(b);
@@ -27,3 +27,18 @@ int  p = SWAP_ARGU(3, x);
 // CHECK: {{.*}}:25:23: error: use of undeclared identifier 'x'
 // CHECK-NEXT: int  p = SWAP_ARGU(3, x);
 // CHECK-NEXT:                       ^
+
+#define APPLY(f,x,y) x f y
+
+struct node {
+};
+
+node ff;
+
+int r = APPLY(+,ff,1);
+// CHECK: {{.*}}:38:15: error: invalid operands to binary expression ('node' and 'int')
+// CHECK-NEXT: int r = APPLY(+,ff,1);
+// CHECK-NEXT:               ^ ~~ ~
+// CHECK-NEXT: {{.*}}:31:24: note: expanded from macro 'APPLY'
+// CHECK-NEXT: #define APPLY(f,x,y) x f y
+// CHECK-NEXT:                      ~ ^ ~
\ No newline at end of file
index 1290b4ea9f33bb314495f1183d80b5275b4a0b56..e401477a2ebdcae290f55446eebe0d50090804a7 100644 (file)
@@ -55,7 +55,6 @@ void rdar11040133() {
 // CHECK: Range: {{.*[/\\]}}serialized-diags.c:22:3 {{.*[/\\]}}serialized-diags.c:22:6
 // CHECK: Range: {{.*[/\\]}}serialized-diags.c:22:13 {{.*[/\\]}}serialized-diags.c:22:18
 // CHECK: +-{{.*[/\\]}}serialized-diags.c:20:15: note: expanded from macro 'false' []
-// CHECK: +-Range: {{.*[/\\]}}serialized-diags.c:22:3 {{.*[/\\]}}serialized-diags.c:22:6
 // CHECK: +-Range: {{.*[/\\]}}serialized-diags.c:20:15 {{.*[/\\]}}serialized-diags.c:20:16
 // CHECK: +-{{.*[/\\]}}serialized-diags.c:19:1: note: 'taz' declared here []
 // CHECK: {{.*[/\\]}}serialized-diags.h:5:7: warning: incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int' [-Wint-conversion]