Files
clang-p2996/clang/test/Reflection/lift-operator.cpp
2025-06-12 16:55:19 -04:00

273 lines
8.5 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
//
//===----------------------------------------------------------------------===//
//
// RUN: %clang_cc1 %s -std=c++23 -freflection -verify
// Reflecting Types
using info = decltype(^^void);
constexpr info info_void = ^^void;
constexpr info info_decltype = ^^decltype(42);
using alias = int;
constexpr info info_alias = ^^alias;
constexpr info info_infoint = ^^decltype(^^int);
constexpr info abominable = ^^void() const & noexcept;
// Reflecting variables
constexpr int i = 42;
constexpr info info_i = ^^i;
// Reflecting templates
template <typename T>
void TemplateFunc();
constexpr info info_template_func = ^^TemplateFunc;
template <typename T>
int TemplateVar;
constexpr info info_template_var = ^^TemplateVar;
template <typename T>
struct TemplateStruct {};
constexpr info info_template_struct = ^^TemplateStruct;
// Reflecting members of a class
struct Members {
struct Type {};
int member_var;
static int static_member_var;
int member_func();
static int static_member_func();
};
constexpr info info_nested_type = ^^Members::Type;
constexpr info info_mem_var = ^^Members::member_var;
constexpr info info_static_mem_var = ^^Members::static_member_var;
constexpr info info_mem_func = ^^Members::member_func;
constexpr info info_static_mem_func = ^^Members::static_member_func;
// Reflecting member templates
struct MemberTemplates {
template <typename T>
struct NestedTemplateStruct {};
template <typename T>
void template_func();
template <typename T>
MemberTemplates &operator+(const T&);
template <typename T>
static void template_static_func();
template <typename T>
static int template_var;
};
constexpr info info_nested_template_struct =
^^MemberTemplates::NestedTemplateStruct;
constexpr info info_nested_template_struct2 =
^^MemberTemplates::template NestedTemplateStruct;
constexpr info info_nested_template_func = ^^MemberTemplates::template_func;
constexpr info info_nested_template_func2 =
^^MemberTemplates::template template_func;
constexpr info info_nested_template_static_func =
^^MemberTemplates::template_static_func;
constexpr info info_nested_template_static_func2 =
^^MemberTemplates::template template_static_func;
constexpr info info_nested_template_var = ^^MemberTemplates::template_var;
constexpr info info_nested_template_var2 =
^^MemberTemplates::template template_var;
constexpr info info_nested_template_operator = ^^MemberTemplates::operator+;
constexpr info info_nested_template_operator2 =
^^MemberTemplates::template operator+;
template <typename T>
void DepScope() {
constexpr info nested_struct = ^^T::template NestedTemplateStruct;
constexpr info nested_func = ^^T::template template_func;
constexpr info nested_static_func = ^^T::template template_static_func;
constexpr info nested_var = ^^T::template template_var;
constexpr info nested_operator = ^^T::template operator+;
}
void InstantiateDepScope() {
DepScope<MemberTemplates>();
}
// Reflecting function scope variables
void reflect_func_scope(int param) {
constexpr info info_param = ^^param;
int local_var;
constexpr info info_local = ^^local_var;
static int static_var;
constexpr info info_static = ^^static_var;
thread_local int thread_var;
constexpr info info_thread = ^^thread_var;
struct local_type {};
constexpr info info_type = ^^local_type;
}
// Reflecting a template parameter
template <typename T>
consteval info foo() {
return ^^T;
}
constexpr info info_tmplparam = foo<int>();
namespace ns {}
constexpr info info_ns = ^^ns;
namespace ns {}
static_assert(info_ns == ^^ns);
// Reflection as a default initializer for a class member
class WithDefaultInitializer {
[[maybe_unused]] info k = ^^::;
};
constexpr WithDefaultInitializer with_default_init;
// Type with a nested name specifier that can't be parsed as an identifier.
namespace A { namespace B { using C = int; } }
constexpr auto complicated_type = ^^A::B::C &;
// ============
// east_west_cv
// ============
namespace east_west_cv {
struct S {};
static_assert(^^S const == ^^const S);
static_assert(^^S volatile == ^^volatile S);
} // namespace east_west_cv
// ==============
// self_reference
// ==============
namespace self_reference {
struct S {
consteval S() {}
decltype(^^::) k = ^^S::k;
};
consteval int fn(decltype(^^::) x = ^^x) { return 0; }
constexpr int x = fn();
} // namspace self_reference
// =================
// enclosing_lambdas
// =================
namespace enclosing_lambdas {
static int s1;
void fn() {
int l1;
static int s2;
constexpr auto rl1 = ^^l1;
(void) [] -> decltype(^^s1, ^^l1, s2) {
// expected-error@-1 {{intervening lambda expression}}
int l2;
constexpr auto rl1_2 = ^^l1;
// expected-error@-1 {{intervening lambda expression}}
constexpr auto rl2 = ^^l2;
};
}
} // namespace enclosing_lambdas
// ====================
// requires_expressions
// ====================
namespace requires_expressions {
void fn(int p) {
(void) requires(int a) { ^^p; };
(void) requires(int a) { ^^a; };
// expected-error@-1 {{local parameter of a requires-expression}}
}
} // namespace requires_expressions
// ===================
// overload_resolution
// ===================
namespace overload_resolution {
template <typename T> void fn() requires (^^T != ^^int);
template <typename T> void fn() requires (^^T == ^^int);
template <typename T> void fn() requires (sizeof(T) == sizeof(int));
[[maybe_unused]] constexpr auto a = ^^fn<char>; // OK
} // namespace overload_resolution
// =======================================
// bb_clang_p2996_issue_35_regression_test
// =======================================
namespace bb_clang_p2996_issue_35_regression_test {
template <auto R = ^^::> class S {};
S s;
} // namespace bb_clang_p2996_issue_35_regression_test
// =======================================
// bb_clang_p2996_issue_73_regression_test
// =======================================
namespace bb_clang_p2996_issue_73_regression_test {
namespace foo {
struct foo {
static_assert(^^foo == ^^::bb_clang_p2996_issue_73_regression_test::foo::foo);
};
static_assert(^^foo == ^^::bb_clang_p2996_issue_73_regression_test::foo::foo);
} // namespace foo
namespace tfoo {
template <typename T> struct tfoo {
static_assert(^^tfoo == ^^tfoo<T>);
};
static_assert(^^tfoo ==
^^::bb_clang_p2996_issue_73_regression_test::tfoo::tfoo);
tfoo<int> instantiation;
} // namespace tfoo
static_assert(^^foo == ^^::bb_clang_p2996_issue_73_regression_test::foo);
static_assert(^^tfoo == ^^::bb_clang_p2996_issue_73_regression_test::tfoo);
} // namespace bb_clang_p2996_issue_73_regression_test
// =======================================
// bb_clang_p2996_issue_11_regression_test
// =======================================
namespace bb_clang_p2996_issue_11_regression_test {
constexpr auto a = ^^:: != ^^int &;
constexpr auto b = ^^:: != ^^int &&;
constexpr auto c = ^^:: != ^^int() &;
constexpr auto d = ^^:: != ^^int() &&;
constexpr auto e = ^^:: != ^^int & true;
//expected-error@-1 {{after top level declarator}} \
//expected-warning@-1 {{'&' binds to reflection operand}}
constexpr auto f = ^^:: != ^^int && true;
//expected-error@-1 {{after top level declarator}} \
//expected-warning@-1 {{'&&' binds to reflection operand}}
constexpr auto g = ^^:: != ^^int() & true;
//expected-error@-1 {{after top level declarator}} \
//expected-warning@-1 {{'&' binds to reflection operand}}
constexpr auto h = ^^:: != ^^int() && true;
//expected-error@-1 {{after top level declarator}} \
//expected-warning@-1 {{'&&' binds to reflection operand}}
} // namespace bb_clang_p2996_issue_11_regression_test