summaryrefslogtreecommitdiffstats
path: root/clang/lib/Frontend/DiagnosticRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Frontend/DiagnosticRenderer.cpp')
-rw-r--r--clang/lib/Frontend/DiagnosticRenderer.cpp83
1 files changed, 64 insertions, 19 deletions
diff --git a/clang/lib/Frontend/DiagnosticRenderer.cpp b/clang/lib/Frontend/DiagnosticRenderer.cpp
index 6ef9a89d86f..caf1f0dce99 100644
--- a/clang/lib/Frontend/DiagnosticRenderer.cpp
+++ b/clang/lib/Frontend/DiagnosticRenderer.cpp
@@ -308,34 +308,77 @@ 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();
+static SourceLocation
+retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID,
+ FileID CaretFileID,
+ const SmallVectorImpl<FileID> &CommonArgExpansions,
+ bool IsBegin, const SourceManager *SM) {
+ assert(SM->getFileID(Loc) == MacroFileID);
+ 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;
+ // Only look at the immediate spelling location of this macro argument if
+ // the other location in the source range is also present in that expansion.
+ if (std::binary_search(CommonArgExpansions.begin(),
+ CommonArgExpansions.end(), MacroFileID))
+ MacroLocation = SM->getImmediateSpellingLoc(Loc);
+ MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first
+ : SM->getImmediateExpansionRange(Loc).second;
} else {
- MacroLocation = getBeginLoc ? SM->getImmediateExpansionRange(Loc).first
- : SM->getImmediateExpansionRange(Loc).second;
+ MacroLocation = IsBegin ? 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;
+ if (MacroLocation.isValid()) {
+ MacroFileID = SM->getFileID(MacroLocation);
+ MacroLocation =
+ retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID,
+ CommonArgExpansions, IsBegin, SM);
+ if (MacroLocation.isValid())
+ return MacroLocation;
+ }
MacroFileID = SM->getFileID(MacroArgLocation);
return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID,
- getBeginLoc, SM);
+ CommonArgExpansions, IsBegin, SM);
+}
+
+/// Walk up the chain of macro expansions and collect the FileIDs identifying the
+/// expansions.
+static void getMacroArgExpansionFileIDs(SourceLocation Loc,
+ SmallVectorImpl<FileID> &IDs,
+ bool IsBegin, const SourceManager *SM) {
+ while (Loc.isMacroID()) {
+ if (SM->isMacroArgExpansion(Loc)) {
+ IDs.push_back(SM->getFileID(Loc));
+ Loc = SM->getImmediateSpellingLoc(Loc);
+ } else {
+ auto ExpRange = SM->getImmediateExpansionRange(Loc);
+ Loc = IsBegin ? ExpRange.first : ExpRange.second;
+ }
+ }
+}
+
+/// Collect the expansions of the begin and end locations and compute the set
+/// intersection. Produces a sorted vector of FileIDs in CommonArgExpansions.
+static void computeCommonMacroArgExpansionFileIDs(
+ SourceLocation Begin, SourceLocation End, const SourceManager *SM,
+ SmallVectorImpl<FileID> &CommonArgExpansions) {
+ SmallVector<FileID, 4> BeginArgExpansions;
+ SmallVector<FileID, 4> EndArgExpansions;
+ getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM);
+ getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM);
+ std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end());
+ std::sort(EndArgExpansions.begin(), EndArgExpansions.end());
+ std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(),
+ EndArgExpansions.begin(), EndArgExpansions.end(),
+ std::back_inserter(CommonArgExpansions));
}
// Helper function to fix up source ranges. It takes in an array of ranges,
@@ -387,10 +430,12 @@ static void mapDiagnosticRanges(
}
// Do the backtracking.
+ SmallVector<FileID, 4> CommonArgExpansions;
+ computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
- true /*getBeginLoc*/, SM);
+ CommonArgExpansions, /*IsBegin=*/true, SM);
End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
- false /*getBeginLoc*/, SM);
+ CommonArgExpansions, /*IsBegin=*/false, SM);
if (Begin.isInvalid() || End.isInvalid()) continue;
// Return the spelling location of the beginning and end of the range.
OpenPOWER on IntegriCloud