Author: Ryosuke Niwa
Date: 2026-05-27T18:13:30-07:00
New Revision: d65897289e68696fa5f5b2d2f449f7633fff13ab

URL: 
https://github.com/llvm/llvm-project/commit/d65897289e68696fa5f5b2d2f449f7633fff13ab
DIFF: 
https://github.com/llvm/llvm-project/commit/d65897289e68696fa5f5b2d2f449f7633fff13ab.diff

LOG: [alpha.webkit.UncountedLocalVarsChecker] Detect an assignment to a 
guardian argument (#198695)

A function parameter of type RefPtr<T>& should not be used as a guardian
variable of a raw pointer/reference variable if the function body
contains an assignment to it since such an assignment can shorten the
lifetime of the guarded object.

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
    clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
    clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm

Removed: 
    


################################################################################
diff  --git 
a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
index 442b8ef58688a..56df6742eda9c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
@@ -86,6 +86,8 @@ struct GuardianVisitor : DynamicRecursiveASTVisitor {
     auto *Callee = CE->getDirectCallee();
     if (!Callee)
       return false;
+    if (isPtrConversion(Callee))
+      return true;
     unsigned ArgIndex = 0;
     unsigned ArgOffset = isa<CXXOperatorCallExpr>(CE);
     for (auto *Arg : CE->arguments()) {
@@ -327,13 +329,14 @@ class RawPtrRefLocalVarsChecker
 
     std::optional<bool> IsUncountedPtr = isUnsafePtr(V->getType());
     if (IsUncountedPtr && *IsUncountedPtr) {
-      if (isPtrOriginSafe(V, Value))
+      if (isPtrOriginSafe(V, Value, DeclWithIssue))
         return;
       reportBug(V, Value, nullptr, DeclWithIssue);
     }
   }
 
-  bool isPtrOriginSafe(const VarDecl *V, const Expr *Value) const {
+  bool isPtrOriginSafe(const VarDecl *V, const Expr *Value,
+                       const Decl *DeclWithIssue) const {
     return tryToFindPtrOrigin(
         Value, /*StopAtFirstRefCountedObj=*/false,
         [&](const clang::CXXRecordDecl *Record) { return isSafePtr(Record); },
@@ -378,10 +381,18 @@ class RawPtrRefLocalVarsChecker
                 }
               }
 
-              // Parameters are guaranteed to be safe for the duration of
-              // the call by another checker.
-              if (isa<ParmVarDecl>(MaybeGuardian))
-                return true;
+              if (isa<ParmVarDecl>(MaybeGuardian)) {
+                if (auto *FD = dyn_cast<FunctionDecl>(DeclWithIssue)) {
+                  if (GuardianVisitor{MaybeGuardian}.TraverseStmt(
+                          FD->getBody()))
+                    return true;
+                }
+                if (auto *MD = dyn_cast<ObjCMethodDecl>(DeclWithIssue)) {
+                  if (GuardianVisitor{MaybeGuardian}.TraverseStmt(
+                          MD->getBody()))
+                    return true;
+                }
+              }
             }
           }
 

diff  --git a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
index 4cb3f560633af..d87e076cb4096 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
@@ -385,6 +385,19 @@ void baz() {
 
 } // namespace local_assignment_basic
 
+namespace local_assignment_to_guardian_parameter {
+
+RefCountable *provide_ref_cntbl();
+
+void foo(RefPtr<RefCountable>& arg) {
+  RefCountable* ptr = arg.get();
+  // expected-warning@-1{{Local variable 'ptr' is uncounted and unsafe 
[alpha.webkit.UncountedLocalVarsChecker]}}
+  arg = nullptr;
+  ptr->method();
+}
+
+} // namespace local_assignment_to_guardian
+
 namespace local_assignment_to_parameter {
 
 RefCountable *provide_ref_cntbl();

diff  --git a/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm 
b/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm
index f49e7bdb3e79c..04f403eda206f 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm
@@ -594,4 +594,11 @@ - (void)storeSomeObj {
   auto *obj = [self getSomeObj];
   [obj doWork];
 }
+
+- (void)assignToGuardianArg:(RetainPtr<SomeObj>&)obj {
+  SomeObj* ptr = obj.get();
+  // expected-warning@-1{{Local variable 'ptr' is unretained and unsafe 
[alpha.webkit.UnretainedLocalVarsChecker]}}
+  obj = nullptr;
+  [ptr doWork];
+}
 @end


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to