https://github.com/usx95 created 
https://github.com/llvm/llvm-project/pull/186799

None

>From ddc56e76e557e0a7e33bbc86e13141cae2e6c909 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Mon, 16 Mar 2026 13:33:13 +0000
Subject: [PATCH] Experimental invalidation annotation

---
 .../LifetimeSafety/LifetimeAnnotations.cpp    | 30 +++++++++++++++++++
 .../warn-lifetime-safety-invalidations.cpp    | 21 +++++++++++++
 2 files changed, 51 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
index 4852f444a51b3..9365dd7cd115a 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
@@ -8,6 +8,7 @@
 #include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/Attrs.inc"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
@@ -277,7 +278,36 @@ bool isUniquePtrRelease(const CXXMethodDecl &MD) {
          MD.getNumParams() == 0 && isStdUniquePtr(*MD.getParent());
 }
 
+static bool hasInvalidatesAttr(const TypeSourceInfo &TSI) {
+  // Walk through the type layers looking for an annotate attribute.
+  TypeLoc TL = TSI.getTypeLoc();
+  while (true) {
+    auto ATL = TL.getAsAdjusted<AttributedTypeLoc>();
+    if (!ATL)
+      break;
+    if (auto *AnnAttr = ATL.getAttrAs<AnnotateTypeAttr>()) {
+      if (AnnAttr->getAnnotation() == "experimental_invalidates")
+        return true;
+    }
+    TL = ATL.getModifiedLoc();
+  }
+  return false;
+}
+
 bool isContainerInvalidationMethod(const CXXMethodDecl &MD) {
+  auto CheckRedecls = [](const FunctionDecl *F) {
+    return llvm::any_of(F->redecls(), [](const FunctionDecl *Redecl) {
+      const TypeSourceInfo *TSI = Redecl->getTypeSourceInfo();
+      return TSI && hasInvalidatesAttr(*TSI);
+    });
+  };
+
+  if (CheckRedecls(&MD))
+    return true;
+  if (const FunctionDecl *Pattern = MD.getTemplateInstantiationPattern();
+      Pattern && CheckRedecls(Pattern))
+    return true;
+
   const CXXRecordDecl *RD = MD.getParent();
   if (!isInStlNamespace(RD))
     return false;
diff --git a/clang/test/Sema/warn-lifetime-safety-invalidations.cpp 
b/clang/test/Sema/warn-lifetime-safety-invalidations.cpp
index 486edd7a1a023..cda35bb62f5c4 100644
--- a/clang/test/Sema/warn-lifetime-safety-invalidations.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-invalidations.cpp
@@ -507,3 +507,24 @@ void ref_capture_reassigned_to_safe() {
   lambda();  // should not warn
 }
 } // namespace lambda_capture_invalidation
+
+namespace invalidation_annotation {
+struct FlatContainer {
+  void push_back(int x) [[clang::annotate_type("experimental_invalidates")]] {
+    data.push_back(x);
+  }
+
+  int& getFirst() [[clang::lifetimebound]] { return data[0]; }
+
+ private:
+  std::vector<int> data;
+};
+
+void foo() {
+  FlatContainer C;
+  C.push_back(1);
+  int& first = C.getFirst();  // expected-warning {{object whose reference is 
captured is later invalidated}}
+  C.push_back(2);             // expected-note {{invalidated here}}
+  (void)first;                // expected-note {{later used here}}
+}
+} // namespace invalidation_annotation

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

Reply via email to