// RUN: %clang_cc1 -verify -fsyntax-only %s -std=c++23 void func() { // expected-note {{'func' declared here}} __builtin_invoke(); // expected-error {{too few arguments to function call, expected at least 1, have 0}} } void nfunc() noexcept {} struct S {}; void argfunc(int, S) {} // expected-note {{'argfunc' declared here}} struct Callable { void operator()() {} void func() {} int var; }; void* malloc(decltype(sizeof(int))); template struct pointer_wrapper { T* v; T& operator*() { return *v; } }; namespace std { template class reference_wrapper { T* ptr; public: constexpr reference_wrapper(T& ref) : ptr(&ref) {} constexpr T& get() { return *ptr; } }; template constexpr reference_wrapper ref(T& v) { return reference_wrapper(v); } } // namespace std struct InvalidSpecialization1 { void func() {} int var; }; template <> class std::reference_wrapper { public: reference_wrapper(InvalidSpecialization1&) {} }; struct InvalidSpecialization2 { void func() {} int var; }; template <> class std::reference_wrapper { public: reference_wrapper(InvalidSpecialization2&) {} private: InvalidSpecialization2& get(); // expected-note 2 {{declared private here}} }; struct ExplicitObjectParam { void func(this const ExplicitObjectParam& self) {} }; struct Incomplete; // expected-note 2 {{forward declaration}} struct Incomplete2; void incomplete_by_val_test(Incomplete); void incomplete_test(Incomplete& incomplete) { __builtin_invoke((int (Incomplete2::*)){}, incomplete); // expected-error {{incomplete type 'Incomplete' used in type trait expression}} \ expected-error {{indirection requires pointer operand ('Incomplete' invalid)}} __builtin_invoke(incomplete_test, incomplete); __builtin_invoke(incomplete_by_val_test, incomplete); // expected-error {{argument type 'Incomplete' is incomplete}} } void call() { __builtin_invoke(func); __builtin_invoke(nfunc); static_assert(!noexcept(__builtin_invoke(func))); static_assert(noexcept(__builtin_invoke(nfunc))); __builtin_invoke(func, 1); // expected-error {{too many arguments to function call, expected 0, have 1}} __builtin_invoke(argfunc, 1); // expected-error {{too few arguments to function call, expected 2, have 1}} __builtin_invoke(Callable{}); __builtin_invoke(malloc, 0); __builtin_invoke(__builtin_malloc, 0); // expected-error {{builtin functions must be directly called}} // Variadic function void variadic_func(int, ...); // expected-note {{declared here}} __builtin_invoke(variadic_func); // expected-error {{too few arguments to function call, expected at least 1, have 0}} __builtin_invoke(variadic_func, 1); __builtin_invoke(variadic_func, 1, 2, 3); // static member function struct StaticMember { static void func(int); }; __builtin_invoke(StaticMember::func, 1); StaticMember sm; __builtin_invoke(sm.func, 1); // lambda __builtin_invoke([] {}); __builtin_invoke([](int) {}, 1); // Member function pointer __builtin_invoke(&Callable::func); // expected-error {{too few arguments to function call, expected at least 2, have 1}} __builtin_invoke(&Callable::func, 1); // expected-error {{indirection requires pointer operand ('int' invalid)}} __builtin_invoke(&Callable::func, Callable{}); __builtin_invoke(&Callable::func, Callable{}, 1); // expected-error {{too many arguments to function call, expected 0, have 1}} __builtin_invoke(&ExplicitObjectParam::func, ExplicitObjectParam{}); Callable c; __builtin_invoke(&Callable::func, &c); __builtin_invoke(&Callable::func, std::ref(c)); __builtin_invoke(&Callable::func, &c); __builtin_invoke(&Callable::func, &c, 2); // expected-error {{too many arguments to function call, expected 0, have 1}} __builtin_invoke(&Callable::func, pointer_wrapper{&c}); __builtin_invoke(&Callable::func, pointer_wrapper{&c}, 2); // expected-error {{too many arguments to function call, expected 0, have 1}} InvalidSpecialization1 is1; InvalidSpecialization2 is2; __builtin_invoke(&InvalidSpecialization1::func, std::ref(is1)); // expected-error {{no member named 'get' in 'std::reference_wrapper'}} __builtin_invoke(&InvalidSpecialization2::func, std::ref(is2)); // expected-error {{'get' is a private member of 'std::reference_wrapper'}} // Member data pointer __builtin_invoke(&Callable::var); // expected-error {{too few arguments to function call, expected at least 2, have 1}} __builtin_invoke(&Callable::var, 1); // expected-error {{indirection requires pointer operand ('int' invalid)}} (void)__builtin_invoke(&Callable::var, Callable{}); __builtin_invoke(&Callable::var, Callable{}, 1); // expected-error {{too many arguments to function call, expected 2, have 3}} (void)__builtin_invoke(&Callable::var, &c); (void)__builtin_invoke(&Callable::var, std::ref(c)); (void)__builtin_invoke(&Callable::var, &c); __builtin_invoke(&Callable::var, &c, 2); // expected-error {{too many arguments to function call, expected 2, have 3}} (void)__builtin_invoke(&Callable::var, pointer_wrapper{&c}); __builtin_invoke(&Callable::var, pointer_wrapper{&c}, 2); // expected-error {{too many arguments to function call, expected 2, have 3}} __builtin_invoke(&InvalidSpecialization1::var, std::ref(is1)); // expected-error {{no member named 'get' in 'std::reference_wrapper'}} (void)__builtin_invoke(&InvalidSpecialization2::var, std::ref(is2)); // expected-error {{'get' is a private member of 'std::reference_wrapper'}} } [[nodiscard]] int diagnose_discard(); int no_diagnose_discard(); namespace std { template auto invoke(Args&&... args) -> decltype(__builtin_invoke(args...)); } // namespace std template concept invocable = requires(Args... args) { __builtin_invoke(args...); }; static_assert(!invocable>); static_assert(!invocable>); void test3() { __builtin_invoke(diagnose_discard); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} __builtin_invoke(no_diagnose_discard); } template auto test(T v) { return __builtin_invoke(v); } auto call2() { test(call); } template void func(ClassT& c, FuncT&& func) { __builtin_invoke(func, c, 1, 2, 3); // expected-error {{too many arguments to function call, expected 0, have 3}} } struct DependentTest { void func(int, int, int); void bad_func(); }; void call3() { DependentTest d; func(d, &DependentTest::func); func(d, &DependentTest::bad_func); // expected-note {{requested here}} } constexpr int constexpr_func() { return 42; } struct ConstexprTestStruct { int i; constexpr int func() { return 55; } }; // Make sure that constant evaluation works static_assert([]() { ConstexprTestStruct s; if (__builtin_invoke(&ConstexprTestStruct::func, s) != 55) // [func.requires]/p1.1 return false; if (__builtin_invoke(&ConstexprTestStruct::func, std::ref(s)) != 55) // [func.requires]/p1.2 return false; if (__builtin_invoke(&ConstexprTestStruct::func, &s) != 55) // [func.requires]/p1.3 return false; s.i = 22; if (__builtin_invoke(&ConstexprTestStruct::i, s) != 22) // [func.requires]/p1.4 return false; if (__builtin_invoke(&ConstexprTestStruct::i, std::ref(s)) != 22) // [func.requires]/p1.5 return false; if (__builtin_invoke(&ConstexprTestStruct::i, &s) != 22) // [func.requires]/p1.6 return false; // [func.requires]/p1.7 if (__builtin_invoke(constexpr_func) != 42) return false; if (__builtin_invoke([] { return 34; }) != 34) return false; return true; }());