[clang] 6eaf612 - [alpha.webkit.UncountedLocalVarsChecker] Only skip the destructor of a null smart pointer temporary bound as const (#231715)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 13 23:09:30 PDT 2026
Author: Fady Farag
Date: 2026-10-13T23:09:25-07:00
New Revision: 6eaf6124b077de6d8726eb50062c02a579d053f3
URL: https://github.com/llvm/llvm-project/commit/6eaf6124b077de6d8726eb50062c02a579d053f3
DIFF: https://github.com/llvm/llvm-project/commit/6eaf6124b077de6d8726eb50062c02a579d053f3.diff
LOG: [alpha.webkit.UncountedLocalVarsChecker] Only skip the destructor of a null smart pointer temporary bound as const (#231715)
Previously, `TrivialFunctionAnalysis` skipped the destructor check of a
temporary owning smart pointer whenever it was constructed to hold
nullptr. That is correct when the temporary is bound to a const
reference, but a temporary materialized as non-const can be given a new
value before it is destructed, so its destructor may delete the object.
This caused a missing warning for any raw pointer/reference local
variable whose guardian was swapped into the temporary. This only skips
the destructor check when the null temporary is materialized through a
NoOp cast to const.
Added:
Modified:
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
Removed:
################################################################################
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 0a98dc6357bd6..afcb5bf2cb692 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -1272,6 +1272,13 @@ class TrivialFunctionAnalysisVisitor
}
bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT) {
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(VMT->getSubExpr());
+ ICE && ICE->getCastKind() == CK_NoOp &&
+ ICE->getType().isConstQualified()) {
+ if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(ICE->getSubExpr());
+ BTE && isNullSmartPtr(BTE->getSubExpr()))
+ return Visit(BTE->getSubExpr());
+ }
return Visit(VMT->getSubExpr());
}
@@ -1330,8 +1337,7 @@ class TrivialFunctionAnalysisVisitor
bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE) {
if (auto *Temp = BTE->getTemporary()) {
- if (!isNullSmartPtr(BTE->getSubExpr()) &&
- !IsFunctionTrivial(Temp->getDestructor()))
+ if (!IsFunctionTrivial(Temp->getDestructor()))
return false;
}
return Visit(BTE->getSubExpr());
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
index e26bd87e0d425..30560987d3130 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
@@ -1052,4 +1052,25 @@ void non_null_temporary(RefCountable& obj) {
}
}
+void null_temporary_swapped_with_guardian(RefCountable& src) {
+ RefPtr<RefCountable> obj = &src;
+ {
+ auto* foo = obj.get();
+ // expected-warning at -1{{Local variable 'foo' is a raw pointer to RefPtr-capable type 'RefCountable' [alpha.webkit.UncountedLocalVarsChecker]}}
+ RefPtr<RefCountable>().swap(obj);
+ foo->trivial();
+ }
+}
+
+void moveInto(RefPtr<RefCountable>&& dst, RefPtr<RefCountable>& src) { dst.swap(src); }
+
+void null_temporary_filled_by_callee(RefPtr<RefCountable> obj) {
+ {
+ auto* foo = obj.get();
+ // expected-warning at -1{{Local variable 'foo' is a raw pointer to RefPtr-capable type 'RefCountable' [alpha.webkit.UncountedLocalVarsChecker]}}
+ moveInto(RefPtr<RefCountable>(), obj);
+ foo->trivial();
+ }
+}
+
} // namespace hash_table_empty_value
More information about the cfe-commits
mailing list