https://github.com/rniwa created https://github.com/llvm/llvm-project/pull/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. >From e4334be7318658f8530747d3c275499157a41149 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa <[email protected]> Date: Wed, 10 Sep 2025 22:15:10 -0700 Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] A return value can be erroneously treated as unsafe if it's a template parameter 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. --- .../WebKit/RawPtrRefCallArgsChecker.cpp | 17 +++++++++++++-- .../WebKit/template-wrapper-call-arg.cpp | 21 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 clang/test/Analysis/Checkers/WebKit/template-wrapper-call-arg.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp index e80f1749d595b..47bd13bea4abb 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp @@ -122,9 +122,22 @@ class RawPtrRefCallArgsChecker return; } auto *E = MemberCallExpr->getImplicitObjectArgument(); - QualType ArgType = MemberCallExpr->getObjectType().getCanonicalType(); + auto MemberCallQT = MemberCallExpr->getObjectType(); + QualType ArgType = MemberCallQT.getCanonicalType(); std::optional<bool> IsUnsafe = isUnsafeType(ArgType); - if (IsUnsafe && *IsUnsafe && !isPtrOriginSafe(E)) + + // 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). + bool IsSafePtr = false; + if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(MemberCallQT)) { + if (auto *Decl = Subst->getAssociatedDecl()) { + if (auto *CXXRD = dyn_cast<CXXRecordDecl>(Decl)) + IsSafePtr = isSafePtr(CXXRD); + } + } + + if (IsUnsafe && *IsUnsafe && !IsSafePtr && !isPtrOriginSafe(E)) reportBugOnThis(E, D); } 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 [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
