241 lines · cpp
1// RUN: %clang_cc1 -verify -fsyntax-only %s -std=c++232 3void func() { // expected-note {{'func' declared here}}4 __builtin_invoke(); // expected-error {{too few arguments to function call, expected at least 1, have 0}}5}6 7void nfunc() noexcept {}8 9struct S {};10void argfunc(int, S) {} // expected-note {{'argfunc' declared here}}11 12struct Callable {13 void operator()() {}14 15 void func() {}16 17 int var;18};19 20void* malloc(decltype(sizeof(int)));21 22template <class T>23struct pointer_wrapper {24 T* v;25 26 T& operator*() {27 return *v;28 }29};30 31namespace std {32 template <class T>33 class reference_wrapper {34 T* ptr;35 36 public:37 constexpr reference_wrapper(T& ref) : ptr(&ref) {}38 39 constexpr T& get() { return *ptr; }40 };41 42 template <class T>43 constexpr reference_wrapper<T> ref(T& v) {44 return reference_wrapper<T>(v);45 }46} // namespace std47 48struct InvalidSpecialization1 {49 void func() {}50 51 int var;52};53 54template <>55class std::reference_wrapper<InvalidSpecialization1> {56public:57 reference_wrapper(InvalidSpecialization1&) {}58};59 60struct InvalidSpecialization2 {61 void func() {}62 63 int var;64};65 66template <>67class std::reference_wrapper<InvalidSpecialization2> {68public:69 reference_wrapper(InvalidSpecialization2&) {}70 71private:72 InvalidSpecialization2& get(); // expected-note 2 {{declared private here}}73};74 75struct ExplicitObjectParam {76 void func(this const ExplicitObjectParam& self) {}77};78 79struct Incomplete; // expected-note 2 {{forward declaration}}80struct Incomplete2;81 82void incomplete_by_val_test(Incomplete);83 84void incomplete_test(Incomplete& incomplete) {85 __builtin_invoke((int (Incomplete2::*)){}, incomplete); // expected-error {{incomplete type 'Incomplete' used in type trait expression}} \86 expected-error {{indirection requires pointer operand ('Incomplete' invalid)}}87 __builtin_invoke(incomplete_test, incomplete);88 __builtin_invoke(incomplete_by_val_test, incomplete); // expected-error {{argument type 'Incomplete' is incomplete}}89}90 91void call() {92 __builtin_invoke(func);93 __builtin_invoke(nfunc);94 static_assert(!noexcept(__builtin_invoke(func)));95 static_assert(noexcept(__builtin_invoke(nfunc)));96 __builtin_invoke(func, 1); // expected-error {{too many arguments to function call, expected 0, have 1}}97 __builtin_invoke(argfunc, 1); // expected-error {{too few arguments to function call, expected 2, have 1}}98 __builtin_invoke(Callable{});99 __builtin_invoke(malloc, 0);100 __builtin_invoke(__builtin_malloc, 0); // expected-error {{builtin functions must be directly called}}101 102 // Variadic function103 void variadic_func(int, ...); // expected-note {{declared here}}104 105 __builtin_invoke(variadic_func); // expected-error {{too few arguments to function call, expected at least 1, have 0}}106 __builtin_invoke(variadic_func, 1);107 __builtin_invoke(variadic_func, 1, 2, 3);108 109 // static member function110 struct StaticMember {111 static void func(int);112 };113 114 __builtin_invoke(StaticMember::func, 1);115 StaticMember sm;116 __builtin_invoke(sm.func, 1);117 118 // lambda119 __builtin_invoke([] {});120 __builtin_invoke([](int) {}, 1);121 122 // Member function pointer123 __builtin_invoke(&Callable::func); // expected-error {{too few arguments to function call, expected at least 2, have 1}}124 __builtin_invoke(&Callable::func, 1); // expected-error {{indirection requires pointer operand ('int' invalid)}}125 __builtin_invoke(&Callable::func, Callable{});126 __builtin_invoke(&Callable::func, Callable{}, 1); // expected-error {{too many arguments to function call, expected 0, have 1}}127 __builtin_invoke(&ExplicitObjectParam::func, ExplicitObjectParam{});128 129 Callable c;130 __builtin_invoke(&Callable::func, &c);131 __builtin_invoke(&Callable::func, std::ref(c));132 __builtin_invoke(&Callable::func, &c);133 __builtin_invoke(&Callable::func, &c, 2); // expected-error {{too many arguments to function call, expected 0, have 1}}134 __builtin_invoke(&Callable::func, pointer_wrapper<Callable>{&c});135 __builtin_invoke(&Callable::func, pointer_wrapper<Callable>{&c}, 2); // expected-error {{too many arguments to function call, expected 0, have 1}}136 137 InvalidSpecialization1 is1;138 InvalidSpecialization2 is2;139 __builtin_invoke(&InvalidSpecialization1::func, std::ref(is1)); // expected-error {{no member named 'get' in 'std::reference_wrapper<InvalidSpecialization1>'}}140 __builtin_invoke(&InvalidSpecialization2::func, std::ref(is2)); // expected-error {{'get' is a private member of 'std::reference_wrapper<InvalidSpecialization2>'}}141 142 // Member data pointer143 __builtin_invoke(&Callable::var); // expected-error {{too few arguments to function call, expected at least 2, have 1}}144 __builtin_invoke(&Callable::var, 1); // expected-error {{indirection requires pointer operand ('int' invalid)}}145 (void)__builtin_invoke(&Callable::var, Callable{});146 __builtin_invoke(&Callable::var, Callable{}, 1); // expected-error {{too many arguments to function call, expected 2, have 3}}147 148 (void)__builtin_invoke(&Callable::var, &c);149 (void)__builtin_invoke(&Callable::var, std::ref(c));150 (void)__builtin_invoke(&Callable::var, &c);151 __builtin_invoke(&Callable::var, &c, 2); // expected-error {{too many arguments to function call, expected 2, have 3}}152 (void)__builtin_invoke(&Callable::var, pointer_wrapper<Callable>{&c});153 __builtin_invoke(&Callable::var, pointer_wrapper<Callable>{&c}, 2); // expected-error {{too many arguments to function call, expected 2, have 3}}154 155 __builtin_invoke(&InvalidSpecialization1::var, std::ref(is1)); // expected-error {{no member named 'get' in 'std::reference_wrapper<InvalidSpecialization1>'}}156 (void)__builtin_invoke(&InvalidSpecialization2::var, std::ref(is2)); // expected-error {{'get' is a private member of 'std::reference_wrapper<InvalidSpecialization2>'}}157}158 159[[nodiscard]] int diagnose_discard();160int no_diagnose_discard();161 162namespace std {163 template <class... Args>164 auto invoke(Args&&... args) -> decltype(__builtin_invoke(args...));165} // namespace std166 167template <class... Args>168concept invocable = requires(Args... args) { __builtin_invoke(args...); };169 170static_assert(!invocable<std::reference_wrapper<InvalidSpecialization1>>);171static_assert(!invocable<std::reference_wrapper<InvalidSpecialization2>>);172 173void test3() {174 __builtin_invoke(diagnose_discard); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}175 __builtin_invoke(no_diagnose_discard);176}177 178template <class T>179auto test(T v) {180 return __builtin_invoke(v);181}182 183auto call2() {184 test(call);185}186 187template <class ClassT, class FuncT>188void func(ClassT& c, FuncT&& func) {189 __builtin_invoke(func, c, 1, 2, 3); // expected-error {{too many arguments to function call, expected 0, have 3}}190}191 192struct DependentTest {193 void func(int, int, int);194 void bad_func();195};196 197void call3() {198 DependentTest d;199 func(d, &DependentTest::func);200 func(d, &DependentTest::bad_func); // expected-note {{requested here}}201}202 203constexpr int constexpr_func() {204 return 42;205}206 207struct ConstexprTestStruct {208 int i;209 constexpr int func() {210 return 55;211 }212};213 214// Make sure that constant evaluation works215static_assert([]() {216 217 ConstexprTestStruct s;218 if (__builtin_invoke(&ConstexprTestStruct::func, s) != 55) // [func.requires]/p1.1219 return false;220 if (__builtin_invoke(&ConstexprTestStruct::func, std::ref(s)) != 55) // [func.requires]/p1.2221 return false;222 if (__builtin_invoke(&ConstexprTestStruct::func, &s) != 55) // [func.requires]/p1.3223 return false;224 225 s.i = 22;226 if (__builtin_invoke(&ConstexprTestStruct::i, s) != 22) // [func.requires]/p1.4227 return false;228 if (__builtin_invoke(&ConstexprTestStruct::i, std::ref(s)) != 22) // [func.requires]/p1.5229 return false;230 if (__builtin_invoke(&ConstexprTestStruct::i, &s) != 22) // [func.requires]/p1.6231 return false;232 233 // [func.requires]/p1.7234 if (__builtin_invoke(constexpr_func) != 42)235 return false;236 if (__builtin_invoke([] { return 34; }) != 34)237 return false;238 239 return true;240}());241