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
