[clang] [LifetimeSafety] Cache lifetimebound macro lookup. NFC. (PR #205250)
Zeyi Xu via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 22 20:54:32 PDT 2026
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 <mitchell.xu2 at gmail.com>
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;
};
More information about the cfe-commits
mailing list