Files
TheRock/compiler/amd-llvm/clang/test/Analysis/Checkers/WebKit/call-args.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

578 lines
14 KiB
C++

// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
#include "mock-types.h"
RefCountable* provide();
void consume_refcntbl(RefCountable*);
void some_function();
namespace simple {
void foo() {
consume_refcntbl(provide());
// expected-warning@-1{{Call argument is uncounted and unsafe}}
}
// Test that the checker works with [[clang::suppress]].
void foo_suppressed() {
[[clang::suppress]]
consume_refcntbl(provide()); // no-warning
}
}
namespace multi_arg {
void consume_refcntbl(int, RefCountable* foo, bool);
void foo() {
consume_refcntbl(42, provide(), true);
// expected-warning@-1{{Call argument for parameter 'foo' is uncounted and unsafe}}
}
}
namespace ref_counted {
Ref<RefCountable> provide_ref_counted() { return Ref<RefCountable>{}; }
void consume_ref_counted(Ref<RefCountable>) {}
void foo() {
consume_refcntbl(provide_ref_counted().ptr());
// no warning
}
}
namespace methods {
struct Consumer {
void consume_ptr(RefCountable* ptr);
void consume_ref(const RefCountable& ref);
};
void foo() {
Consumer c;
c.consume_ptr(provide());
// expected-warning@-1{{Call argument for parameter 'ptr' is uncounted and unsafe}}
c.consume_ref(*provide());
// expected-warning@-1{{Call argument for parameter 'ref' is uncounted and unsafe}}
}
void foo2() {
struct Consumer {
void consume(RefCountable*) { some_function(); }
void whatever() {
consume(provide());
// expected-warning@-1{{Call argument is uncounted and unsafe}}
}
};
}
void foo3() {
struct Consumer {
void consume(RefCountable*) { some_function(); }
void whatever() {
this->consume(provide());
// expected-warning@-1{{Call argument is uncounted and unsafe}}
}
};
}
}
namespace casts {
RefCountable* downcast(RefCountable*);
void foo() {
consume_refcntbl(provide());
// expected-warning@-1{{Call argument is uncounted and unsafe}}
consume_refcntbl(static_cast<RefCountable*>(provide()));
// expected-warning@-1{{Call argument is uncounted and unsafe}}
consume_refcntbl(dynamic_cast<RefCountable*>(provide()));
// expected-warning@-1{{Call argument is uncounted and unsafe}}
consume_refcntbl(const_cast<RefCountable*>(provide()));
// expected-warning@-1{{Call argument is uncounted and unsafe}}
consume_refcntbl(reinterpret_cast<RefCountable*>(provide()));
// expected-warning@-1{{Call argument is uncounted and unsafe}}
consume_refcntbl(downcast(provide()));
// expected-warning@-1{{Call argument is uncounted and unsafe}}
consume_refcntbl(
static_cast<RefCountable*>(
downcast(
static_cast<RefCountable*>(
provide()
)
)
)
);
// expected-warning@-8{{Call argument is uncounted and unsafe}}
}
}
namespace null_ptr {
void foo_ref() {
consume_refcntbl(nullptr);
consume_refcntbl(0);
}
}
namespace ref_counted_lookalike {
struct Decoy {
RefCountable* get();
};
void foo() {
Decoy D;
consume_refcntbl(D.get());
// expected-warning@-1{{Call argument is uncounted and unsafe}}
}
}
namespace Ref_to_reference_conversion_operator {
template<typename T> struct Ref {
Ref() = default;
Ref(T*) { }
T* get() { return nullptr; }
operator T& () { return t; }
T t;
};
void consume_ref(RefCountable&) {}
void foo() {
Ref<RefCountable> bar;
consume_ref(bar);
}
}
namespace param_formarding_function {
void consume_ref_countable_ref(RefCountable&);
void consume_ref_countable_ptr(RefCountable*);
namespace ptr {
void foo(RefCountable* param) {
consume_ref_countable_ptr(param);
}
}
namespace ref {
void foo(RefCountable& param) {
consume_ref_countable_ref(param);
}
}
namespace ref_deref_operators {
void foo_ref(RefCountable& param) {
consume_ref_countable_ptr(&param);
}
void foo_ptr(RefCountable* param) {
consume_ref_countable_ref(*param);
}
}
namespace casts {
RefCountable* downcast(RefCountable*);
template<class T> T* bitwise_cast(T*);
template<class T> T* bit_cast(T*);
void foo(RefCountable* param) {
consume_ref_countable_ptr(downcast(param));
consume_ref_countable_ptr(bitwise_cast(param));
consume_ref_countable_ptr(bit_cast(param));
}
}
}
namespace param_formarding_lambda {
auto consume_ref_countable_ref = [](RefCountable&) { some_function(); };
auto consume_ref_countable_ptr = [](RefCountable*) { some_function(); };
namespace ptr {
void foo(RefCountable* param) {
consume_ref_countable_ptr(param);
}
}
namespace ref {
void foo(RefCountable& param) {
consume_ref_countable_ref(param);
}
}
namespace ref_deref_operators {
void foo_ref(RefCountable& param) {
consume_ref_countable_ptr(&param);
}
void foo_ptr(RefCountable* param) {
consume_ref_countable_ref(*param);
}
}
namespace casts {
RefCountable* downcast(RefCountable*) { return nullptr; }
template<class T>
T* bitwise_cast(T*) { return nullptr; }
void foo(RefCountable* param) {
consume_ref_countable_ptr(downcast(param));
consume_ref_countable_ptr(bitwise_cast(param));
}
}
}
namespace param_forwarding_method {
struct methodclass {
void consume_ref_countable_ref(RefCountable&) {};
static void consume_ref_countable_ptr(RefCountable*) {};
};
namespace ptr {
void foo(RefCountable* param) {
methodclass::consume_ref_countable_ptr(param);
}
}
namespace ref {
void foo(RefCountable& param) {
methodclass mc;
mc.consume_ref_countable_ref(param);
}
}
namespace ref_deref_operators {
void foo_ref(RefCountable& param) {
methodclass::consume_ref_countable_ptr(&param);
}
void foo_ptr(RefCountable* param) {
methodclass mc;
mc.consume_ref_countable_ref(*param);
}
}
namespace casts {
RefCountable* downcast(RefCountable*) { return nullptr; }
template<class T>
T* bitwise_cast(T*) { return nullptr; }
void foo(RefCountable* param) {
methodclass::consume_ref_countable_ptr(downcast(param));
methodclass::consume_ref_countable_ptr(bitwise_cast(param));
}
}
}
namespace downcast {
void consume_ref_countable(RefCountable*) {}
RefCountable* downcast(RefCountable*) { return nullptr; }
void foo() {
RefPtr<RefCountable> bar;
consume_ref_countable( downcast(bar.get()) );
}
}
namespace string_impl {
struct String {
RefCountable* impl() { return nullptr; }
};
struct AtomString {
RefCountable rc;
RefCountable& impl() { return rc; }
};
void consume_ptr(RefCountable*) {}
void consume_ref(RefCountable&) {}
namespace simple {
void foo() {
String s;
AtomString as;
consume_ptr(s.impl());
consume_ref(as.impl());
}
}
}
namespace default_arg {
RefCountable* global;
void function_with_default_arg(RefCountable* param = global);
// expected-warning@-1{{Call argument for parameter 'param' is uncounted and unsafe}}
void foo() {
function_with_default_arg();
}
}
namespace cxx_member_func {
Ref<RefCountable> provideProtected();
void foo() {
provide()->trivial();
provide()->method();
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
provideProtected()->method();
(provideProtected())->method();
};
}
namespace cxx_member_operator_call {
// The hidden this-pointer argument without a corresponding parameter caused couple bugs in parameter <-> argument attribution.
struct Foo {
Foo& operator+(RefCountable* bad);
friend Foo& operator-(Foo& lhs, RefCountable* bad);
void operator()(RefCountable* bad);
int operator[](unsigned i);
};
RefCountable* global;
struct Container : public RefCountable {
int m[4];
int& operator[](unsigned i) {
some_function();
return m[i];
}
};
Container container();
void foo12() {
Foo f;
f + global;
// expected-warning@-1{{Call argument for parameter 'bad' is uncounted and unsafe}}
f - global;
// expected-warning@-1{{Call argument for parameter 'bad' is uncounted and unsafe}}
f(global);
// expected-warning@-1{{Call argument for parameter 'bad' is uncounted and unsafe}}
container()[0] = 3;
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
}
}
namespace call_function_ptr {
class RefCountableWithWeakPtr : public RefCountable, public CanMakeWeakPtr<RefCountableWithWeakPtr> {
public:
void method();
};
RefCountableWithWeakPtr* provide();
void foo(void (*consume)(void*, RefCountableWithWeakPtr*), void (*consumeVar)(RefCountableWithWeakPtr*, ...), void (RefCountableWithWeakPtr::*method)()) {
consume(nullptr, provide());
// expected-warning@-1{{Call argument is uncounted and unsafe}}
consumeVar(nullptr, provide());
// expected-warning@-1{{Call argument is uncounted and unsafe}}
(provide()->*method)();
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
}
template <typename T, typename U, typename... Arg>
void bar(T* obj, int (U::* function)(void*, Arg... args), Arg... args) {
(obj->*function)(args...);
}
}
namespace call_with_ptr_on_ref {
Ref<RefCountable> provideProtected();
void bar(RefCountable* bad);
bool baz();
void foo(bool v) {
bar(v ? nullptr : provideProtected().ptr());
bar(baz() ? provideProtected().ptr() : nullptr);
bar(v ? provide() : provideProtected().ptr());
// expected-warning@-1{{Call argument for parameter 'bad' is uncounted and unsafe}}
bar(v ? provideProtected().ptr() : provide());
// expected-warning@-1{{Call argument for parameter 'bad' is uncounted and unsafe}}
}
}
namespace call_with_explicit_construct_from_auto {
struct Impl {
void ref() const;
void deref() const;
static Ref<Impl> create();
};
template <typename T>
struct ArgObj {
T* t;
};
struct Object {
Object();
Object(Ref<Impl>&&);
Impl* impl() const { return m_impl.get(); }
static Object create(ArgObj<char>&) { return Impl::create(); }
static void bar(Impl&);
private:
RefPtr<Impl> m_impl;
};
template<typename CharacterType> void foo()
{
auto result = Object::create(ArgObj<CharacterType> { });
Object::bar(Ref { *result.impl() });
}
}
namespace call_with_explicit_temporary_obj {
void foo() {
Ref { *provide() }->method();
RefPtr { provide() }->method();
}
template <typename T>
void bar() {
Ref(*provide())->method();
RefPtr(provide())->method();
}
void baz() {
bar<int>();
}
class Foo {
Ref<RefCountable> ensure();
void foo() {
Ref { ensure() }->method();
}
};
void baz(Ref<RefCountable>&& arg) {
Ref { arg }->method();
}
}
namespace call_with_explicit_construct {
class Obj {
public:
Obj(RefCountable* obj = provide(), RefCountable* otherObj = nullptr) {
// expected-warning@-1{{Call argument for parameter 'obj' is uncounted and unsafe}}
consume_refcntbl(obj);
if (otherObj)
otherObj->method();
}
Obj(RefCountable& obj) {
obj.method();
}
};
void foo(RefCountable* arg) {
Obj obj1;
Obj obj2(provide());
// expected-warning@-1{{Call argument for parameter 'obj' is uncounted and unsafe}}
Obj obj3(*provide());
// expected-warning@-1{{Call argument for parameter 'obj' is uncounted and unsafe}}
Obj obj4(Ref<RefCountable> { *provide() }.get());
Obj obj5(arg);
Obj obj6(arg, provide());
// expected-warning@-1{{Call argument for parameter 'otherObj' is uncounted and unsafe}}
}
}
namespace call_with_adopt_ref {
class Obj {
public:
void ref() const;
void deref() const;
void method();
};
// This is needed due to rdar://141692212.
struct dummy {
RefPtr<Obj> any;
};
void foo() {
adoptRef(new Obj)->method();
}
}
namespace call_on_member {
class SomeObj {
public:
static Ref<SomeObj> create() { return adoptRef(*new SomeObj); }
void ref() const;
void deref() const;
void doWork() {
m_obj->method();
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
m_obj.get()->method();
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
m_constObj->method();
}
void localWork() {
RefPtr obj = provide();
obj->method();
obj.get()->method();
}
void argWork(RefPtr<RefCountable> arg) {
arg->method();
arg.get()->method();
}
void temporaryWork() {
RefPtr { provide() }->method();
RefPtr { provide() }.get()->method();
}
void work();
private:
RefPtr<RefCountable> m_obj;
const RefPtr<RefCountable> m_constObj;
};
}
namespace call_with_weak_ptr {
class RefCountableWithWeakPtr : public RefCountable, public CanMakeWeakPtr<RefCountableWithWeakPtr> {
};
RefCountableWithWeakPtr* provide();
void consume(RefCountableWithWeakPtr*);
void foo() {
WeakPtr weakPtr = provide();
consume(weakPtr);
// expected-warning@-1{{Call argument is uncounted and unsafe}}
weakPtr->method();
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
}
struct Provider {
RefCountableWithWeakPtr* provide();
};
int intValue();
struct Container {
Container(Provider& provider)
: m_weakPtr(provider.provide())
, m_value(intValue())
{ }
private:
WeakPtr<RefCountableWithWeakPtr> m_weakPtr;
int m_value;
};
}