Author: Ryosuke Niwa
Date: 2025-09-11T15:51:02-07:00
New Revision: 50da22a9f4394de964eceb23097e1d05cc4dcdb6

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

LOG: [alpha.webkit.UncountedCallArgsChecker] A return value can be erroneously 
treated as unsafe if it's a template parameter (#157993)

When a template class takes Ref<T> as a template parameter and this
template parameter is used as the return value of a member function, the
return value can be treated as unsafe (i.e. emits a false positive). The
issue was caused by getCanonicalType sometimes converting Ref<T> to T.
Workaround this problem by avoid emitting a warning when the original,
non-canonical type is a safe pointer type.

Added: 
    clang/test/Analysis/Checkers/WebKit/template-wrapper-call-arg.cpp

Modified: 
    clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index 3fc10385885a3..6f13d552b4b44 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -161,6 +161,24 @@ bool tryToFindPtrOrigin(
             Name == "NSClassFromString")
           return callback(E, true);
       }
+
+      // Sometimes, canonical type erroneously turns Ref<T> into T.
+      // Workaround this problem by checking again if the original type was
+      // a SubstTemplateTypeParmType of a safe smart pointer type (e.g. Ref).
+      if (auto *CalleeDecl = call->getCalleeDecl()) {
+        if (auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) {
+          auto RetType = FD->getReturnType();
+          if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(RetType)) {
+            if (auto *SubstType = Subst->desugar().getTypePtr()) {
+              if (auto *RD = dyn_cast<RecordType>(SubstType)) {
+                if (auto *CXX = dyn_cast<CXXRecordDecl>(RD->getOriginalDecl()))
+                  if (isSafePtr(CXX))
+                    return callback(E, true);
+              }
+            }
+          }
+        }
+      }
     }
     if (auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E)) {
       if (auto *Method = ObjCMsgExpr->getMethodDecl()) {

diff  --git a/clang/test/Analysis/Checkers/WebKit/template-wrapper-call-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/template-wrapper-call-arg.cpp
new file mode 100644
index 0000000000000..b0ff210f9415e
--- /dev/null
+++ b/clang/test/Analysis/Checkers/WebKit/template-wrapper-call-arg.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_analyze_cc1 
-analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
+// expected-no-diagnostics
+
+#include "mock-types.h"
+
+struct Obj {
+  void ref() const;
+  void deref() const;
+
+  void someFunction();
+};
+
+template<typename T> class Wrapper {
+public:
+  T obj();
+};
+
+static void foo(Wrapper<Ref<Obj>>&& wrapper)
+{
+  wrapper.obj()->someFunction();
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to