From dea98de3fb4bea09b3ed3a68d90a03e21546b5b0 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Fri, 30 Nov 2012 06:19:40 +0000 Subject: [PATCH] Fix the computation of highlight ranges so we produce something sane when the beginning and end of the range are in different macro arguments. PR14399. llvm-svn: 168984 --- clang/lib/Frontend/DiagnosticRenderer.cpp | 40 +++++++++++++++++++++++-------- clang/test/Misc/caret-diags-macros.c | 14 +++++++++++ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/clang/lib/Frontend/DiagnosticRenderer.cpp b/clang/lib/Frontend/DiagnosticRenderer.cpp index 2d156f7..3143cc7 100644 --- a/clang/lib/Frontend/DiagnosticRenderer.cpp +++ b/clang/lib/Frontend/DiagnosticRenderer.cpp @@ -242,20 +242,40 @@ static void mapDiagnosticRanges( SourceLocation Begin = I->getBegin(), End = I->getEnd(); bool IsTokenRange = I->isTokenRange(); - // Search the macro caller chain for the beginning of the range. - while (Begin.isMacroID() && SM->getFileID(Begin) != CaretLocFileID) - Begin = SM->getImmediateMacroCallerLoc(Begin); - - // Search the macro caller chain for the beginning of the range. - while (End.isMacroID() && SM->getFileID(End) != CaretLocFileID) { - // The computation of the next End is an inlined version of - // getImmediateMacroCallerLoc, except it chooses the end of an - // expansion range. - if (SM->isMacroArgExpansion(End)) { + FileID BeginFileID = SM->getFileID(Begin); + FileID EndFileID = SM->getFileID(End); + + // Find the common parent for the beginning and end of the range. + + // First, crawl the expansion chain for the beginning of the range. + llvm::SmallDenseMap BeginLocsMap; + while (Begin.isMacroID() && BeginFileID != EndFileID) { + BeginLocsMap[BeginFileID] = Begin; + Begin = SM->getImmediateExpansionRange(Begin).first; + BeginFileID = SM->getFileID(Begin); + } + + // Then, crawl the expansion chain for the end of the range. + if (BeginFileID != EndFileID) { + while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) { + End = SM->getImmediateExpansionRange(End).second; + EndFileID = SM->getFileID(End); + } + if (End.isMacroID()) { + Begin = BeginLocsMap[EndFileID]; + BeginFileID = EndFileID; + } + } + + 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); } // Return the spelling location of the beginning and end of the range. diff --git a/clang/test/Misc/caret-diags-macros.c b/clang/test/Misc/caret-diags-macros.c index 5faddb6..a41816f 100644 --- a/clang/test/Misc/caret-diags-macros.c +++ b/clang/test/Misc/caret-diags-macros.c @@ -163,3 +163,17 @@ int y = Y; // CHECK-NEXT: {{.*}}:134:15: note: expanded from macro 'QMARK' // CHECK-NEXT: #define QMARK ? // CHECK-NEXT: {{^ \^}} + +// PR14399 +void iequals(int,int,int); +void foo_aa() +{ +#define /* */ BARC(c, /* */b, a, ...) (a+b+/* */c + __VA_ARGS__ +0) + iequals(__LINE__, BARC(4,3,2,6,8), 8); +} +// CHECK: {{.*}}:172:21: warning: expression result unused +// CHECK-NEXT: iequals(__LINE__, BARC(4,3,2,6,8), 8); +// CHECK-NEXT: {{^ \^~~~~~~~~~~~~~~}} +// CHECK-NEXT: {{.*}}:171:51: note: expanded from macro 'BARC' +// CHECK-NEXT: #define /* */ BARC(c, /* */b, a, ...) (a+b+/* */c + __VA_ARGS__ +0) +// CHECK-NEXT: {{^ ~~~~~~~~~~ \^}} -- 2.7.4