https://github.com/benedekaibas updated https://github.com/llvm/llvm-project/pull/216739
>From bebd57c259e309b9c7134fd874beb5a54d615639 Mon Sep 17 00:00:00 2001 From: benedekaibas <[email protected]> Date: Mon, 17 Aug 2026 15:59:49 +0200 Subject: [PATCH 1/2] [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 <[email protected]> Date: Tue, 18 Aug 2026 17:23:55 +0200 Subject: [PATCH 2/2] 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 {}; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
