https://github.com/benedekaibas updated https://github.com/llvm/llvm-project/pull/216688
>From 2938322915465c7ff19d2b5a04a6e5b5940f87ee Mon Sep 17 00:00:00 2001 From: benedekaibas <[email protected]> Date: Thu, 20 Aug 2026 16:21:38 +0200 Subject: [PATCH 1/5] Include the documentation in the checkers.md that replaced checkers.rst. --- clang/docs/analyzer/checkers.md | 67 +++++++++++++++++++ .../clang/StaticAnalyzer/Checkers/Checkers.td | 20 +++--- clang/test/Analysis/dangling-ptr-deref.cpp | 2 +- 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/clang/docs/analyzer/checkers.md b/clang/docs/analyzer/checkers.md index 3b54c3a359c3f..cfe15eef9326c 100644 --- a/clang/docs/analyzer/checkers.md +++ b/clang/docs/analyzer/checkers.md @@ -3300,6 +3300,73 @@ 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. +This includes a dereference in a return statement. 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. + +```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 +} + +int test_deref_in_return() { + int *ptr = 0; + { + int num = 5; + ptr = # + } // note: 'num' is destroyed here + return *ptr; // 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 b6b3857dc7b35..3e6e7c9ea13d5 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -289,6 +289,16 @@ 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>; + } // end "alpha.core" //===----------------------------------------------------------------------===// @@ -802,22 +812,12 @@ 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<NotDocumented>; - } // 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 628d1f5f49b228c67a8fcb25615db0364cd76b3f Mon Sep 17 00:00:00 2001 From: benedekaibas <[email protected]> Date: Mon, 17 Aug 2026 15:05:13 +0200 Subject: [PATCH 2/5] Revert move to alpha.core. --- .../clang/StaticAnalyzer/Checkers/Checkers.td | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 3e6e7c9ea13d5..b1b87dc883ed6 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -289,16 +289,6 @@ 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>; - } // end "alpha.core" //===----------------------------------------------------------------------===// @@ -812,12 +802,22 @@ 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" //===----------------------------------------------------------------------===// >From f5aff877f4242f4224515bda4ee5e513123f2118 Mon Sep 17 00:00:00 2001 From: benedekaibas <[email protected]> Date: Mon, 17 Aug 2026 15:27:54 +0200 Subject: [PATCH 3/5] Correct RUN lines for the DanglingPtrDeref test suite. --- clang/test/Analysis/dangling-ptr-deref.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp b/clang/test/Analysis/dangling-ptr-deref.cpp index 8572b6416f150..55dd5eadc8ad0 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.core.DanglingPtrDeref \ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.DanglingPtrDeref \ // RUN: -analyzer-config cfg-lifetime=true -analyzer-output=text -verify %s void test_case_one() { >From 737f1a3d446b3e420b0481aae27b26d1986a2d14 Mon Sep 17 00:00:00 2001 From: benedekaibas <[email protected]> Date: Wed, 26 Aug 2026 13:40:53 +0200 Subject: [PATCH 4/5] Remove test and text for dereference in return statement. --- clang/docs/analyzer/checkers.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/clang/docs/analyzer/checkers.md b/clang/docs/analyzer/checkers.md index cfe15eef9326c..41c040d229fff 100644 --- a/clang/docs/analyzer/checkers.md +++ b/clang/docs/analyzer/checkers.md @@ -3307,9 +3307,8 @@ remove the const qualifier from the original declaration or use a mutable copy. 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. -This includes a dereference in a return statement. 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. +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. @@ -3324,15 +3323,6 @@ void test_deref() { *ptr = 6; // warn: use of 'num' after its lifetime ended } -int test_deref_in_return() { - int *ptr = 0; - { - int num = 5; - ptr = # - } // note: 'num' is destroyed here - return *ptr; // warn: use of 'num' after its lifetime ended -} - void test_in_scope() { int num = 5; int *ptr = # >From 0181e057fbd2e3fe44f3a20be311a14390761ced Mon Sep 17 00:00:00 2001 From: benedekaibas <[email protected]> Date: Wed, 26 Aug 2026 13:53:30 +0200 Subject: [PATCH 5/5] Explanation for suppressing the fp report. --- clang/docs/analyzer/checkers.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/docs/analyzer/checkers.md b/clang/docs/analyzer/checkers.md index 41c040d229fff..81c91ccffb14f 100644 --- a/clang/docs/analyzer/checkers.md +++ b/clang/docs/analyzer/checkers.md @@ -3311,7 +3311,9 @@ A return statement that does not dereference the pointer does not lead to a repo 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. +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() { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
