https://github.com/zeyi2 updated 
https://github.com/llvm/llvm-project/pull/205250

>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 1/4] [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;
 };
 

>From 798dc68f9eba602bb6d4c0c1d83abaf7fd451dce Mon Sep 17 00:00:00 2001
From: Zeyi Xu <[email protected]>
Date: Tue, 23 Jun 2026 11:57:14 +0800
Subject: [PATCH 2/4] small style nit fixes

---
 clang/lib/Sema/SemaLifetimeSafety.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaLifetimeSafety.h 
b/clang/lib/Sema/SemaLifetimeSafety.h
index c2f7a56e166c4..b3f5a3b477a4d 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -444,11 +444,11 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
 private:
   struct LifetimeBoundMacroCache {
     bool IsBuilt = false;
-    llvm::SmallVector<const IdentifierInfo *> Candidates;
+    SmallVector<const IdentifierInfo *> Candidates;
   };
 
   void buildLifetimeBoundMacroCache(LifetimeBoundMacroCache &Cache,
-                                    llvm::ArrayRef<TokenValue> Tokens) {
+                                    ArrayRef<TokenValue> Tokens) {
     if (Cache.IsBuilt)
       return;
 

>From dda6eb03e8f5268e184a3b88005e57ae0be5f51e Mon Sep 17 00:00:00 2001
From: Zeyi Xu <[email protected]>
Date: Wed, 24 Jun 2026 04:59:47 +0800
Subject: [PATCH 3/4] add tests

---
 .../annotation-suggestions-fixits.cpp         | 33 +++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp 
b/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp
index 99f0d16cd8e68..e2fb9dd5df40a 100644
--- a/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp
+++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp
@@ -239,6 +239,39 @@ View return_view_with_latest_macro(View a) {
   return a;
 }
 
+#define REDEFINED_LIFETIMEBOUND_MACRO [[clang::lifetimebound]]
+
+View return_view_with_redefined_macro(View a) {
+  // CHECK: :[[@LINE-1]]:39: warning: parameter in intra-TU function should be 
marked
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:45-[[@LINE-2]]:45}:" 
REDEFINED_LIFETIMEBOUND_MACRO"
+  return a;
+}
+
+#undef REDEFINED_LIFETIMEBOUND_MACRO
+#define REDEFINED_LIFETIMEBOUND_MACRO [[maybe_unused]]
+
+View return_view_after_redefined_macro(View a) {
+  // CHECK: :[[@LINE-1]]:40: warning: parameter in intra-TU function should be 
marked
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:46-[[@LINE-2]]:46}:" 
SECOND_LIFETIMEBOUND_MACRO"
+  return a;
+}
+
+#define UNDEFINED_LIFETIMEBOUND_MACRO [[clang::lifetimebound]]
+
+View return_view_with_undefined_macro(View a) {
+  // CHECK: :[[@LINE-1]]:39: warning: parameter in intra-TU function should be 
marked
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:45-[[@LINE-2]]:45}:" 
UNDEFINED_LIFETIMEBOUND_MACRO"
+  return a;
+}
+
+#undef UNDEFINED_LIFETIMEBOUND_MACRO
+
+View return_view_after_undefined_macro(View a) {
+  // CHECK: :[[@LINE-1]]:40: warning: parameter in intra-TU function should be 
marked
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:46-[[@LINE-2]]:46}:" 
SECOND_LIFETIMEBOUND_MACRO"
+  return a;
+}
+
 struct MacroMember {
   MyObj data;
 

>From 0d2200b612913f690d400f10d65a583a95149fe2 Mon Sep 17 00:00:00 2001
From: Zeyi Xu <[email protected]>
Date: Wed, 24 Jun 2026 21:35:13 +0800
Subject: [PATCH 4/4] add assert

---
 clang/lib/Sema/SemaLifetimeSafety.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/lib/Sema/SemaLifetimeSafety.h 
b/clang/lib/Sema/SemaLifetimeSafety.h
index 83f0e64523b1e..7c78a6a1e8c31 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -482,6 +482,8 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
 
       // Choose the matching macro defined latest before Loc.
       SourceLocation Location = Def.getLocation();
+      assert(Location.isInvalid() ||
+             SM.isBeforeInTranslationUnit(Location, Loc));
       if (BestLocation.isInvalid() ||
           (Location.isValid() &&
            SM.isBeforeInTranslationUnit(BestLocation, Location))) {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to