82 lines
3.2 KiB
C++
82 lines
3.2 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Copyright 2024 Bloomberg Finance L.P.
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// UNSUPPORTED: c++03 || c++11 || c++14 || c++17 || c++20
|
|
// ADDITIONAL_COMPILE_FLAGS: -freflection
|
|
// ADDITIONAL_COMPILE_FLAGS: -Wno-unneeded-internal-declaration -Wno-unused-variable -Wno-unused-value
|
|
|
|
// <experimental/reflection>
|
|
//
|
|
// [reflection]
|
|
|
|
#include <meta>
|
|
|
|
namespace NS {
|
|
struct A {
|
|
consteval int fn() const { return 24; }
|
|
};
|
|
} // namespace NS
|
|
|
|
struct A {
|
|
constexpr int fn() const { return 42; }
|
|
|
|
consteval void void_fn() const {
|
|
// no-op
|
|
};
|
|
};
|
|
|
|
struct B {};
|
|
|
|
int main() {
|
|
// ======================
|
|
// non-static member functions
|
|
// ======================
|
|
constexpr A expectedClass{};
|
|
reflect_invoke(^^A::fn, {^^expectedClass});
|
|
// expected-error@-1 {{expressions of consteval-only type}}
|
|
|
|
reflect_invoke(^^A::void_fn, {^^expectedClass});
|
|
// expected-error-re@-1 {{call to consteval function 'std::meta::reflect_invoke<{{.*}}>' is not a constant expression}}
|
|
// expected-note@-2 {{cannot invoke reflection of void-returning function}}
|
|
// expected-error@-3 {{consteval-only type}}
|
|
|
|
reflect_invoke(^^A::fn, {});
|
|
// expected-error-re@-1 {{call to consteval function 'std::meta::reflect_invoke<{{.*}}>' is not a constant expression}}
|
|
// expected-note@-2 {{expected related object reflection as a first argument for invoking non-static member function}}
|
|
// expected-error@-3 {{consteval-only type}}
|
|
|
|
reflect_invoke(^^A::fn, {std::meta::reflect_constant(42)});
|
|
// expected-error-re@-1 {{call to consteval function 'std::meta::reflect_invoke<{{.*}}>' is not a constant expression}}
|
|
// expected-note@-2 {{expected related object reflection as a first argument for invoking non-static member function}}
|
|
// expected-error@-3 {{consteval-only type}}
|
|
|
|
constexpr B differentClass{};
|
|
reflect_invoke(^^A::fn, {^^differentClass});
|
|
// expected-error-re@-1 {{call to consteval function 'std::meta::reflect_invoke<{{.*}}>' is not a constant expression}}
|
|
// expected-note@-2 {{method is not a member of given object reflection}}
|
|
// expected-error@-3 {{consteval-only type}}
|
|
|
|
constexpr NS::A differentNamespaceClass{};
|
|
reflect_invoke(^^A::fn, {^^differentNamespaceClass});
|
|
// expected-error-re@-1 {{call to consteval function 'std::meta::reflect_invoke<{{.*}}>' is not a constant expression}}
|
|
// expected-note@-2 {{method is not a member of given object reflection}}
|
|
// expected-error@-3 {{consteval-only type}}
|
|
|
|
// test that implementation workaround with getting constexpr method from pointer couldn't be abused
|
|
constexpr int (A::*constexpr_pointer)() const = &A::fn;
|
|
reflect_invoke(^^constexpr_pointer, {^^expectedClass}); // ok
|
|
// expected-error@-1 {{consteval-only type}}
|
|
|
|
int (A::*pointer)() const = &A::fn;
|
|
reflect_invoke(^^pointer, {^^expectedClass});
|
|
// expected-error-re@-1 {{call to consteval function 'std::meta::reflect_invoke<{{.*}}>' is not a constant expression}}
|
|
// expected-error@-2 {{consteval-only type}}
|
|
}
|