[clang] [analyzer] Move the lifetime checkers from alpha.cplusplus to alpha.core (PR #216739)
Benedek Kaibas via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 27 07:58:24 PDT 2026
https://github.com/benedekaibas updated https://github.com/llvm/llvm-project/pull/216739
>From bebd57c259e309b9c7134fd874beb5a54d615639 Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Mon, 17 Aug 2026 15:59:49 +0200
Subject: [PATCH 1/4] [analyzer] Move the LifetimeModeling and DanglingPtrDeref
checkers to alpha.core
---
clang/docs/analyzer/checkers.md | 119 +++++++++---------
.../clang/StaticAnalyzer/Checkers/Checkers.td | 32 ++---
clang/test/Analysis/dangling-ptr-deref.cpp | 2 +-
3 files changed, 77 insertions(+), 76 deletions(-)
diff --git a/clang/docs/analyzer/checkers.md b/clang/docs/analyzer/checkers.md
index 81c91ccffb14f..715af9e781299 100644
--- a/clang/docs/analyzer/checkers.md
+++ b/clang/docs/analyzer/checkers.md
@@ -3198,6 +3198,66 @@ void test() {
}
```
+(alpha-core-danglingptrderef)=
+
+#### alpha.core.DanglingPtrDeref (C, C++)
+
+Check for dereferences of pointers that refer to an object whose
+lifetime has already ended. Such a pointer is dangling. The checker
+reports it when it is dereferenced and when it is passed to a function.
+A return statement that does not dereference the pointer does not lead to a report.
+Such a case is reported by the {ref}`core-StackAddressEscape` checker.
+
+Each object is reported at most once on an execution path. If the same dangling
+pointer is used several times then only the first use is reported. Setting the pointer
+to null when the object goes out of scope avoids the dangling pointer and suppresses
+the report.
+
+```cpp
+void test_deref() {
+ int *ptr = 0;
+ {
+ int num = 5;
+ ptr = #
+ } // note: 'num' is destroyed here
+ *ptr = 6; // warn: use of 'num' after its lifetime ended
+}
+
+void test_in_scope() {
+ int num = 5;
+ int *ptr = #
+ {
+ *ptr = 6; // no warning, 'num' is still in scope
+ }
+}
+```
+
+The `-analyzer-config cfg-lifetime=true` option is a prerequisite for these
+reports. Without it the checker does not report anything and no error is emitted
+by the analyzer.
+
+**Limitations**
+
+If the analyzer cannot analyze the body of the called function, for example because
+its definition is not available in the given translation unit, then a dangling
+pointer passed to it is reported even if the function would never dereference
+it. This can lead to false positives.
+
+```cpp
+// The definition of the function is not available that is why the analyzer
+// assumes the pointer is used.
+int is_null(int *p);
+
+void argument_example() {
+ int *ptr = 0;
+ {
+ int num = 5;
+ ptr = #
+ }
+ is_null(ptr); // false positive: the pointer is compared, not dereferenced
+}
+```
+
(alpha-core-dynamictypechecker)=
#### alpha.core.DynamicTypeChecker (ObjC)
@@ -3300,65 +3360,6 @@ remove the const qualifier from the original declaration or use a mutable copy.
### alpha.cplusplus
-(alpha-cplusplus-danglingptrderef)=
-
-#### alpha.cplusplus.DanglingPtrDeref (C++)
-
-Check for dereferences of pointers that refer to an object whose
-lifetime has already ended. Such a pointer is dangling. The checker
-reports it when it is dereferenced and when it is passed to a function.
-A return statement that does not dereference the pointer does not lead to a report.
-Such a case is reported by the {ref}`core-StackAddressEscape` checker.
-
-Each object is reported at most once on an execution path. If the same dangling
-pointer is used several times then only the first use is reported. Setting the pointer
-to null when the object goes out of scope avoids the dangling pointer and suppresses
-the report.
-
-```cpp
-void test_deref() {
- int *ptr = 0;
- {
- int num = 5;
- ptr = #
- } // note: 'num' is destroyed here
- *ptr = 6; // warn: use of 'num' after its lifetime ended
-}
-
-void test_in_scope() {
- int num = 5;
- int *ptr = #
- {
- *ptr = 6; // no warning, 'num' is still in scope
- }
-}
-```
-
-The `-analyzer-config cfg-lifetime=true` option is a prerequisite for these
-reports. Without it the checker does not report anything and no error is emitted
-by the analyzer.
-
-**Limitations**
-
-If the analyzer cannot analyze the body of the called function, for example because
-its definition is not available in the given translation unit, then a dangling
-pointer passed to it is reported even if the function would never dereference
-it. This can lead to false positives.
-
-```cpp
-// The definition of the function is not available that is why the analyzer
-// assumes the pointer is used.
-int is_null(int *p);
-
-void argument_example() {
- int *ptr = 0;
- {
- int num = 5;
- ptr = #
- }
- is_null(ptr); // false positive: the pointer is compared, not dereferenced
-}
-```
(alpha-cplusplus-deletewithnonvirtualdtor)=
#### alpha.cplusplus.DeleteWithNonVirtualDtor (C++)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index b1b87dc883ed6..4dd3b70db6715 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -289,6 +289,22 @@ def StdVariantChecker : Checker<"StdVariant">,
HelpText<"Check for bad type access for std::variant.">,
Documentation<HasDocumentation>;
+def LifetimeModeling : Checker<"LifetimeModeling">,
+ HelpText<"Model lifetime annotations for other checkers">,
+ Documentation<NotDocumented>,
+ Hidden;
+
+def DanglingPtrDeref : Checker<"DanglingPtrDeref">,
+ HelpText<"Check for dereferences of a dangling pointer">,
+ Dependencies<[LifetimeModeling]>,
+ Documentation<HasDocumentation>;
+
+def UseAfterLifetimeEnd : Checker<"UseAfterLifetimeEnd">,
+ HelpText<"Check for uses of references or pointers that "
+ "outlive their bound object">,
+ Dependencies<[LifetimeModeling]>,
+ Documentation<NotDocumented>;
+
} // end "alpha.core"
//===----------------------------------------------------------------------===//
@@ -802,22 +818,6 @@ def SmartPtrChecker: Checker<"SmartPtr">,
Dependencies<[SmartPtrModeling]>,
Documentation<HasDocumentation>;
-def LifetimeModeling : Checker<"LifetimeModeling">,
- HelpText<"Model lifetime annotations for other checkers">,
- Documentation<NotDocumented>,
- Hidden;
-
-def UseAfterLifetimeEnd : Checker<"UseAfterLifetimeEnd">,
- HelpText<"Check for uses of references or pointers that "
- "outlive their bound object">,
- Dependencies<[LifetimeModeling]>,
- Documentation<NotDocumented>;
-
-def DanglingPtrDeref : Checker<"DanglingPtrDeref">,
- HelpText<"Check for dereferences of a dangling pointer">,
- Dependencies<[LifetimeModeling]>,
- Documentation<HasDocumentation>;
-
} // end: "alpha.cplusplus"
//===----------------------------------------------------------------------===//
diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp b/clang/test/Analysis/dangling-ptr-deref.cpp
index 55dd5eadc8ad0..8572b6416f150 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.DanglingPtrDeref \
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.DanglingPtrDeref \
// RUN: -analyzer-config cfg-lifetime=true -analyzer-output=text -verify %s
void test_case_one() {
>From b94cc0b1973843fe1d558f0ffd67292750cda4cc Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Tue, 18 Aug 2026 17:23:55 +0200
Subject: [PATCH 2/4] Move UseAfterLifetimeEnd out from alpha.cplusplus to
alpha.core
---
clang/include/clang/StaticAnalyzer/Checkers/Checkers.td | 6 ++++++
clang/test/Analysis/debug-lifetime-bound.cpp | 2 +-
clang/test/Analysis/lifetime-bound.cpp | 4 ++--
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 4dd3b70db6715..b4a525c815429 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -294,6 +294,12 @@ def LifetimeModeling : Checker<"LifetimeModeling">,
Documentation<NotDocumented>,
Hidden;
+def UseAfterLifetimeEnd : Checker<"UseAfterLifetimeEnd">,
+ HelpText<"Check for uses of references or pointers that "
+ "outlive their bound object">,
+ Dependencies<[LifetimeModeling]>,
+ Documentation<NotDocumented>;
+
def DanglingPtrDeref : Checker<"DanglingPtrDeref">,
HelpText<"Check for dereferences of a dangling pointer">,
Dependencies<[LifetimeModeling]>,
diff --git a/clang/test/Analysis/debug-lifetime-bound.cpp b/clang/test/Analysis/debug-lifetime-bound.cpp
index b52d23c88071d..eb4106111d427 100644
--- a/clang/test/Analysis/debug-lifetime-bound.cpp
+++ b/clang/test/Analysis/debug-lifetime-bound.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugLifetimeModeling -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.UseAfterLifetimeEnd,debug.DebugLifetimeModeling -verify %s
// expected-no-diagnostics
diff --git a/clang/test/Analysis/lifetime-bound.cpp b/clang/test/Analysis/lifetime-bound.cpp
index ff8b4e45c0dee..eba5c81e1fa6a 100644
--- a/clang/test/Analysis/lifetime-bound.cpp
+++ b/clang/test/Analysis/lifetime-bound.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugLifetimeModeling \
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.UseAfterLifetimeEnd,debug.DebugLifetimeModeling \
// RUN: -analyzer-config cfg-lifetime=true -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugLifetimeModeling \
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.UseAfterLifetimeEnd,debug.DebugLifetimeModeling \
// RUN: -analyzer-output=text %s 2>&1 | FileCheck --strict-whitespace %s
struct A {};
>From 73ed0068f0571ab24d3cb3f17013f03ee72ca520 Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Thu, 27 Aug 2026 15:45:33 +0200
Subject: [PATCH 3/4] Remove duplicated UseAfterLifetimeEnd entries.
---
clang/include/clang/StaticAnalyzer/Checkers/Checkers.td | 6 ------
1 file changed, 6 deletions(-)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index b4a525c815429..d8f5d74e7ff13 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -305,12 +305,6 @@ def DanglingPtrDeref : Checker<"DanglingPtrDeref">,
Dependencies<[LifetimeModeling]>,
Documentation<HasDocumentation>;
-def UseAfterLifetimeEnd : Checker<"UseAfterLifetimeEnd">,
- HelpText<"Check for uses of references or pointers that "
- "outlive their bound object">,
- Dependencies<[LifetimeModeling]>,
- Documentation<NotDocumented>;
-
} // end "alpha.core"
//===----------------------------------------------------------------------===//
>From 68fa1e10f0fcd87f929689ad9aced1d35462e23f Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Thu, 27 Aug 2026 16:57:57 +0200
Subject: [PATCH 4/4] Update the release notes.
---
clang/docs/ReleaseNotes.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index cd7f40aec112d..35aae605d8476 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -680,6 +680,8 @@ features cannot lower the translation-unit ABI level;
#### Moved checkers
+The `alpha.cplusplus.UseAfterLifetimeEnd` checker was renamed to `alpha.core.UseAfterLifetimeEnd`.
+
#### Diagnostic changes
- For self-assignments during initialization (`T v = v;`), `core.uninitialized.Assign` will not report them as uninitialized accesses (except C++ reference types), and the checks will be delayed until the first accesses of these variables; `deadcode.DeadStores` will not report them as dead stores. (#GH187530)
More information about the cfe-commits
mailing list