Index: cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp =================================================================== --- cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp +++ cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp @@ -423,6 +423,38 @@ SpellingRanges, None, &SM); } +static bool checkRangeForMacroArgExpansion(CharSourceRange Range, + const SourceManager &SM) { + SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd(); + while (BegLoc != EndLoc) { + if (!SM.isMacroArgExpansion(BegLoc)) + return false; + BegLoc.getLocWithOffset(1); + } + + return SM.isMacroArgExpansion(BegLoc); +} + +/// A helper function to check if the current ranges are all inside +/// the macro expansions. +static bool checkRangesForMacroArgExpansion(SourceLocation Loc, + ArrayRef Ranges, + const SourceManager &SM) { + assert(Loc.isMacroID() && "Must be a macro expansion!"); + + SmallVector SpellingRanges; + mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); + + if (!SM.isMacroArgExpansion(Loc)) + return false; + + for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) + if (!checkRangeForMacroArgExpansion(*I, SM)) + return false; + + return true; +} + /// \brief Recursively emit notes for each macro expansion and caret /// diagnostics where appropriate. /// @@ -443,12 +475,19 @@ // Produce a stack of macro backtraces. SmallVector LocationStack; + unsigned IgnoredEnd = 0; while (Loc.isMacroID()) { LocationStack.push_back(Loc); + if (checkRangesForMacroArgExpansion(Loc, Ranges, SM)) + IgnoredEnd = LocationStack.size(); + Loc = SM.getImmediateMacroCallerLoc(Loc); assert(!Loc.isInvalid() && "must have a valid source location here"); } + LocationStack.erase(LocationStack.begin(), + LocationStack.begin() + IgnoredEnd); + unsigned MacroDepth = LocationStack.size(); unsigned MacroLimit = DiagOpts->MacroBacktraceLimit; if (MacroDepth <= MacroLimit || MacroLimit == 0) { Index: cfe/trunk/test/Misc/diag-presumed.c =================================================================== --- cfe/trunk/test/Misc/diag-presumed.c +++ cfe/trunk/test/Misc/diag-presumed.c @@ -6,13 +6,11 @@ X(int n = error); // PRESUMED: diag-presumed.c:101:11: error: use of undeclared identifier 'error' -// PRESUMED: diag-presumed.c:100:14: note: expanded from // SPELLING: diag-presumed.c:6:11: error: use of undeclared identifier 'error' -// SPELLING: diag-presumed.c:5:14: note: expanded from ; -// PRESUMED: diag-presumed.c:108:1: error: extra ';' outside of a functio -// SPELLING: diag-presumed.c:13:1: error: extra ';' outside of a functio +// PRESUMED: diag-presumed.c:106:1: error: extra ';' outside of a functio +// SPELLING: diag-presumed.c:11:1: error: extra ';' outside of a functio # 1 "thing1.cc" 1 # 1 "thing1.h" 1 @@ -24,13 +22,13 @@ // SPELLING-NOT: extra ';' another error; -// PRESUMED: included from {{.*}}diag-presumed.c:112: +// PRESUMED: included from {{.*}}diag-presumed.c:110: // PRESUMED: from thing1.cc:1: // PRESUMED: from thing1.h:1: // PRESUMED: systemheader.h:7:1: error: unknown type name 'another' // SPELLING-NOT: included from -// SPELLING: diag-presumed.c:26:1: error: unknown type name 'another' +// SPELLING: diag-presumed.c:24:1: error: unknown type name 'another' # 1 "thing1.h" 2 # 1 "thing1.cc" 2 Index: cfe/trunk/test/Misc/reduced-diags-macros-backtrace.cpp =================================================================== --- cfe/trunk/test/Misc/reduced-diags-macros-backtrace.cpp +++ cfe/trunk/test/Misc/reduced-diags-macros-backtrace.cpp @@ -0,0 +1,47 @@ +// RUN: not %clang_cc1 -fsyntax-only -fmacro-backtrace-limit 0 %s 2>&1 | FileCheck %s --check-prefix=ALL +// RUN: not %clang_cc1 -fsyntax-only -fmacro-backtrace-limit 2 %s 2>&1 | FileCheck %s --check-prefix=SKIP + +#define F(x) x + 1 +#define G(x) F(x) + 2 +#define ADD(x,y) G(x) + y +#define LEVEL4(x) ADD(p,x) +#define LEVEL3(x) LEVEL4(x) +#define LEVEL2(x) LEVEL3(x) +#define LEVEL1(x) LEVEL2(x) + +int a = LEVEL1(b); + +// ALL: {{.*}}:12:9: error: use of undeclared identifier 'p' +// ALL-NEXT: int a = LEVEL1(b); +// ALL-NEXT: ^ +// ALL-NEXT: {{.*}}:10:19: note: expanded from macro 'LEVEL1' +// ALL-NEXT: #define LEVEL1(x) LEVEL2(x) +// ALL-NEXT: ^ +// ALL-NEXT: {{.*}}:9:19: note: expanded from macro 'LEVEL2' +// ALL-NEXT: #define LEVEL2(x) LEVEL3(x) +// ALL-NEXT: ^ +// ALL-NEXT: {{.*}}:8:19: note: expanded from macro 'LEVEL3' +// ALL-NEXT: #define LEVEL3(x) LEVEL4(x) +// ALL-NEXT: ^ +// ALL-NEXT: {{.*}}:7:23: note: expanded from macro 'LEVEL4' +// ALL-NEXT: #define LEVEL4(x) ADD(p,x) +// ALL-NEXT: ^ +// ALL-NEXT: {{.*}}:12:16: error: use of undeclared identifier 'b' +// ALL-NEXT: int a = LEVEL1(b); +// ALL-NEXT: ^ +// ALL-NEXT: 2 errors generated. + +// SKIP: {{.*}}:12:9: error: use of undeclared identifier 'p' +// SKIP-NEXT: int a = LEVEL1(b); +// SKIP-NEXT: ^ +// SKIP-NEXT: {{.*}}:10:19: note: expanded from macro 'LEVEL1' +// SKIP-NEXT: #define LEVEL1(x) LEVEL2(x) +// SKIP-NEXT: ^ +// SKIP-NEXT: note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) +// SKIP-NEXT: {{.*}}:7:23: note: expanded from macro 'LEVEL4' +// SKIP-NEXT: #define LEVEL4(x) ADD(p,x) +// SKIP-NEXT: ^ +// SKIP-NEXT: {{.*}}:12:16: error: use of undeclared identifier 'b' +// SKIP-NEXT: int a = LEVEL1(b); +// SKIP-NEXT: ^ +// SKIP-NEXT: 2 errors generated. Index: cfe/trunk/test/Misc/reduced-diags-macros.cpp =================================================================== --- cfe/trunk/test/Misc/reduced-diags-macros.cpp +++ cfe/trunk/test/Misc/reduced-diags-macros.cpp @@ -0,0 +1,29 @@ +// RUN: not %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck %s -strict-whitespace + +#define NO_INITIATION(x) int a = x * 2 +#define NO_DEFINITION(x) int c = x * 2 + +NO_INITIATION(a); +NO_DEFINITION(b); + +// CHECK: {{.*}}:6:15: warning: variable 'a' is uninitialized when used within its own initialization +// CHECK-NEXT: NO_INITIATION(a); +// 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: {{.*}}:7:15: error: use of undeclared identifier 'b' +// CHECK-NEXT: NO_DEFINITION(b); +// CHECK-NEXT: ^ + + +#define F(x) x + 1 +#define ADD(x,y) y + F(x) +#define SWAP_ARGU(x,y) ADD(y,x) + +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: ^ Index: cfe/trunk/test/Preprocessor/macro_arg_slocentry_merge.c =================================================================== --- cfe/trunk/test/Preprocessor/macro_arg_slocentry_merge.c +++ cfe/trunk/test/Preprocessor/macro_arg_slocentry_merge.c @@ -3,5 +3,3 @@ #include "macro_arg_slocentry_merge.h" // CHECK: macro_arg_slocentry_merge.h:7:19: error: unknown type name 'win' -// CHECK: macro_arg_slocentry_merge.h:5:16: note: expanded from macro 'WINDOW' -// CHECK: macro_arg_slocentry_merge.h:6:18: note: expanded from macro 'P_'