Files
clang-p2996/libcxx/test/std/experimental/reflection/define-aggregate.pass.cpp
Barry Revzin 97a102f706 Improve <meta> compile time (#164)
* 1. Remove variant usage

* 2. Remove <algorithm>

* 3. Remove most of <ranges>
2025-06-29 09:30:19 -04:00

428 lines
12 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
// ADDITIONAL_COMPILE_FLAGS: -Wno-unused-private-field
// <experimental/reflection>
//
// [reflection]
//
// RUN: %{exec} %t.exe > %t.stdout
#include <meta>
#include <print>
#include <ranges>
constexpr auto ctx = std::meta::access_context::unchecked();
// =========================
// completion_with_no_fields
// =========================
namespace completion_with_no_fields {
struct S;
class C;
union U;
static_assert(!is_complete_type(^^S));
static_assert(!is_complete_type(^^C));
static_assert(!is_complete_type(^^U));
consteval {
define_aggregate(^^S, {});
define_aggregate(^^C, {});
define_aggregate(^^U, {});
}
static_assert(is_complete_type(^^S));
static_assert(is_complete_type(^^C));
static_assert(is_complete_type(^^U));
static_assert(nonstatic_data_members_of(^^S, ctx).size() == 0);
static_assert(nonstatic_data_members_of(^^C, ctx).size() == 0);
static_assert(nonstatic_data_members_of(^^U, ctx).size() == 0);
S s;
C c;
U u;
} // namespace completion_with_no_fields
// ==============
// test_all_flags
// ==============
namespace test_all_flags {
struct S;
static_assert(!is_complete_type(^^S));
consteval {
define_aggregate(^^S, {
data_member_spec(^^int, {.name="count", .alignment=16}),
data_member_spec(^^bool, {.name="flag"}),
data_member_spec(^^int, {.width=0}),
data_member_spec(^^int, {.width=5}),
});
}
static_assert(is_complete_type(^^S));
// unnamed bitfields are not nonstatic data members.
static_assert(nonstatic_data_members_of(^^S, ctx).size() == 3);
static_assert(alignment_of(^^S::count) == 16);
static_assert(bit_size_of(nonstatic_data_members_of(^^S, ctx)[2]) == 5);
static_assert((members_of(^^S, ctx) |
std::views::filter(std::meta::is_bit_field) |
std::views::transform(std::meta::bit_size_of) |
std::ranges::to<std::vector>()) == std::vector<size_t> {0, 5});
constexpr S s = {14, true, 11};
static_assert(s.count == 14);
static_assert(s.flag);
static_assert(s.[:nonstatic_data_members_of(^^S, ctx)[2]:] == 11);
struct Empty {};
struct WithEmpty;
consteval {
define_aggregate(^^WithEmpty, {
data_member_spec(^^int, {}),
data_member_spec(^^Empty, {.no_unique_address=true}),
});
}
static_assert(sizeof(WithEmpty) == sizeof(int));
} // namespace test_all_flags
// ================
// class_completion
// ================
namespace class_completion {
class C;
static_assert(!is_complete_type(^^C));
consteval {
define_aggregate(^^C, {
data_member_spec(^^int, {.name="count"}),
data_member_spec(^^bool, {.name="flag"}),
});
}
static_assert(is_complete_type(^^C));
static_assert(nonstatic_data_members_of(^^C, ctx).size() == 2);
static_assert(
(members_of(^^C, ctx) |
std::views::filter(std::meta::is_nonstatic_data_member) |
std::views::filter(std::meta::is_public) |
std::ranges::to<std::vector>()).size() == 2);
C c;
} // namespace class_completion
// ================
// union_completion
// ================
namespace union_completion {
union U;
static_assert(!is_complete_type(^^U));
consteval {
define_aggregate(^^U, {
data_member_spec(^^int, {.name="count"}),
data_member_spec(^^bool, {.name="flag"}),
});
}
static_assert(is_complete_type(^^U));
static_assert(size_of(^^U) == size_of(^^U::count));
static_assert(nonstatic_data_members_of(^^U, ctx).size() == 2);
static_assert(
(members_of(^^U, ctx) |
std::views::filter(std::meta::is_nonstatic_data_member) |
std::ranges::to<std::vector>()).size() == 2);
U u = {13};
} // namespace union_completion
// ==================================
// template_specialization_completion
// ==================================
namespace template_specialization_completion {
template <int Idx> struct S;
template <> struct S<0> {};
template <> struct S<2> {};
consteval int nextIncompleteIdx() {
for (int Idx = 0;; ++Idx)
if (!is_complete_type(substitute(^^S, {std::meta::reflect_constant(Idx)})))
return Idx;
}
consteval {
define_aggregate(^^S<nextIncompleteIdx()>, {
data_member_spec(^^int, {.name="mem"}),
});
}
consteval {
define_aggregate(^^S<nextIncompleteIdx()>, {
data_member_spec(^^bool, {.name="mem"}),
});
}
static_assert(nonstatic_data_members_of(^^S<0>, ctx).size() == 0);
static_assert(nonstatic_data_members_of(^^S<1>, ctx).size() == 1);
static_assert(type_of(^^S<1>::mem) == ^^int);
static_assert(nonstatic_data_members_of(^^S<2>, ctx).size() == 0);
static_assert(nonstatic_data_members_of(^^S<3>, ctx).size() == 1);
static_assert(type_of(^^S<3>::mem) == ^^bool);
static_assert(!is_complete_type(^^S<4>));
} // namespace template_specialization_completion
// ============================
// completion_of_dependent_type
// ============================
namespace completion_of_dependent_type {
template <typename T, std::meta::info... Mems>
consteval bool completeDefn() {
return is_type(define_aggregate(^^T, {Mems...}));
}
struct S;
static_assert(!is_complete_type(^^S));
consteval {
completeDefn<S, data_member_spec(^^bool, {.name="flag"}),
data_member_spec(^^int, {.name="count"})>();
}
static_assert(is_complete_type(^^S));
static_assert(nonstatic_data_members_of(^^S, ctx).size() == 2);
S s;
} // namespace completion_of_dependent_type
// =========================
// completion_of_local_class
// =========================
namespace completion_of_local_class {
consteval int fn() {
struct S;
consteval {
define_aggregate(^^S, {
data_member_spec(^^int, {.name="member"})
});
}
S s = {13};
return s.member;
}
static_assert(fn() == 13);
} // namespace completion_of_local_class
// ======================================
// completion_of_template_with_pack_param
// ======================================
namespace completion_of_template_with_pack_param {
template <typename...>
struct foo;
consteval {
define_aggregate(^^foo<>, { data_member_spec(^^int, {.name="mem1"}) });
define_aggregate(^^foo<int>, { data_member_spec(^^int, {.name="mem2"}) });
define_aggregate(^^foo<bool, char>, {
data_member_spec(^^int, {.name="mem3"})
});
}
constexpr foo<> f1 = {1};
constexpr foo<int> f2 = {2};
constexpr foo<bool, char> f3 = {3};
static_assert(f1.mem1 + f2.mem2 + f3.mem3 == 6);
} // namespace completion_of_template_with_pack_param
// =========================
// with_non_contiguous_range
// =========================
namespace with_non_contiguous_range {
struct foo;
consteval {
define_aggregate(
^^foo,
std::views::join(std::vector<std::vector<std::pair<bool,
std::meta::info>>> {
{
std::make_pair(true, std::meta::data_member_spec(^^int, {.name="i"})),
}, {
std::make_pair(false, std::meta::data_member_spec(^^std::string)),
std::make_pair(true, std::meta::data_member_spec(^^bool, {.name="b"})),
}
}) |
std::views::filter([](auto P) { return P.first; }) |
std::views::transform([](auto P) { return P.second;
}));
}
static_assert(type_of(^^foo::i) == ^^int);
static_assert(type_of(^^foo::b) == ^^bool);
static_assert(nonstatic_data_members_of(^^foo, ctx).size() == 2);
} // namespace with_non_contiguous_range
// =============================
// utf8_identifier_of_roundtrips
// =============================
namespace utf8_identifier_of_roundtrip {
class Kühl { };
class Cls1;
consteval {
define_aggregate(^^Cls1, {
data_member_spec(^^int, {.name=u8identifier_of(^^Kühl)})
});
}
static_assert(u8identifier_of(nonstatic_data_members_of(^^Cls1, ctx)[0]) ==
u8"Kühl");
static_assert(identifier_of(nonstatic_data_members_of(^^Cls1, ctx)[0]) ==
"Kühl");
} // namespace utf8_identifier_of_roundtrip
// ===========================
// data_member_spec_comparison
// ===========================
namespace data_member_spec_comparison {
static_assert(data_member_spec(^^int, {}) != ^^int);
static_assert(data_member_spec(^^int, {}) == data_member_spec(^^int, {}));
static_assert(data_member_spec(^^int, {}) !=
data_member_spec(^^int, {.name="i"}));
static_assert(data_member_spec(^^int, {.name=u8"i"}) ==
data_member_spec(^^int, {.name="i"}));
static_assert(data_member_spec(^^int, {.name="i", .alignment=4}) !=
data_member_spec(^^int, {.name="i"}));
static_assert(data_member_spec(^^int, {.name=""}) ==
data_member_spec(^^int, {}));
using Alias = int;
static_assert(data_member_spec(^^Alias, {}) != data_member_spec(^^int, {}));
} // namespace data_member_spec_comparison
// ====================
// immediate_escalating
// ====================
namespace immediate_escalating {
struct S;
auto L = [] {
define_aggregate(^^S, {});
return 0;
};
consteval { L(); }
S s;
} // namespace immediate_escalating
// ===================
// checks_for_overflow
// ===================
namespace check_for_overflow {
struct Incomplete;
struct S {
int member = (define_aggregate(^^Incomplete, {}), 1);
};
static_assert(!is_complete_type(^^Incomplete));
} // namespace check_for_overflow
// =======================
// out_of_scope_injections
// =======================
namespace out_of_scope_injections {
namespace {
[[maybe_unused]] void fn() {
struct I;
{
consteval { define_aggregate(^^I, {}); }
[[maybe_unused]] I i;
}
[[maybe_unused]] I i;
}
} // namespace
namespace {
struct I;
consteval void *fn1() {
static constexpr auto r = ^^I;
return (void *)&r;
}
consteval int fn2(void *ptr) {
define_aggregate(*(std::meta::info *)ptr, {});
return 12;
}
namespace a {
consteval { (void) fn2(fn1()); }
} // namespace
[[maybe_unused]] I i;
} // namespace
} // namespace out_of_scope_injections
// ========================================
// bb_clang_p2996_issue_145_regression_test
// ========================================
namespace bb_clang_p2996_issue_145_regression_test {
template<int>
struct int_template;
struct int_holder { int x; };
template<int_holder>
struct int_holder_template;
consteval {
std::meta::define_aggregate(^^int_template<0>, {});
std::meta::define_aggregate(^^int_holder_template<int_holder{0}>, {});
}
int_template<0> o1;
int_holder_template<int_holder{0}> o2;
} // namespace bb_clang_p2996_issue_145_regression_test
// ========================================
// bb_clang_p2996_issue_159_regression_test
// ========================================
namespace bb_clang_p2996_issue_159_regression_test {
template <auto V>
struct VS;
template <>
struct VS<^^float>{};
consteval {
std::meta::define_aggregate(^^VS<0>, {});
std::meta::define_aggregate(
std::meta::substitute(^^VS, {std::meta::reflect_constant(1)}), {});
std::meta::define_aggregate(
std::meta::substitute(^^VS, {std::meta::reflect_constant(^^int)}),
{});
}
VS<1> v1;
VS<^^int> v2;
} // namespace bb_clang_p2996_issue_159_regression_test
int main() { }