diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 4ddd11495f534..cd33476344a34 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -468,6 +468,18 @@ bool isPtrConversion(const FunctionDecl *F) { FunctionName == "checked_objc_cast") return true; + auto ReturnType = F->getReturnType(); + if (auto *Type = ReturnType.getTypePtrOrNull()) { + if (auto *AttrType = dyn_cast(Type)) { + if (auto *Attr = AttrType->getAttr()) { + if (auto *AnnotateType = dyn_cast(Attr)) { + if (AnnotateType->getAnnotation() == "webkit.pointerconversion") + return true; + } + } + } + } + return false; } diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-safe-functions.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-safe-functions.cpp index a87446564870c..5c540a58debaf 100644 --- a/clang/test/Analysis/Checkers/WebKit/call-args-safe-functions.cpp +++ b/clang/test/Analysis/Checkers/WebKit/call-args-safe-functions.cpp @@ -1,10 +1,12 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s -// expected-no-diagnostics + +#include "mock-types.h" class Base { public: - inline void ref(); - inline void deref(); + void ref(); + void deref(); + void doWork(); }; class Derived : public Base { @@ -21,6 +23,7 @@ class SubDerived final : public Derived { class OtherObject { public: Derived* obj(); + Base* base(); }; class String { @@ -44,6 +47,12 @@ inline Target* uncheckedDowncast(Source* source) return static_cast(source); } +template +Target* [[clang::annotate_type("webkit.pointerconversion")]] newCastFunction(Source*); + +template +Target* [[clang::annotate_type("unrelated-annotation")]] badCastFunction(Source*); + template String toString(const Types&... values); @@ -52,5 +61,17 @@ void foo(OtherObject* other) dynamicDowncast(other->obj()); checkedDowncast(other->obj()); uncheckedDowncast(other->obj()); + newCastFunction(other->obj()); + badCastFunction(other->obj()); + // expected-warning@-1{{Call argument is uncounted and unsafe}} toString(other->obj()); } + +struct SomeStruct { + Derived* [[clang::annotate_type("webkit.pointerconversion")]] ptrConversion(Base*); + + void foo(OtherObject& otherObj) { + RefPtr ptr = otherObj.base(); + ptrConversion(ptr.get())->doWork(); + } +};