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@-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@-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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
