Skip to content

Commit 7200359

Browse files
committed
Fixes for dependent entity proxies.
Also fixes a crash in vanilla P2996 involving similar code.
1 parent d5d35ef commit 7200359

9 files changed

+95
-37
lines changed

clang/lib/Sema/SemaReflect.cpp

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -935,17 +935,9 @@ ExprResult Sema::ActOnCXXReflectExpr(SourceLocation OpLoc,
935935
VD && CheckReflectVar(*this, VD, Id.getSourceRange()))
936936
return ExprError();
937937

938-
// TODO(P2996): Try addressing this.
939-
//
940-
// Why do we have to build an expression here? Just stash in an APValue?
941938
if (isa<VarDecl, BindingDecl, FunctionDecl, FieldDecl, EnumConstantDecl,
942-
NonTypeTemplateParmDecl>(ND)) {
943-
ExprResult Result = BuildDeclarationNameExpr(SS, Found, false, false);
944-
if (Result.isInvalid())
945-
return ExprError();
946-
947-
return BuildCXXReflectExpr(OpLoc, Result.get());
948-
}
939+
NonTypeTemplateParmDecl, UnresolvedUsingValueDecl>(ND))
940+
return BuildCXXReflectExpr(OpLoc, NameInfo.getBeginLoc(), ND);
949941

950942
if (auto *TD = dyn_cast<TemplateDecl>(ND))
951943
return BuildCXXReflectExpr(OpLoc, NameInfo.getBeginLoc(),
@@ -1203,6 +1195,9 @@ Sema::ActOnSpliceTemplateArgument(SpliceSpecifier *Splice) {
12031195
case ReflectionKind::Annotation:
12041196
Diag(Splice->getBeginLoc(), diag::err_unsupported_splice_kind)
12051197
<< "annotations" << 0 << 0;
1198+
break;
1199+
case ReflectionKind::EntityProxy:
1200+
llvm_unreachable("proxies should already have been unwrapped");
12061201
}
12071202
return ParsedTemplateArgument();
12081203
}
@@ -1228,13 +1223,30 @@ Decl *Sema::ActOnConstevalBlockDeclaration(SourceLocation ConstevalLoc,
12281223

12291224
ExprResult Sema::BuildCXXReflectExpr(SourceLocation OperatorLoc,
12301225
SourceLocation OperandLoc, QualType T) {
1226+
if (auto *UT = dyn_cast<UsingType>(T)) {
1227+
if (Context.getLangOpts().EntityProxyReflection)
1228+
return BuildCXXReflectExpr(OperatorLoc, OperandLoc, UT->getFoundDecl());
1229+
else
1230+
T = UT->getUnderlyingType();
1231+
}
1232+
12311233
APValue RV(ReflectionKind::Type, T.getAsOpaquePtr());
12321234
return CXXReflectExpr::Create(Context, OperatorLoc, OperandLoc, RV);
12331235
}
12341236

12351237
// TODO(P2996): Capture whole SourceRange of declaration naming.
12361238
ExprResult Sema::BuildCXXReflectExpr(SourceLocation OperatorLoc,
12371239
SourceLocation OperandLoc, Decl *D) {
1240+
// This case can happen after transforming a dependent reflection naming a
1241+
// using-declarator.
1242+
if (auto *UD = dyn_cast<UsingDecl>(D)) {
1243+
if (UD->shadow_size() > 1) {
1244+
Diag(OperandLoc, diag::err_reflect_overload_set);
1245+
return ExprError();
1246+
}
1247+
D = *UD->shadow_begin();
1248+
}
1249+
12381250
D = D->getCanonicalDecl();
12391251

12401252
ReflectionKind RK = ReflectionKind::Declaration;
@@ -1244,6 +1256,8 @@ ExprResult Sema::BuildCXXReflectExpr(SourceLocation OperatorLoc,
12441256
RK = ReflectionKind::EntityProxy;
12451257

12461258
APValue RV(RK, D);
1259+
if (!getLangOpts().EntityProxyReflection)
1260+
RV = MaybeUnproxy(Context, RV);
12471261
return CXXReflectExpr::Create(Context, OperatorLoc,
12481262
SourceRange(OperandLoc, OperandLoc), RV);
12491263
}
@@ -1274,8 +1288,13 @@ ExprResult Sema::BuildCXXReflectExpr(SourceLocation OperatorLoc, Expr *E) {
12741288
}
12751289

12761290
// Check if this is a reference to a declared entity.
1277-
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
1278-
return BuildCXXReflectExpr(OperatorLoc, DRE->getExprLoc(), DRE->getDecl());
1291+
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
1292+
Decl *D = DRE->getDecl();
1293+
if (auto *F = DRE->getFoundDecl(); isa<UsingShadowDecl>(F))
1294+
D = F;
1295+
1296+
return BuildCXXReflectExpr(OperatorLoc, DRE->getExprLoc(), D);
1297+
}
12791298

12801299
// Special case for '^[:splice:]'.
12811300
if (auto *SE = dyn_cast<CXXSpliceExpr>(E))
@@ -1766,6 +1785,8 @@ ExprResult Sema::BuildReflectionSpliceExpr(SourceLocation TemplateKWLoc,
17661785
diag::err_unexpected_reflection_kind_in_splice)
17671786
<< 1 << Splice->getSourceRange();
17681787
return ExprError();
1788+
case ReflectionKind::EntityProxy:
1789+
llvm_unreachable("proxies should already have been unwrapped");
17691790
}
17701791
return Result;
17711792
}
@@ -1931,6 +1952,8 @@ DeclContext *Sema::TryFindDeclContextOf(SpliceSpecifier *Splice) {
19311952
Diag(Splice->getBeginLoc(), diag::err_expected_class_or_namespace)
19321953
<< "spliced entity" << getLangOpts().CPlusPlus;
19331954
return nullptr;
1955+
case ReflectionKind::EntityProxy:
1956+
llvm_unreachable("proxies should already have been unwrapped");
19341957
}
19351958
llvm_unreachable("unknown reflection kind");
19361959
}

