@@ -1411,9 +1411,7 @@ class TranslateASTVisitor final
14111411 auto Begin = Range.getBegin ();
14121412 auto End = Range.getEnd ();
14131413
1414- // Check that we are only expanding a single macro call.
1415- if (!Begin.isMacroID () || !End.isMacroID () ||
1416- Mgr.getImmediateMacroCallerLoc (Begin) != Mgr.getImmediateMacroCallerLoc (End)) {
1414+ if (!Begin.isMacroID () || !End.isMacroID ()) {
14171415 return true ;
14181416 }
14191417
@@ -1436,21 +1434,9 @@ class TranslateASTVisitor final
14361434 return true ;
14371435 }
14381436
1439- auto ReplacementBegin = mac->getReplacementToken (0 ).getLocation ();
1440- auto ReplacementEnd = mac->getDefinitionEndLoc ();
1441- // Verify that this expansion covers the entire macro replacement
1442- // definition, i.e. E is not a subexpression of the macro
1443- // replacement.
1444- if (Mgr.getSpellingLoc (Range.getBegin ()) != ReplacementBegin ||
1445- Mgr.getSpellingLoc (Range.getEnd ()) != ReplacementEnd) {
1446- return true ;
1447- }
1448-
14491437 if (VisitMacro (name, ExpansionRange.getBegin (), mac, E)) {
14501438 curMacroExpansionStack.push_back (mac);
14511439 }
1452-
1453- Range = ExpansionRange.getAsRange ();
14541440 }
14551441
14561442 return true ;
@@ -1460,20 +1446,72 @@ class TranslateASTVisitor final
14601446 auto &Mgr = Context->getSourceManager ();
14611447 auto Begin = Range.getBegin ();
14621448 auto End = Range.getEnd ();
1463-
1464- // Holds the stack of ranges of macro expansions.
1465- // The last element is the top-level macro call.
14661449 std::vector<CharSourceRange> ExpansionStack;
14671450
14681451 do {
1452+ if (!isAtStartOfImmediateMacroExpansion (Begin)) {
1453+ break ;
1454+ }
1455+
14691456 auto ExpansionRange = Mgr.getImmediateExpansionRange (Begin);
14701457 ExpansionStack.push_back (ExpansionRange);
14711458 Begin = ExpansionRange.getBegin ();
14721459 } while (Begin.isMacroID ());
14731460
1461+ // Find the point at which `Begin` and `End` converge on the same expansion range.
1462+ // This is where the expression in `Range` first corresponds to a single macro call.
1463+ auto ConvergencePoint = ExpansionStack.end ();
1464+
1465+ do {
1466+ if (!isAtEndOfImmediateMacroExpansion (End)) {
1467+ break ;
1468+ }
1469+
1470+ auto ExpansionRange = Mgr.getImmediateExpansionRange (End);
1471+ ConvergencePoint = std::find_if (
1472+ ExpansionStack.begin (),
1473+ ExpansionStack.end (),
1474+ [ExpansionRange](auto &R) {
1475+ return R.getAsRange () == ExpansionRange.getAsRange () &&
1476+ R.isTokenRange () == ExpansionRange.isTokenRange ();
1477+ }
1478+ );
1479+ End = ExpansionRange.getEnd ();
1480+ } while (End.isMacroID () && ConvergencePoint == ExpansionStack.end ());
1481+
1482+ // Remove all elements before the convergence point.
1483+ ExpansionStack.erase (ExpansionStack.begin (), ConvergencePoint);
1484+
1485+ // Ensure the remaining ranges still correspond to the input `Range`.
1486+ auto EraseAfter = std::find_if (
1487+ ExpansionStack.begin (),
1488+ ExpansionStack.end (),
1489+ [this , &Mgr](auto &R) {
1490+ auto End = R.getEnd ();
1491+ return End.isMacroID () && !isAtEndOfImmediateMacroExpansion (End);
1492+ }
1493+ );
1494+ auto EraseFrom = EraseAfter + 1 ;
1495+
1496+ if (EraseFrom < ExpansionStack.end ()) {
1497+ ExpansionStack.erase (EraseFrom, ExpansionStack.end ());
1498+ }
1499+
14741500 return ExpansionStack;
14751501 }
14761502
1503+ bool isAtStartOfImmediateMacroExpansion (SourceLocation loc) const {
1504+ auto &Mgr = Context->getSourceManager ();
1505+ return Mgr.isAtStartOfImmediateMacroExpansion (loc);
1506+ }
1507+
1508+ bool isAtEndOfImmediateMacroExpansion (SourceLocation loc) const {
1509+ auto &Mgr = Context->getSourceManager ();
1510+ auto spellingLoc = Mgr.getSpellingLoc (loc);
1511+ auto len = Lexer::MeasureTokenLength (spellingLoc, Mgr, Context->getLangOpts ());
1512+ return Mgr.isAtEndOfImmediateMacroExpansion (loc.getLocWithOffset (len));
1513+ }
1514+
14771515 bool VisitVAArgExpr (VAArgExpr *E) {
14781516 std::vector<void *> childIds{E->getSubExpr ()};
14791517 encode_entry (E, TagVAArgExpr, childIds);
0 commit comments