[clang] [Lifetime] Fix 'clang::lifetimebound' ignored on template method definition (PR #178000)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 26 09:30:51 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-analysis
Author: Baranov Victor (vbvictor)
<details>
<summary>Changes</summary>
Closes https://github.com/llvm/llvm-project/issues/177798.
Same pattern with `getTemplateInstantiationPattern()` for attrs checking is already used in other LLVM places, e.g.:
https://github.com/llvm/llvm-project/blame/main/clang/lib/CodeGen/CodeGenModule.cpp#L2830-L2839
---
Full diff: https://github.com/llvm/llvm-project/pull/178000.diff
2 Files Affected:
- (modified) clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp (+12-5)
- (modified) clang/test/Sema/warn-lifetime-analysis-nocfg.cpp (+24-2)
``````````diff
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
index 93c7a86d0a57c..dd925d2b8fe6e 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
@@ -74,11 +74,18 @@ bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
FD = getDeclWithMergedLifetimeBoundAttrs(FD);
// Attribute merging doesn't work well with attributes on function types (like
// 'this' param). We need to check all redeclarations.
- for (const FunctionDecl *Redecl : FD->redecls()) {
- const TypeSourceInfo *TSI = Redecl->getTypeSourceInfo();
- if (TSI && getLifetimeBoundAttrFromFunctionType(*TSI))
- return true;
- }
+ auto CheckRedecls = [](const FunctionDecl *F) {
+ return llvm::any_of(F->redecls(), [](const FunctionDecl *Redecl) {
+ const TypeSourceInfo *TSI = Redecl->getTypeSourceInfo();
+ return TSI && getLifetimeBoundAttrFromFunctionType(*TSI);
+ });
+ };
+
+ if (CheckRedecls(FD))
+ return true;
+ if (const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern();
+ Pattern && CheckRedecls(Pattern))
+ return true;
return isNormalAssignmentOperator(FD);
}
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index 99a796c360a7f..605479d4db372 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -1252,6 +1252,24 @@ inline const char* StringTemplateSpecC<char>::data() const [[clang::lifetimeboun
return buffer;
}
+template<typename T>
+class MemberFuncsTpl {
+public:
+ // Template Version A: Attribute on declaration only
+ const T* memberA(const T& x [[clang::lifetimebound]]);
+ // Template Version B: Attribute on definition only
+ const T* memberB(const T& x);
+ // Template Version C: Attribute on BOTH declaration and definition
+ const T* memberC(const T& x [[clang::lifetimebound]]);
+};
+
+template<typename T>
+const T* MemberFuncsTpl<T>::memberA(const T& x) { return &x; }
+template<typename T>
+const T* MemberFuncsTpl<T>::memberB(const T& x [[clang::lifetimebound]]) { return &x; }
+template<typename T>
+const T* MemberFuncsTpl<T>::memberC(const T& x [[clang::lifetimebound]]) { return &x; }
+
void test() {
// Non-templated tests
const auto ptrA = StringA().data(); // Declaration-only attribute // expected-warning {{temporary whose address is used}}
@@ -1260,13 +1278,17 @@ void test() {
// Templated tests (generic templates)
const auto ptrTA = StringTemplateA<char>().data(); // Declaration-only attribute // expected-warning {{temporary whose address is used}}
- // FIXME: Definition is not instantiated until the end of TU. The attribute is not merged when this call is processed.
- const auto ptrTB = StringTemplateB<char>().data(); // Definition-only attribute
+ const auto ptrTB = StringTemplateB<char>().data(); // Definition-only attribute // expected-warning {{temporary whose address is used}}
const auto ptrTC = StringTemplateC<char>().data(); // Both have attribute // expected-warning {{temporary whose address is used}}
// Template specialization tests
const auto ptrTSA = StringTemplateSpecA<char>().data(); // Declaration-only attribute // expected-warning {{temporary whose address is used}}
const auto ptrTSB = StringTemplateSpecB<char>().data(); // Definition-only attribute // expected-warning {{temporary whose address is used}}
const auto ptrTSC = StringTemplateSpecC<char>().data(); // Both have attribute // expected-warning {{temporary whose address is used}}
+
+ MemberFuncsTpl<int> mtf;
+ const int* pTMA = mtf.memberA(1); // Declaration-only attribute // expected-warning {{temporary whose address is used}}
+ const int* pTMB = mtf.memberB(2); // Definition-only attribute // FIXME: Definition-only attribute
+ const int* pTMC = mtf.memberC(3); // Both have attribute // expected-warning {{temporary whose address is used}}
}
} // namespace GH175391
``````````
</details>
https://github.com/llvm/llvm-project/pull/178000
More information about the cfe-commits
mailing list