https://github.com/zeyi2 created https://github.com/llvm/llvm-project/pull/205250
None >From 1ca4f441b6209697f1c7d8c97c1d9a12d03f129c Mon Sep 17 00:00:00 2001 From: Zeyi Xu <[email protected]> Date: Tue, 23 Jun 2026 11:54:15 +0800 Subject: [PATCH] [LifetimeSafety] Cache lifetimebound macro lookup. NFC. --- clang/lib/Sema/SemaLifetimeSafety.h | 91 ++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 4bde272fb40a1..c2f7a56e166c4 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -442,21 +442,94 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { } private: + struct LifetimeBoundMacroCache { + bool IsBuilt = false; + llvm::SmallVector<const IdentifierInfo *> Candidates; + }; + + void buildLifetimeBoundMacroCache(LifetimeBoundMacroCache &Cache, + llvm::ArrayRef<TokenValue> Tokens) { + if (Cache.IsBuilt) + return; + + const Preprocessor &PP = S.getPreprocessor(); + // Collect macro names that were ever defined as a lifetimebound attribute. + for (const auto &M : PP.macros()) { + const IdentifierInfo *II = M.first; + const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II); + if (!MD) + continue; + + // Include earlier matching definitions to handle redefinitions. + for (MacroDirective::DefInfo Def = MD->getDefinition(); Def; + Def = Def.getPreviousDefinition()) { + const MacroInfo *MI = Def.getMacroInfo(); + if (MI->isObjectLike() && Tokens.size() == MI->getNumTokens() && + std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin())) { + Cache.Candidates.push_back(II); + break; + } + } + } + Cache.IsBuilt = true; + } + + StringRef getLastCachedMacroWithSpelling(SourceLocation Loc, + llvm::ArrayRef<TokenValue> Tokens, + LifetimeBoundMacroCache &Cache) { + if (Loc.isInvalid()) + return {}; + + buildLifetimeBoundMacroCache(Cache, Tokens); + + const Preprocessor &PP = S.getPreprocessor(); + const SourceManager &SM = S.getSourceManager(); + SourceLocation BestLocation; + StringRef BestSpelling; + for (const IdentifierInfo *II : Cache.Candidates) { + const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II); + if (!MD) + continue; + const MacroDirective::DefInfo Def = MD->findDirectiveAtLoc(Loc, SM); + if (!Def || !Def.getMacroInfo()) + continue; + + // Ensure the macro definition active at Loc still has this spelling. + const MacroInfo *MI = Def.getMacroInfo(); + if (!MI->isObjectLike() || Tokens.size() != MI->getNumTokens() || + !std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin())) + continue; + + // Choose the matching macro defined latest before Loc. + SourceLocation Location = Def.getLocation(); + if (BestLocation.isInvalid() || + (Location.isValid() && + SM.isBeforeInTranslationUnit(BestLocation, Location))) { + BestLocation = Location; + BestSpelling = II->getName(); + } + } + return BestSpelling; + } + std::string getLifetimeBoundFixItText(SourceLocation Loc, bool LeadingSpace, bool AllowGNUAttrMacro = true) { StringRef Spelling = S.getLangOpts().LifetimeSafetyLifetimeBoundMacro; if (Spelling.empty() && Loc.isValid()) { const Preprocessor &PP = S.getPreprocessor(); - Spelling = PP.getLastMacroWithSpelling( - Loc, {tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"), - tok::coloncolon, PP.getIdentifierInfo("lifetimebound"), - tok::r_square, tok::r_square}); + Spelling = getLastCachedMacroWithSpelling( + Loc, + {tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"), + tok::coloncolon, PP.getIdentifierInfo("lifetimebound"), + tok::r_square, tok::r_square}, + ClangLifetimeBoundMacroCache); if (Spelling.empty() && AllowGNUAttrMacro) - Spelling = PP.getLastMacroWithSpelling( - Loc, {tok::kw___attribute, tok::l_paren, tok::l_paren, - PP.getIdentifierInfo("lifetimebound"), tok::r_paren, - tok::r_paren}); + Spelling = getLastCachedMacroWithSpelling( + Loc, + {tok::kw___attribute, tok::l_paren, tok::l_paren, + PP.getIdentifierInfo("lifetimebound"), tok::r_paren, tok::r_paren}, + GNULifetimeBoundMacroCache); } const std::string Text = Spelling.empty() ? "[[clang::lifetimebound]]" : Spelling.str(); @@ -589,6 +662,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { } } + LifetimeBoundMacroCache ClangLifetimeBoundMacroCache; + LifetimeBoundMacroCache GNULifetimeBoundMacroCache; Sema &S; }; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