clang/lib/Sema/TreeTransform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9089,7 +9089,7 @@ TreeTransform<Derived>::TransformCXXReflectExpr(CXXReflectExpr *E) {
90899089
return RecordConstevalOnly.RecordAndReturn(
90909090
getSema().BuildCXXReflectExpr(E->getOperatorLoc(),
90919091
E->getOperandRange().getBegin(),
9092-
cast<ValueDecl>(Transformed)));
9092+
Transformed));
90939093
}
90949094
case ReflectionKind::Template: {
90959095
TemplateName TName = RV.getReflectedTemplate();

libcxx/test/std/experimental/reflection/entity-proxies.pass.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,36 @@ static_assert(is_access_specified(^^G::n));
8585

8686
static_assert(dealias(^^H::n) == ^^F::n);
8787

88+
// =================
89+
// dependent_proxies
90+
// =================
91+
92+
namespace dependent_proxies {
93+
template <typename T>
94+
struct S : T {
95+
using T::fn;
96+
using typename T::Inner;
97+
98+
static constexpr auto r = ^^S::fn;
99+
static constexpr auto s = ^^fn;
100+
static constexpr auto t = ^^typename S::Inner;
101+
static constexpr auto u = ^^Inner;
102+
};
103+
104+
struct A { void fn(); struct Inner {}; };
105+
static_assert(is_entity_proxy(S<A>::r));
106+
static_assert(is_entity_proxy(S<A>::s));
107+
static_assert(parent_of(S<A>::r) == ^^S<A>);
108+
static_assert(S<A>::r == S<A>::s);
109+
static_assert(dealias(S<A>::r) == ^^A::fn);
110+
static_assert(&[:S<A>::r:] == &A::fn);
111+
112+
static_assert(is_entity_proxy(S<A>::t));
113+
static_assert(is_entity_proxy(S<A>::u));
114+
static_assert(parent_of(S<A>::t) == ^^S<A>);
115+
static_assert(S<A>::t == S<A>::u);
116+
static_assert(dealias(S<A>::t) == ^^A::Inner);
117+
118+
} // namespace dependent_proxies
119+
88120
int main() { }

libcxx/test/std/experimental/reflection/linkage-and-storage-class.pass.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static_assert(has_static_storage_duration(^^i1));
5959
static_assert(!has_thread_storage_duration(^^i1));
6060
static_assert(!has_automatic_storage_duration(^^i1));
6161

62-
static int i2;
62+
[[maybe_unused]] static int i2;
6363
static_assert(has_static_storage_duration(^^i2));
6464
static_assert(!has_thread_storage_duration(^^i2));
6565
static_assert(!has_automatic_storage_duration(^^i2));
@@ -69,12 +69,12 @@ static_assert(!has_static_storage_duration(^^i3));
6969
static_assert(has_thread_storage_duration(^^i3));
7070
static_assert(!has_automatic_storage_duration(^^i3));
7171

72-
static thread_local int i4;
72+
[[maybe_unused]] static thread_local int i4;
7373
static_assert(!has_static_storage_duration(^^i4));
7474
static_assert(has_thread_storage_duration(^^i4));
7575
static_assert(!has_automatic_storage_duration(^^i4));
7676

77-
void foo(float parameter_var) {
77+
void foo([[maybe_unused]] float parameter_var) {
7878
static_assert(!has_static_storage_duration(^^parameter_var));
7979
static_assert(!has_thread_storage_duration(^^parameter_var));
8080
static_assert(has_automatic_storage_duration(^^parameter_var));
@@ -84,13 +84,13 @@ void foo(float parameter_var) {
8484
static_assert(!has_thread_storage_duration(^^nonstatic_var));
8585
static_assert(has_automatic_storage_duration(^^nonstatic_var));
8686

87-
int& ref_to_nonstatic_var = nonstatic_var;
87+
[[maybe_unused]] int& ref_to_nonstatic_var = nonstatic_var;
8888
static_assert(!has_static_storage_duration(^^ref_to_nonstatic_var));
8989
static_assert(!has_thread_storage_duration(^^ref_to_nonstatic_var));
9090
static_assert(has_automatic_storage_duration(^^ref_to_nonstatic_var));
9191

9292
// assert the funcs check SD of the reference instead of the target object
93-
static int& static_ref_to_var = nonstatic_var;
93+
[[maybe_unused]] static int& static_ref_to_var = nonstatic_var;
9494
static_assert(has_static_storage_duration(^^static_ref_to_var));
9595
static_assert(!has_thread_storage_duration(^^static_ref_to_var));
9696
static_assert(!has_automatic_storage_duration(^^static_ref_to_var));
@@ -100,12 +100,12 @@ void foo(float parameter_var) {
100100
static_assert(!has_thread_storage_duration(^^static_var));
101101
static_assert(!has_automatic_storage_duration(^^static_var));
102102

103-
int& ref_to_static_var = static_var;
103+
[[maybe_unused]] int& ref_to_static_var = static_var;
104104
static_assert(!has_static_storage_duration(^^ref_to_static_var));
105105
static_assert(!has_thread_storage_duration(^^ref_to_static_var));
106106
static_assert(has_automatic_storage_duration(^^ref_to_static_var));
107107

108-
thread_local int tl_var;
108+
[[maybe_unused]] thread_local int tl_var;
109109
static_assert(!has_static_storage_duration(^^tl_var));
110110
static_assert(has_thread_storage_duration(^^tl_var));
111111
static_assert(!has_automatic_storage_duration(^^tl_var));
@@ -164,7 +164,7 @@ static_assert(!has_automatic_storage_duration(std::meta::reflect_value(4)));
164164

165165
namespace linkage {
166166
int global;
167-
static int s_global;
167+
[[maybe_unused]] static int s_global;
168168

169169
namespace { struct internal_linkage_type; }
170170
struct external_linkage_type;

libcxx/test/std/experimental/reflection/member-classification.pass.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,11 +426,13 @@ struct S {
426426
};
427427

428428
// non generic lambdas
429-
constexpr auto noexcept_lambda = []() noexcept {};
430-
constexpr auto not_noexcept_lambda = []{};
429+
[[maybe_unused]] constexpr auto noexcept_lambda = []() noexcept {};
430+
[[maybe_unused]] constexpr auto not_noexcept_lambda = []{};
431431

432432
// generic lambdas
433+
[[maybe_unused]]
433434
constexpr auto noexcept_generic_lambda = []<typename T>() noexcept {};
435+
[[maybe_unused]]
434436
constexpr auto not_noexcept_generic_lambda = []<typename T>() {};
435437

436438
// functions
@@ -890,7 +892,7 @@ struct S {
890892

891893
int v1;
892894

893-
const int v2 = 0;
895+
[[maybe_unused]] const int v2 = 0;
894896
const int arr1[] = {1, 2};
895897

896898
volatile int v3;

libcxx/test/std/experimental/reflection/names.pass.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ static_assert(display_string_of(^^Cls::Enum::B) == "B");
223223
static_assert(display_string_of(^^Cls::EnumCls) == "EnumCls");
224224
static_assert(display_string_of(^^Cls::EnumCls::B) == "B");
225225

226-
template <typename... Ts> consteval bool param_pack_has_ident(Ts...ts) {
226+
template <typename... Ts>
227+
consteval bool param_pack_has_ident([[maybe_unused]] Ts...ts) {
227228
return (has_identifier(^^ts) || ...);
228229
}
229230
static_assert(!param_pack_has_ident<int, bool, char>(3, false, 'c'));

libcxx/test/std/experimental/reflection/reflect-invoke.pass.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static_assert([:reflect_invoke(^^Cls::fn,
6464
{std::meta::reflect_value(4)}):] == 16);
6565

6666
// With reflection of constexpr variable as an argument.
67-
static constexpr int five = 5;
67+
[[maybe_unused]] static constexpr int five = 5;
6868

6969
static_assert([:reflect_invoke(^^fn1, {^^five}):] == 47);
7070

@@ -287,7 +287,7 @@ static_assert(std::meta::reflect_value(42) ==
287287
{^^num}));
288288

289289
// member function called with object reference
290-
constexpr auto num_ref = &num;
290+
[[maybe_unused]] constexpr auto num_ref = &num;
291291
static_assert(std::meta::reflect_value(42) ==
292292
reflect_invoke(^^Number::get_value,
293293
{^^num_ref}));
@@ -318,7 +318,7 @@ struct FloatNumber : public Number, IsReal{
318318
consteval FloatNumber(int v) : Number(v), IsReal(true) {}
319319
};
320320

321-
constexpr FloatNumber childNumber{42};
321+
[[maybe_unused]] constexpr FloatNumber childNumber{42};
322322
static_assert(std::meta::reflect_value(42) ==
323323
reflect_invoke(^^Number::get_value,
324324
{^^childNumber}));
@@ -374,7 +374,7 @@ static_assert(reflect_invoke(^^fn_pointer, {std::meta::reflect_value(2)})
374374
== std::meta::reflect_value(4));
375375

376376
// pointer to non-static method
377-
constexpr Cls data(42);
377+
[[maybe_unused]] constexpr Cls data(42);
378378
constexpr int (Cls::*get_pointer)() const = &Cls::get;
379379
static_assert(reflect_invoke(^^get_pointer, {^^data}) == std::meta::reflect_value(42));
380380

libcxx/test/std/experimental/reflection/source-location.pass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ static_assert(std::string_view(reflected_loc.file_name()) == loc.file_name());
2727
static_assert(reflected_loc.line() == loc.line());
2828
static_assert(reflected_loc.column() == 32);
2929

30-
void foo(int param) {
30+
void foo([[maybe_unused]] int param) {
3131
constexpr std::string_view FnName = __PRETTY_FUNCTION__;
3232

3333
static_assert(source_location_of(^^param).function_name() == FnName);
3434

35-
int var;
35+
[[maybe_unused]] int var;
3636
static_assert(source_location_of(^^var).function_name() == FnName);
3737

3838
struct S { std::source_location mem; };

libcxx/test/std/experimental/reflection/to-and-from-values.pass.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ static_assert(CheckValueIs<&fn>(^^fn));
136136
static_assert(CheckValueIs<&Cls::k>(^^Cls::k));
137137
static_assert(CheckValueIs<&Cls::fn>(^^Cls::fn));
138138
static_assert(CheckValueIs<42>([]() {
139-
constexpr int x = 42;
139+
[[maybe_unused]] constexpr int x = 42;
140140
return ^^x;
141141
}()));
142142

@@ -186,7 +186,7 @@ namespace extract_ref_semantics {
186186
// within an immediate function context. It isn't legal as spec'd by P2996R3,
187187
// but we may want to make it work. Not going to sink more time into making
188188
// the commented line below work, until we have a decision.
189-
consteval int myfn(int arg) {
189+
consteval int myfn([[maybe_unused]] int arg) {
190190
int val = 3;
191191
int &ref = extract<int &>(^^val);
192192

@@ -219,7 +219,7 @@ static_assert(type_of(^^a1) == ^^const int);
219219
static_assert(type_of(value_of(^^a1)) == ^^int);
220220

221221
using Alias2 = S;
222-
constexpr Alias2 a2 {};
222+
[[maybe_unused]] constexpr Alias2 a2 {};
223223
static_assert(type_of(^^a2) == ^^const S);
224224
static_assert(type_of(value_of(^^a2)) == ^^const S);
225225

@@ -232,7 +232,7 @@ static_assert(type_of(value_of(std::meta::reflect_object(p.first))) ==
232232

233233
constexpr int g = 3;
234234
consteval std::meta::info fn() {
235-
const int &r = g;
235+
[[maybe_unused]] const int &r = g;
236236
static_assert([:value_of(^^r):] == 3);
237237
return value_of(^^r);
238238
}
@@ -284,10 +284,10 @@ static_assert(value_of(^^constGlobal) == value_of(rref));
284284
static_assert(value_of(^^constGlobal) == std::meta::reflect_value(11));
285285

286286
enum Enum { A };
287-
static constexpr Enum e = A;
287+
[[maybe_unused]] static constexpr Enum e = A;
288288

289289
enum EnumCls { CA };
290-
static constexpr EnumCls ce = CA;
290+
[[maybe_unused]] static constexpr EnumCls ce = CA;
291291

292292
static_assert(value_of(^^A) != value_of(^^CA));
293293

0 commit comments

Comments
 (0)