[clang] [LifetimeSafety] Add separate diagnostic groups for constructor annotation suggestions (PR #206254)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 27 07:33:10 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-temporal-safety
Author: Utkarsh Saxena (usx95)
<details>
<summary>Changes</summary>
Reason:
* Better selective enablement.
* In experience, constructor annotations are the most useful and improves detection by manifolds.
---
Full diff: https://github.com/llvm/llvm-project/pull/206254.diff
5 Files Affected:
- (modified) clang/docs/LifetimeSafety.rst (+2)
- (modified) clang/include/clang/Basic/DiagnosticGroups.td (+9-2)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+12)
- (modified) clang/lib/Sema/SemaLifetimeSafety.h (+13-4)
- (modified) clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp (+7-7)
``````````diff
diff --git a/clang/docs/LifetimeSafety.rst b/clang/docs/LifetimeSafety.rst
index be9b32f8d4b2d..ec97a795e5670 100644
--- a/clang/docs/LifetimeSafety.rst
+++ b/clang/docs/LifetimeSafety.rst
@@ -524,7 +524,9 @@ enables only the high-confidence subset of these checks.
* ``-Wlifetime-safety-suggestions``: Enables suggestions to add ``[[clang::lifetimebound]]`` to function parameters and ``this`` parameters.
* ``-Wlifetime-safety-intra-tu-suggestions``: Suggestions for functions local to the translation unit.
+ * ``-Wlifetime-safety-intra-tu-constructor-suggestions``: Suggestions for constructors local to the translation unit.
* ``-Wlifetime-safety-cross-tu-suggestions``: Suggestions for functions visible across translation units (e.g., in headers).
+ * ``-Wlifetime-safety-cross-tu-constructor-suggestions``: Suggestions for constructors visible across translation units.
* ``-Wlifetime-safety-validations``: Enables checks that validate existing lifetime annotations.
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 6418ab4757a0c..1c9d021317289 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -673,10 +673,17 @@ Warnings to detect use-after-free and related temporal safety bugs based on life
}];
}
+def LifetimeSafetyCrossTUConstructorSuggestions
+ : DiagGroup<"lifetime-safety-cross-tu-constructor-suggestions">;
+def LifetimeSafetyIntraTUConstructorSuggestions
+ : DiagGroup<"lifetime-safety-intra-tu-constructor-suggestions">;
+
def LifetimeSafetyCrossTUSuggestions
- : DiagGroup<"lifetime-safety-cross-tu-suggestions">;
+ : DiagGroup<"lifetime-safety-cross-tu-suggestions",
+ [LifetimeSafetyCrossTUConstructorSuggestions]>;
def LifetimeSafetyIntraTUSuggestions
- : DiagGroup<"lifetime-safety-intra-tu-suggestions">;
+ : DiagGroup<"lifetime-safety-intra-tu-suggestions",
+ [LifetimeSafetyIntraTUConstructorSuggestions]>;
def LifetimeSafetySuggestions
: DiagGroup<"lifetime-safety-suggestions",
[LifetimeSafetyCrossTUSuggestions,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7e20630708312..dae400d6d16b4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11082,6 +11082,18 @@ def warn_lifetime_safety_cross_tu_param_suggestion
InGroup<LifetimeSafetyCrossTUSuggestions>,
DefaultIgnore;
+def warn_lifetime_safety_intra_tu_ctor_param_suggestion
+ : Warning<"parameter in intra-TU constructor should be marked "
+ "[[clang::lifetimebound]]">,
+ InGroup<LifetimeSafetyIntraTUConstructorSuggestions>,
+ DefaultIgnore;
+
+def warn_lifetime_safety_cross_tu_ctor_param_suggestion
+ : Warning<"parameter in cross-TU constructor should be marked "
+ "[[clang::lifetimebound]]">,
+ InGroup<LifetimeSafetyCrossTUConstructorSuggestions>,
+ DefaultIgnore;
+
def warn_lifetime_safety_intra_tu_this_suggestion
: Warning<"implicit this in intra-TU function should be marked "
"[[clang::lifetimebound]]">,
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index a3d546792fe41..3b9ea9eafbec5 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -67,6 +67,8 @@ inline bool IsLifetimeSafetyEnabled(Sema &S, const Decl *D) {
diag::warn_lifetime_safety_invalidated_global,
diag::warn_lifetime_safety_cross_tu_param_suggestion,
diag::warn_lifetime_safety_intra_tu_param_suggestion,
+ diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion,
+ diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion,
diag::warn_lifetime_safety_cross_tu_this_suggestion,
diag::warn_lifetime_safety_intra_tu_this_suggestion,
diag::warn_lifetime_safety_inapplicable_lifetimebound};
@@ -81,6 +83,8 @@ inline bool ShouldSuggestLifetimeAnnotations(Sema &S, const Decl *D) {
constexpr unsigned DiagIDs[] = {
diag::warn_lifetime_safety_intra_tu_param_suggestion,
diag::warn_lifetime_safety_cross_tu_param_suggestion,
+ diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion,
+ diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion,
diag::warn_lifetime_safety_intra_tu_this_suggestion,
diag::warn_lifetime_safety_cross_tu_this_suggestion};
for (unsigned DiagID : DiagIDs)
@@ -280,10 +284,15 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
void suggestLifetimeboundToParmVar(WarningScope Scope,
const ParmVarDecl *ParmToAnnotate,
EscapingTarget Target) override {
- unsigned DiagID =
- (Scope == WarningScope::CrossTU)
- ? diag::warn_lifetime_safety_cross_tu_param_suggestion
- : diag::warn_lifetime_safety_intra_tu_param_suggestion;
+ unsigned DiagID;
+ if (isa<CXXConstructorDecl>(ParmToAnnotate->getDeclContext()))
+ DiagID = (Scope == WarningScope::CrossTU)
+ ? diag::warn_lifetime_safety_cross_tu_ctor_param_suggestion
+ : diag::warn_lifetime_safety_intra_tu_ctor_param_suggestion;
+ else
+ DiagID = (Scope == WarningScope::CrossTU)
+ ? diag::warn_lifetime_safety_cross_tu_param_suggestion
+ : diag::warn_lifetime_safety_intra_tu_param_suggestion;
auto [InsertionPoint, FixItText] = getLifetimeBoundFixIt(ParmToAnnotate);
diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
index 98c528516b8e7..56ed4a6dc7106 100644
--- a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
+++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
@@ -522,7 +522,7 @@ S forward(const MyObj &obj) { // expected-warning {{parameter in intra-TU functi
namespace capturing_constructor {
struct CaptureRefToView {
View v; // expected-note {{escapes to this field}}
- CaptureRefToView(const MyObj& obj) : v(obj) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
+ CaptureRefToView(const MyObj& obj) : v(obj) {} // expected-warning {{parameter in intra-TU constructor should be marked [[clang::lifetimebound]]}}
};
CaptureRefToView test_ref_to_view() {
@@ -533,7 +533,7 @@ CaptureRefToView test_ref_to_view() {
struct CaptureRefToPtr {
const MyObj* p; // expected-note {{escapes to this field}}
- CaptureRefToPtr(const MyObj& obj) : p(&obj) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
+ CaptureRefToPtr(const MyObj& obj) : p(&obj) {} // expected-warning {{parameter in intra-TU constructor should be marked [[clang::lifetimebound]]}}
};
CaptureRefToPtr test_ref_to_ptr() {
@@ -544,7 +544,7 @@ CaptureRefToPtr test_ref_to_ptr() {
struct CaptureViewToView {
View v; // expected-note {{escapes to this field}}
- CaptureViewToView(View v_param) : v(v_param) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
+ CaptureViewToView(View v_param) : v(v_param) {} // expected-warning {{parameter in intra-TU constructor should be marked [[clang::lifetimebound]]}}
};
CaptureViewToView test_view_to_view() {
@@ -556,7 +556,7 @@ CaptureViewToView test_view_to_view() {
struct CapturePtrToPtr {
const MyObj* p; // expected-note {{escapes to this field}}
- CapturePtrToPtr(const MyObj* p_param) : p(p_param) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
+ CapturePtrToPtr(const MyObj* p_param) : p(p_param) {} // expected-warning {{parameter in intra-TU constructor should be marked [[clang::lifetimebound]]}}
};
CapturePtrToPtr test_ptr_to_ptr() {
@@ -567,7 +567,7 @@ CapturePtrToPtr test_ptr_to_ptr() {
struct CaptureRefToRef {
const MyObj& r; // expected-note {{escapes to this field}}
- CaptureRefToRef(const MyObj& obj) : r(obj) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
+ CaptureRefToRef(const MyObj& obj) : r(obj) {} // expected-warning {{parameter in intra-TU constructor should be marked [[clang::lifetimebound]]}}
};
CaptureRefToRef test_ref_to_ref() {
@@ -580,7 +580,7 @@ struct BaseWithView {
View v; // expected-note {{escapes to this field}}
};
struct CaptureRefToBaseView : BaseWithView {
- CaptureRefToBaseView(const MyObj& obj) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
+ CaptureRefToBaseView(const MyObj& obj) { // expected-warning {{parameter in intra-TU constructor should be marked [[clang::lifetimebound]]}}
v = obj;
}
};
@@ -654,7 +654,7 @@ struct LifetimeBoundCtor {
struct HasCtorField {
LifetimeBoundCtor* field; // expected-note {{escapes to this field}}
- HasCtorField(const MyObj& obj) : field(new LifetimeBoundCtor(obj)) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
+ HasCtorField(const MyObj& obj) : field(new LifetimeBoundCtor(obj)) {} // expected-warning {{parameter in intra-TU constructor should be marked [[clang::lifetimebound]]}}
};
HasCtorField test_dangling_field_ctor() {
``````````
</details>
https://github.com/llvm/llvm-project/pull/206254
More information about the cfe-commits
mailing list