Separate parameter/variable reflections.

This commit is contained in:
Dan Katz
2025-06-19 19:17:03 +03:00
parent bebe293731
commit 2a631b61e3
13 changed files with 237 additions and 141 deletions

View File

@@ -40,6 +40,7 @@ template <typename T> class BasicReaderBase;
class Expr;
class FieldDecl;
class NamespaceDecl;
class ParmVarDecl;
struct PrintingPolicy;
class Type;
class UsingShadowDecl;
@@ -564,6 +565,9 @@ public:
bool isReflectedEntityProxy() const {
return isReflection() && getReflectionKind() == ReflectionKind::EntityProxy;
}
bool isReflectedParameter() const {
return isReflection() && getReflectionKind() == ReflectionKind::Parameter;
}
bool isReflectedBaseSpecifier() const {
return isReflection() &&
getReflectionKind() == ReflectionKind::BaseSpecifier;
@@ -763,6 +767,7 @@ public:
const TemplateName getReflectedTemplate() const;
Decl *getReflectedNamespace() const;
UsingShadowDecl *getReflectedEntityProxy() const;
ParmVarDecl *getReflectedParameter() const;
CXXBaseSpecifier *getReflectedBaseSpecifier() const;
TagDataMemberSpec *getReflectedDataMemberSpec() const;
CXX26AnnotationAttr *getReflectedAnnotation() const;

View File

@@ -507,6 +507,10 @@ let Class = PropertyTypeCase<APValue, "Reflection"> in {
let Conditional = [{ kind == ReflectionKind::EntityProxy }];
let Read = [{ base.getReflectedEntityProxy() }];
}
def : Property<"baseParameter", DeclRef> {
let Conditional = [{ kind == ReflectionKind::Parameter }];
let Read = [{ base.getReflectedParameter() }];
}
def : Property<"baseBaseSpecDerivedFrom", CXXRecordDeclRef> {
let Conditional = [{ kind == ReflectionKind::BaseSpecifier }];
let Read = [{ base.getReflectedBaseSpecifier()->getDerived() }];
@@ -574,6 +578,9 @@ let Class = PropertyTypeCase<APValue, "Reflection"> in {
case ReflectionKind::EntityProxy:
V = APValue(kind, *baseEntityProxy);
break;
case ReflectionKind::Parameter:
V = APValue(kind, *baseParameter);
break;
case ReflectionKind::BaseSpecifier:
V = APValue(
kind,

View File

@@ -3054,6 +3054,10 @@ DEF_TRAVERSE_STMT(CXXReflectExpr, {
TRY_TO(TraverseDecl(RV.getReflectedEntityProxy()));
break;
}
case ReflectionKind::Parameter: {
TRY_TO(TraverseDecl(RV.getReflectedParameter()));
break;
}
case ReflectionKind::Annotation: {
TRY_TO(TraverseStmt(RV.getReflectedAnnotation()->getArg()));
break;

View File

@@ -87,6 +87,11 @@ enum class ReflectionKind {
/// Corresponds to a UsingShadowDecl.
EntityProxy,
/// \brief A reflection of a function parameter.
///
/// Corresponds to a ParmVarDecl.
Parameter,
/// \brief A reflection of a base class specifier.
///
/// Corresponds to a CXXBaseSpecifier.

View File

@@ -552,6 +552,13 @@ static void profileReflection(llvm::FoldingSetNodeID &ID, APValue V) {
ID.AddPointer(TDecl);
return;
}
case ReflectionKind::Parameter: {
ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(V.getReflectedParameter());
if (auto *FD = dyn_cast<FunctionDecl>(PVD->getDeclContext()))
PVD = FD->getFirstDecl()->getParamDecl(PVD->getFunctionScopeIndex());
ID.AddPointer(PVD);
return;
}
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::BaseSpecifier:
@@ -936,6 +943,13 @@ UsingShadowDecl *APValue::getReflectedEntityProxy() const {
const_cast<void *>(getOpaqueReflectionData()));
}
ParmVarDecl *APValue::getReflectedParameter() const {
assert(getReflectionKind() == ReflectionKind::Parameter &&
"not a reflection of a parameter");
return reinterpret_cast<ParmVarDecl *>(
const_cast<void *>(getOpaqueReflectionData()));
}
CXXBaseSpecifier *APValue::getReflectedBaseSpecifier() const {
assert(getReflectionKind() == ReflectionKind::BaseSpecifier &&
"not a reflection of a base specifier");
@@ -1304,6 +1318,9 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy,
case ReflectionKind::EntityProxy:
Repr = "entity-proxy";
break;
case ReflectionKind::Parameter:
Repr = "parameter";
break;
case ReflectionKind::BaseSpecifier:
Repr = "base-specifier";
break;
@@ -1647,6 +1664,7 @@ void APValue::setReflection(ReflectionKind RK, const void *Ptr) {
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:

View File

@@ -982,6 +982,14 @@ ExprDependence clang::computeDependence(CXXReflectExpr *E,
D |= ExprDependence::UnexpandedPack;
return D | computeDeclDependence(VD, Ctx);
}
case ReflectionKind::Parameter: {
ParmVarDecl *PD = RV.getReflectedParameter();
if (PD->getType()->isDependentType())
D |= ExprDependence::ValueInstantiation;
if (PD->getType()->containsUnexpandedParameterPack())
D |= ExprDependence::UnexpandedPack;
return D | computeDeclDependence(PD, Ctx);
}
case ReflectionKind::Template: {
const TemplateName Template = RV.getReflectedTemplate();

View File

@@ -625,13 +625,6 @@ static bool get_ith_parameter_of(APValue &Result, ASTContext &C,
QualType ResultTy, SourceRange Range,
ArrayRef<Expr *> Args, Decl *ContainingDecl);
static bool has_consistent_identifier(APValue &Result, ASTContext &C,
MetaActions &Meta, EvalFn Evaluator,
DiagFn Diagnoser, bool AllowInjection,
QualType ResultTy, SourceRange Range,
ArrayRef<Expr *> Args,
Decl *ContainingDecl);
static bool has_ellipsis_parameter(APValue &Result, ASTContext &C,
MetaActions &Meta, EvalFn Evaluator,
DiagFn Diagnoser, bool AllowInjection,
@@ -663,6 +656,11 @@ static bool return_type_of(APValue &Result, ASTContext &C, MetaActions &Meta,
SourceRange Range, ArrayRef<Expr *> Args,
Decl *ContainingDecl);
static bool variable_of(APValue &Result, ASTContext &C, MetaActions &Meta,
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
QualType ResultTy, SourceRange Range,
ArrayRef<Expr *> Args, Decl *ContainingDecl);
static bool get_ith_annotation_of(APValue &Result, ASTContext &C,
MetaActions &Meta, EvalFn Evaluator,
DiagFn Diagnoser, bool AllowInjection,
@@ -827,12 +825,12 @@ static constexpr Metafunction Metafunctions[] = {
// P3096 metafunction extensions
{ Metafunction::MFRK_metaInfo, 3, 3, get_ith_parameter_of },
{ Metafunction::MFRK_bool, 1, 1, has_consistent_identifier },
{ Metafunction::MFRK_bool, 1, 1, has_ellipsis_parameter },
{ Metafunction::MFRK_bool, 1, 1, has_default_argument },
{ Metafunction::MFRK_bool, 1, 1, is_explicit_object_parameter },
{ Metafunction::MFRK_bool, 1, 1, is_function_parameter },
{ Metafunction::MFRK_metaInfo, 1, 1, return_type_of },
{ Metafunction::MFRK_metaInfo, 1, 1, variable_of },
// P3394 annotation metafunction extensions
{ Metafunction::MFRK_metaInfo, 3, 3, get_ith_annotation_of },
@@ -897,6 +895,8 @@ static APValue makeReflection(Decl *D) {
return APValue(ReflectionKind::Template, D);
else if (isa<UsingShadowDecl>(D))
return APValue(ReflectionKind::EntityProxy, D);
else if (isa<ParmVarDecl>(D))
return APValue(ReflectionKind::Parameter, D);
return APValue(ReflectionKind::Declaration, D);
}
@@ -1654,6 +1654,9 @@ StringRef DescriptionOf(APValue RV, bool Granular = true) {
case ReflectionKind::BaseSpecifier: {
return "a base class specifier";
}
case ReflectionKind::Parameter: {
return "a parameter";
}
case ReflectionKind::DataMemberSpec: {
return "a description of a non-static data member";
}
@@ -1718,6 +1721,7 @@ bool get_begin_enumerator_decl_of(APValue &Result, ASTContext &C,
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation: {
return DiagnoseReflectionKind(Diagnoser, Range, "an enum type",
@@ -1759,6 +1763,7 @@ bool get_next_enumerator_decl_of(APValue &Result, ASTContext &C,
case ReflectionKind::Value:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation: {
@@ -1821,6 +1826,7 @@ bool get_ith_base_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Value:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
@@ -1882,6 +1888,7 @@ bool get_ith_template_argument_of(APValue &Result, ASTContext &C,
case ReflectionKind::Value:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
@@ -1970,6 +1977,7 @@ bool get_begin_member_decl_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Null:
case ReflectionKind::Declaration:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::Template:
case ReflectionKind::Object:
case ReflectionKind::Value:
@@ -2088,15 +2096,6 @@ bool identifier_of(APValue &Result, ASTContext &C, MetaActions &Meta,
break;
}
case ReflectionKind::Declaration: {
if (auto *PVD = dyn_cast<ParmVarDecl>(RV.getReflectedDecl())) {
bool ConsistentName = getParameterName(PVD, Name);
if (EnforceConsistent && !ConsistentName) {
return Diagnoser(Range.getBegin(), diag::metafn_inconsistent_name)
<< DescriptionOf(RV) << Range;
}
break;
}
if (auto *ND = dyn_cast<NamedDecl>(RV.getReflectedDecl())) {
if (!findTemplateOfDecl(ND).isNull())
return Diagnoser(Range.getBegin(), diag::metafn_name_is_not_identifier)
@@ -2124,6 +2123,14 @@ bool identifier_of(APValue &Result, ASTContext &C, MetaActions &Meta,
break;
}
case ReflectionKind::Parameter: {
bool ConsistentName = getParameterName(RV.getReflectedParameter(), Name);
if (EnforceConsistent && !ConsistentName) {
return Diagnoser(Range.getBegin(), diag::metafn_inconsistent_name)
<< DescriptionOf(RV) << Range;
}
break;
}
case ReflectionKind::Template: {
const TemplateDecl *TD = RV.getReflectedTemplate().getAsTemplateDecl();
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(TD)) {
@@ -2209,20 +2216,28 @@ bool has_identifier(APValue &Result, ASTContext &C, MetaActions &Meta,
break;
}
case ReflectionKind::Parameter: {
auto *PVD = RV.getReflectedParameter();
std::string Name;
bool Consistent = getParameterName(PVD, Name);
HasIdentifier = Consistent && !Name.empty();
break;
}
case ReflectionKind::Declaration: {
auto *D = RV.getReflectedDecl();
if (auto *PVD = dyn_cast<ParmVarDecl>(D)) {
std::string Name;
(void) getParameterName(PVD, Name);
HasIdentifier = !Name.empty();
break;
} else if (auto *FD = dyn_cast<FunctionDecl>(D);
if (auto *FD = dyn_cast<FunctionDecl>(D);
FD && FD->getTemplateSpecializationArgs())
break;
else if (isa<VarTemplateSpecializationDecl>(D))
break;
else if (auto *PVD = dyn_cast<ParmVarDecl>(D)) {
std::string Name;
(void) getParameterName(PVD, Name);
HasIdentifier = !Name.empty();
}
else if (auto *ND = dyn_cast<NamedDecl>(D))
HasIdentifier = (ND->getIdentifier() != nullptr);
@@ -2342,6 +2357,9 @@ bool source_location_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::EntityProxy:
return findDeclLoc(Result, C, Evaluator, ResultTy,
RV.getReflectedEntityProxy());
case ReflectionKind::Parameter:
return findDeclLoc(Result, C, Evaluator, ResultTy,
RV.getReflectedParameter());
case ReflectionKind::BaseSpecifier:
return findBaseSpecLoc(Result, C, Evaluator, ResultTy,
RV.getReflectedBaseSpecifier());
@@ -2391,9 +2409,15 @@ bool type_of(APValue &Result, ASTContext &C, MetaActions &Meta,
if (auto *FD = dyn_cast<FunctionDecl>(VD))
Meta.EnsureInstantiationOfExceptionSpec(Range.getBegin(), FD);
bool DropCV = isa<ParmVarDecl>(VD);
QualType QT = desugarType(VD->getType(),
/*UnwrapAliases=*/ true, DropCV,
/*UnwrapAliases=*/ true, /*DropCV=*/false,
/*DropRefs=*/false);
return SetAndSucceed(Result, makeReflection(QT));
}
case ReflectionKind::Parameter: {
ParmVarDecl *PVD = RV.getReflectedParameter();
QualType QT = desugarType(PVD->getType(),
/*UnwrapAliases=*/ true, /*DropCV=*/true,
/*DropRefs=*/false);
return SetAndSucceed(Result, makeReflection(QT));
}
@@ -2466,6 +2490,9 @@ bool parent_of(APValue &Result, ASTContext &C, MetaActions &Meta,
return DiagWrapper(parentOf(Result,
RV.getReflectedTemplate().getAsTemplateDecl()));
}
case ReflectionKind::Parameter: {
return DiagWrapper(parentOf(Result, RV.getReflectedParameter()));
}
case ReflectionKind::Namespace:
if (isa<TranslationUnitDecl>(RV.getReflectedNamespace())) {
if (Diagnoser)
@@ -2506,6 +2533,7 @@ bool underlying_entity_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Declaration:
case ReflectionKind::Template:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, RV);
@@ -2547,6 +2575,7 @@ bool proxied_entity_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Namespace:
case ReflectionKind::Template:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return DiagnoseReflectionKind(Diagnoser, Range, "an entity proxy");
@@ -2600,6 +2629,7 @@ bool object_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Type:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::Template:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
@@ -2720,6 +2750,7 @@ bool constant_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
return Diagnoser(Range.getBegin(), diag::metafn_cannot_query_property)
@@ -2762,6 +2793,7 @@ bool template_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
@@ -2786,6 +2818,7 @@ static bool CanActAsTemplateArg(const APValue &RV) {
}
case ReflectionKind::Namespace:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
case ReflectionKind::Null:
@@ -3230,6 +3263,7 @@ bool extract(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
return Diagnoser(Range.getBegin(), diag::metafn_cannot_extract)
@@ -3282,6 +3316,7 @@ bool is_ACCESS(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Object:
case ReflectionKind::Value:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Parameter:
case ReflectionKind::Annotation:
case ReflectionKind::Namespace:
return SetAndSucceed(Result, makeBool(C, false));
@@ -3345,6 +3380,7 @@ bool is_virtual(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, makeBool(C, IsVirtual));
@@ -3531,26 +3567,22 @@ bool is_const(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, makeBool(C, false));
case ReflectionKind::Type: {
bool result = isConstQualifiedType(RV.getReflectedType());
return SetAndSucceed(Result, makeBool(C, result));
}
case ReflectionKind::Declaration: {
bool result = false;
if (!isa<ParmVarDecl>(RV.getReflectedDecl()))
result = isConstQualifiedType(RV.getReflectedDecl()->getType());
bool result = isConstQualifiedType(RV.getReflectedDecl()->getType());
return SetAndSucceed(Result, makeBool(C, result));
}
case ReflectionKind::Object:
case ReflectionKind::Value: {
bool result = isConstQualifiedType(RV.getTypeOfReflectedResult(C));
return SetAndSucceed(Result, makeBool(C, result));
}
}
@@ -3573,6 +3605,7 @@ bool is_volatile(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
@@ -3583,10 +3616,7 @@ bool is_volatile(APValue &Result, ASTContext &C, MetaActions &Meta,
return SetAndSucceed(Result, makeBool(C, result));
}
case ReflectionKind::Declaration: {
bool result = false;
if (!isa<ParmVarDecl>(RV.getReflectedDecl()))
result = isVolatileQualifiedType(RV.getReflectedDecl()->getType());
bool result = isVolatileQualifiedType(RV.getReflectedDecl()->getType());
return SetAndSucceed(Result, makeBool(C, result));
}
case ReflectionKind::Object:
@@ -3955,6 +3985,7 @@ bool is_static_member(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Value:
case ReflectionKind::Namespace:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, makeBool(C, result));
@@ -4086,6 +4117,7 @@ bool is_alias(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Declaration:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Parameter:
case ReflectionKind::Annotation:
case ReflectionKind::EntityProxy:
return SetAndSucceed(Result, makeBool(C, false));
@@ -4163,6 +4195,7 @@ bool has_complete_definition(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
break;
@@ -4202,6 +4235,7 @@ bool is_enumerable_type(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
break;
@@ -4497,6 +4531,7 @@ bool has_template_arguments(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, makeBool(C, false));
@@ -4604,6 +4639,7 @@ bool is_constructor(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Namespace:
case ReflectionKind::Template:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, makeBool(C, false));
@@ -4753,6 +4789,7 @@ bool is_destructor(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, makeBool(C, false));
@@ -4785,6 +4822,7 @@ bool is_special_member_function(APValue &Result, ASTContext &C,
case ReflectionKind::Value:
case ReflectionKind::Namespace:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, makeBool(C, false));
@@ -5137,6 +5175,7 @@ bool offset_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return DiagnoseReflectionKind(Diagnoser, Range, "a non-static data member",
@@ -5210,6 +5249,7 @@ bool size_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::Annotation:
return Diagnoser(Range.getBegin(), diag::metafn_cannot_query_property)
<< 3 << DescriptionOf(RV);
@@ -5235,6 +5275,7 @@ bool bit_offset_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return DiagnoseReflectionKind(Diagnoser, Range, "a non-static data member",
@@ -5306,6 +5347,7 @@ bool bit_size_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::Annotation:
return Diagnoser(Range.getBegin(), diag::metafn_cannot_query_property)
<< 3 << DescriptionOf(RV);
@@ -5370,6 +5412,7 @@ bool alignment_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::Annotation:
return Diagnoser(Range.getBegin(), diag::metafn_cannot_query_property)
<< 4 << DescriptionOf(RV) << Range;
@@ -5429,6 +5472,7 @@ bool get_ith_parameter_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return true;
@@ -5437,43 +5481,6 @@ bool get_ith_parameter_of(APValue &Result, ASTContext &C, MetaActions &Meta,
<< 5 << DescriptionOf(RV) << Range;
}
bool has_consistent_identifier(APValue &Result, ASTContext &C,
MetaActions &Meta, EvalFn Evaluator,
DiagFn Diagnoser, bool AllowInjection,
QualType ResultTy, SourceRange Range,
ArrayRef<Expr *> Args, Decl *ContainingDecl) {
assert(Args[0]->getType()->isReflectionType());
assert(ResultTy == C.BoolTy);
APValue RV;
if (!Evaluator(RV, Args[0], true))
return true;
switch (RV.getReflectionKind()) {
case ReflectionKind::Declaration:
if (auto *PVD = dyn_cast<ParmVarDecl>(RV.getReflectedDecl())) {
[[maybe_unused]] std::string Unused;
bool Consistent = getParameterName(PVD, Unused);
return SetAndSucceed(Result, makeBool(C, Consistent));
}
[[fallthrough]];
case ReflectionKind::Null:
case ReflectionKind::Type:
case ReflectionKind::Object:
case ReflectionKind::Value:
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
case ReflectionKind::EntityProxy:
return has_identifier(Result, C, Meta, Evaluator, Diagnoser, AllowInjection,
ResultTy, Range, Args, ContainingDecl);
}
llvm_unreachable("unknown reflection kind");
}
bool has_ellipsis_parameter(APValue &Result, ASTContext &C, MetaActions &Meta,
EvalFn Evaluator, DiagFn Diagnoser,
bool AllowInjection, QualType ResultTy,
@@ -5494,6 +5501,7 @@ bool has_ellipsis_parameter(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return Diagnoser(Range.getBegin(), diag::metafn_cannot_query_property)
@@ -5530,12 +5538,11 @@ bool has_default_argument(APValue &Result, ASTContext &C, MetaActions &Meta,
return true;
switch (RV.getReflectionKind()) {
case ReflectionKind::Declaration: {
if (auto *PVD = dyn_cast<ParmVarDecl>(RV.getReflectedDecl())) {
PVD = getMostRecentParmVarDecl(PVD);
return SetAndSucceed(Result, makeBool(C, PVD->hasDefaultArg()));
}
[[fallthrough]];
case ReflectionKind::Parameter: {
ParmVarDecl *PVD = getMostRecentParmVarDecl(RV.getReflectedParameter());
return SetAndSucceed(Result, makeBool(C, PVD->hasDefaultArg()));
}
case ReflectionKind::Declaration:
case ReflectionKind::Null:
case ReflectionKind::Type:
case ReflectionKind::Object:
@@ -5549,7 +5556,6 @@ bool has_default_argument(APValue &Result, ASTContext &C, MetaActions &Meta,
return DiagnoseReflectionKind(Diagnoser, Range, "a function parameter",
DescriptionOf(RV));
}
}
llvm_unreachable("unknown reflection kind");
}
@@ -5566,10 +5572,8 @@ bool is_explicit_object_parameter(APValue &Result, ASTContext &C,
return true;
bool result = false;
if (RV.isReflectedDecl()) {
if (auto *PVD = dyn_cast<ParmVarDecl>(RV.getReflectedDecl()))
result = PVD->isExplicitObjectParameter();
}
if (RV.isReflectedParameter())
result = RV.getReflectedParameter()->isExplicitObjectParameter();
return SetAndSucceed(Result, makeBool(C, result));
}
@@ -5585,11 +5589,7 @@ bool is_function_parameter(APValue &Result, ASTContext &C, MetaActions &Meta,
if (!Evaluator(RV, Args[0], true))
return true;
bool result = false;
if (RV.isReflectedDecl()) {
result = isa<const ParmVarDecl>(RV.getReflectedDecl());
}
return SetAndSucceed(Result, makeBool(C, result));
return SetAndSucceed(Result, makeBool(C, RV.isReflectedParameter()));
}
bool return_type_of(APValue &Result, ASTContext &C, MetaActions &Meta,
@@ -5631,6 +5631,7 @@ bool return_type_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return Diagnoser(Range.getBegin(), diag::metafn_cannot_query_property)
@@ -5639,6 +5640,33 @@ bool return_type_of(APValue &Result, ASTContext &C, MetaActions &Meta,
llvm_unreachable("unknown reflection kind");
}
bool variable_of(APValue &Result, ASTContext &C, MetaActions &Meta,
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
Decl *ContainingDecl) {
assert(Args[0]->getType()->isReflectionType());
assert(ResultTy == C.MetaInfoTy);
APValue RV;
if (!Evaluator(RV, Args[0], true))
return true;
if (!RV.isReflectedParameter())
return DiagnoseReflectionKind(Diagnoser, Range, "a function parameter",
DescriptionOf(RV));
ParmVarDecl *PVD = RV.getReflectedParameter();
FunctionDecl *FD = cast<FunctionDecl>(PVD->getDeclContext());
if (Meta.CurrentCtx()->getCanonicalDecl() != FD->getCanonicalDecl())
return true;
assert(FD->getDefinition());
PVD = FD->getDefinition()->getParamDecl(PVD->getFunctionScopeIndex());
APValue Var(ReflectionKind::Declaration, PVD);
return SetAndSucceed(Result, Var);
}
bool get_ith_annotation_of(APValue &Result, ASTContext &C, MetaActions &Meta,
EvalFn Evaluator, DiagFn Diagnoser,
bool AllowInjection, QualType ResultTy,
@@ -5709,6 +5737,7 @@ bool get_ith_annotation_of(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Object:
case ReflectionKind::Value:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return Diagnoser(Range.getBegin(), diag::metafn_cannot_query_property)
@@ -5781,6 +5810,7 @@ bool annotate(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Value:
case ReflectionKind::Template:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
case ReflectionKind::EntityProxy:
@@ -5956,6 +5986,7 @@ bool is_accessible(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Object:
case ReflectionKind::Value:
case ReflectionKind::Namespace:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, makeBool(C, true));
@@ -6019,6 +6050,7 @@ bool is_access_specified(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Object:
case ReflectionKind::Value:
case ReflectionKind::Namespace:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return SetAndSucceed(Result, makeBool(C, false));
@@ -6195,6 +6227,7 @@ bool reflect_invoke(APValue &Result, ASTContext &C, MetaActions &Meta,
case ReflectionKind::Type:
case ReflectionKind::Namespace:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
return Diagnoser(Range.getBegin(), diag::metafn_cannot_invoke)

View File

@@ -4993,7 +4993,7 @@ void CXXNameMangler::mangleReflection(const APValue &R) {
Out << 'd';
Decl *D = R.getReflectedDecl();
if (auto * ED = dyn_cast<EnumConstantDecl>(D)) {
if (auto *ED = dyn_cast<EnumConstantDecl>(D)) {
mangleIntegerLiteral(ED->getType(), ED->getInitVal());
} else if (auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
GlobalDecl GD(CD, Ctor_Complete);
@@ -5001,20 +5001,23 @@ void CXXNameMangler::mangleReflection(const APValue &R) {
} else if (auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
GlobalDecl GD(DD, Dtor_Complete);
mangle(GD);
} else if (auto *PVD = dyn_cast<ParmVarDecl>(D)) {
if (const FunctionDecl *Func
= dyn_cast<FunctionDecl>(PVD->getDeclContext())) {
Out << 'p';
unsigned Num = Func->getNumParams() - PVD->getFunctionScopeIndex();
if (Num > 1)
mangleNumber(Num - 2);
Out << '_';
}
} else {
mangle(cast<NamedDecl>(D));
}
break;
}
case ReflectionKind::Parameter: {
auto *PVD = R.getReflectedParameter();
if (const FunctionDecl *Func
= dyn_cast<FunctionDecl>(PVD->getDeclContext())) {
Out << 'p';
unsigned Num = Func->getNumParams() - PVD->getFunctionScopeIndex();
if (Num > 1)
mangleNumber(Num - 2);
Out << '_';
}
break;
}
case ReflectionKind::Template: {
Out << 't';

View File

@@ -2207,6 +2207,7 @@ void MicrosoftCXXNameMangler::mangleReflection(const APValue &R) {
case ReflectionKind::Template:
case ReflectionKind::Namespace:
case ReflectionKind::EntityProxy:
case ReflectionKind::Parameter:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:

View File

@@ -1699,6 +1699,7 @@ ExprResult Sema::BuildReflectionSpliceExpr(SourceLocation TemplateKWLoc,
case ReflectionKind::Type:
case ReflectionKind::Namespace:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
Diag(Splice->getBeginLoc(),
@@ -1834,6 +1835,7 @@ DeclContext *Sema::TryFindDeclContextOf(SpliceSpecifier *Splice) {
case ReflectionKind::Value:
case ReflectionKind::Declaration:
case ReflectionKind::BaseSpecifier:
case ReflectionKind::Parameter:
case ReflectionKind::DataMemberSpec:
case ReflectionKind::Annotation:
Diag(Splice->getBeginLoc(), diag::err_expected_class_or_namespace)

View File

@@ -9071,6 +9071,14 @@ TreeTransform<Derived>::TransformCXXReflectExpr(CXXReflectExpr *E) {
E->getOperandRange().getBegin(),
cast<UsingShadowDecl>(Transformed)));
}
case ReflectionKind::Parameter: {
Decl *Transformed = getDerived().TransformDecl(E->getExprLoc(),
RV.getReflectedParameter());
return RecordConstevalOnly.RecordAndReturn(
getSema().BuildCXXReflectExpr(E->getOperatorLoc(),
E->getOperandRange().getBegin(),
Transformed));
}
case ReflectionKind::Namespace: {
Decl *Transformed =
getDerived().TransformDecl(E->getExprLoc(),

View File

@@ -340,14 +340,12 @@ consteval auto is_entity_proxy(info) -> bool;
// function parameters (P3096)
consteval auto parameters_of(info) -> vector<info>;
consteval auto has_consistent_identifier(info) -> bool;
consteval auto any_identifier_of(info) -> string_view;
consteval auto u8any_identifier_of(info) -> u8string_view;
consteval auto has_ellipsis_parameter(info) -> bool;
consteval auto has_default_argument(info) -> bool;
consteval auto is_explicit_object_parameter(info) -> bool;
consteval auto is_function_parameter(info) -> bool;
consteval auto return_type_of(info) -> info;
consteval auto variable_of(info) -> info;
// annotations (P3394)
consteval auto annotations_of(info) -> vector<info>;
@@ -528,12 +526,12 @@ enum : unsigned {
// P3096 parameter reflection metafunctions
__metafn_get_ith_parameter_of,
__metafn_has_consistent_identifier,
__metafn_has_ellipsis_parameter,
__metafn_has_default_argument,
__metafn_is_explicit_object_parameter,
__metafn_is_function_parameter,
__metafn_return_type_of,
__metafn_variable_of,
// P3394 annotation metafunctions
__metafn_get_ith_annotation_of,
@@ -2082,20 +2080,6 @@ consteval auto parameters_of(info r) -> vector<info> {
return vector<info>{rng.begin(), rng.end()};
}
consteval auto has_consistent_identifier(info r) -> bool {
return __metafunction(detail::__metafn_has_consistent_identifier, r);
}
consteval auto any_identifier_of(info r) -> string_view {
return __metafunction(detail::__metafn_identifier_of, ^^const char *, r,
/*UTF8=*/false, /*EnforceConsistent=*/false);
}
consteval auto u8any_identifier_of(info r) -> u8string_view {
return __metafunction(detail::__metafn_identifier_of, ^^const char8_t *,
r, /*UTF8=*/true, /*EnforceConsistent=*/false);
}
consteval auto has_ellipsis_parameter(info r) -> bool {
return __metafunction(detail::__metafn_has_ellipsis_parameter, r);
}
@@ -2116,6 +2100,10 @@ consteval auto return_type_of(info r) -> info {
return __metafunction(detail::__metafn_return_type_of, r);
}
consteval auto variable_of(info r) -> info {
return __metafunction(detail::__metafn_variable_of, r);
}
#endif // __has_feature(parameter_reflection)
#if __has_feature(annotation_attributes)

View File

@@ -53,17 +53,17 @@ static_assert(parameters_of(type_of(^^fn)) ==
std::vector {^^int, ^^bool, ^^const S<int> &});
static_assert(type_of(parameters_of(^^fn)[0]) == ^^int);
static_assert(identifier_of(parameters_of(^^fn)[0]) == "a");
static_assert(has_consistent_identifier(parameters_of(^^fn)[0]));
static_assert(has_identifier(parameters_of(^^fn)[0]));
static_assert(!has_default_argument(parameters_of(^^fn)[0]));
static_assert(!is_explicit_object_parameter(parameters_of(^^fn)[0]));
static_assert(type_of(parameters_of(^^fn)[1]) == ^^bool);
static_assert(identifier_of(parameters_of(^^fn)[1]) == "b");
static_assert(has_consistent_identifier(parameters_of(^^fn)[1]));
static_assert(has_identifier(parameters_of(^^fn)[1]));
static_assert(!has_default_argument(parameters_of(^^fn)[1]));
static_assert(!is_explicit_object_parameter(parameters_of(^^fn)[1]));
static_assert(type_of(parameters_of(^^fn)[2]) == ^^const S<int> &);
static_assert(identifier_of(parameters_of(^^fn)[2]) == "s");
static_assert(has_consistent_identifier(parameters_of(^^fn)[2]));
static_assert(has_identifier(parameters_of(^^fn)[2]));
static_assert(!has_default_argument(parameters_of(^^fn)[2]));
static_assert(!is_explicit_object_parameter(parameters_of(^^fn)[2]));
static_assert(!has_ellipsis_parameter(^^fn));
@@ -91,7 +91,7 @@ constexpr auto ctor =
static_assert(parameters_of(ctor).size() == 1);
static_assert(type_of(parameters_of(ctor)[0]) == ^^int);
static_assert(identifier_of(parameters_of(ctor)[0]) == "a");
static_assert(has_consistent_identifier(parameters_of(ctor)[0]));
static_assert(has_identifier(parameters_of(ctor)[0]));
static_assert(!has_default_argument(parameters_of(ctor)[0]));
static_assert(!is_explicit_object_parameter(parameters_of(ctor)[0]));
static_assert(!has_ellipsis_parameter(ctor));
@@ -106,12 +106,12 @@ static_assert(parameters_of(^^Cls::fn).size() == 2);
static_assert(parameters_of(type_of(^^Cls::fn)) == std::vector {^^int, ^^bool});
static_assert(type_of(parameters_of(^^Cls::fn)[0]) == ^^int);
static_assert(identifier_of(parameters_of(^^Cls::fn)[0]) == "a");
static_assert(has_consistent_identifier(parameters_of(^^Cls::fn)[0]));
static_assert(has_identifier(parameters_of(^^Cls::fn)[0]));
static_assert(!has_default_argument(parameters_of(^^Cls::fn)[0]));
static_assert(!is_explicit_object_parameter(parameters_of(^^Cls::fn)[0]));
static_assert(type_of(parameters_of(^^Cls::fn)[1]) == ^^bool);
static_assert(identifier_of(parameters_of(^^Cls::fn)[1]) == "b");
static_assert(has_consistent_identifier(parameters_of(^^Cls::fn)[1]));
static_assert(has_identifier(parameters_of(^^Cls::fn)[1]));
static_assert(has_default_argument(parameters_of(^^Cls::fn)[1]));
static_assert(!is_explicit_object_parameter(parameters_of(^^Cls::fn)[1]));
static_assert(!has_ellipsis_parameter(^^Cls::fn));
@@ -123,12 +123,11 @@ static_assert(parameters_of(type_of(^^Cls::fn2)) ==
std::vector {^^Cls &, ^^int});
static_assert(type_of(parameters_of(^^Cls::fn2)[0]) == ^^Cls &);
static_assert(identifier_of(parameters_of(^^Cls::fn2)[0]) == "self");
static_assert(has_consistent_identifier(parameters_of(^^Cls::fn2)[0]));
static_assert(has_identifier(parameters_of(^^Cls::fn2)[0]));
static_assert(!has_default_argument(parameters_of(^^Cls::fn2)[0]));
static_assert(is_explicit_object_parameter(parameters_of(^^Cls::fn2)[0]));
static_assert(type_of(parameters_of(^^Cls::fn2)[1]) == ^^int);
static_assert(!has_identifier(parameters_of(^^Cls::fn2)[1]));
static_assert(has_consistent_identifier(parameters_of(^^Cls::fn2)[1]));
static_assert(!has_default_argument(parameters_of(^^Cls::fn2)[1]));
static_assert(has_ellipsis_parameter(^^Cls::fn2));
static_assert(has_ellipsis_parameter(type_of(^^Cls::fn2)));
@@ -139,7 +138,7 @@ static_assert(parameters_of(^^Cls::sfn).size() == 1);
static_assert(parameters_of(type_of(^^Cls::sfn)) == std::vector {^^int});
static_assert(type_of(parameters_of(^^Cls::sfn)[0]) == ^^int);
static_assert(identifier_of(parameters_of(^^Cls::sfn)[0]) == "a");
static_assert(has_consistent_identifier(parameters_of(^^Cls::sfn)[0]));
static_assert(has_identifier(parameters_of(^^Cls::sfn)[0]));
static_assert(!has_default_argument(parameters_of(^^Cls::sfn)[0]));
static_assert(!is_explicit_object_parameter(parameters_of(^^Cls::sfn)[0]));
static_assert(has_ellipsis_parameter(^^Cls::sfn));
@@ -163,17 +162,17 @@ consteval bool check() {
std::vector {^^int &&, ^^char &&, ^^bool &&});
static_assert(type_of(parameters_of(Fn)[0]) == ^^int &&);
static_assert(identifier_of(parameters_of(Fn)[0]) == "ts");
static_assert(has_consistent_identifier(parameters_of(Fn)[0]));
static_assert(has_identifier(parameters_of(Fn)[0]));
static_assert(!has_default_argument(parameters_of(Fn)[0]));
static_assert(!is_explicit_object_parameter(parameters_of(Fn)[0]));
static_assert(type_of(parameters_of(Fn)[1]) == ^^char &&);
static_assert(identifier_of(parameters_of(Fn)[1]) == "ts");
static_assert(has_consistent_identifier(parameters_of(Fn)[1]));
static_assert(has_identifier(parameters_of(Fn)[1]));
static_assert(!has_default_argument(parameters_of(Fn)[1]));
static_assert(!is_explicit_object_parameter(parameters_of(Fn)[1]));
static_assert(type_of(parameters_of(Fn)[2]) == ^^bool &&);
static_assert(identifier_of(parameters_of(Fn)[2]) == "ts");
static_assert(has_consistent_identifier(parameters_of(Fn)[2]));
static_assert(has_identifier(parameters_of(Fn)[2]));
static_assert(!has_default_argument(parameters_of(Fn)[2]));
static_assert(!is_explicit_object_parameter(parameters_of(Fn)[2]));
static_assert(!has_ellipsis_parameter(Fn));
@@ -199,12 +198,12 @@ static_assert(parameters_of(^^fn).size() == 2);
static_assert(parameters_of(type_of(^^fn)) == std::vector {^^int, ^^bool});
static_assert(type_of(parameters_of(^^fn)[0]) == ^^int);
static_assert(identifier_of(parameters_of(^^fn)[0]) == "a");
static_assert(has_consistent_identifier(parameters_of(^^fn)[0]));
static_assert(has_identifier(parameters_of(^^fn)[0]));
static_assert(!has_default_argument(parameters_of(^^fn)[0]));
static_assert(!is_explicit_object_parameter(parameters_of(^^fn)[0]));
static_assert(type_of(parameters_of(^^fn)[1]) == ^^bool);
static_assert(identifier_of(parameters_of(^^fn)[1]) == "b");
static_assert(has_consistent_identifier(parameters_of(^^fn)[1]));
static_assert(has_identifier(parameters_of(^^fn)[1]));
static_assert(has_default_argument(parameters_of(^^fn)[1]));
static_assert(!is_explicit_object_parameter(parameters_of(^^fn)[1]));
static_assert(!has_ellipsis_parameter(^^fn));
@@ -217,7 +216,7 @@ static_assert(!has_ellipsis_parameter(type_of(^^fn)));
namespace with_ambiguous_names {
void fn(int a1, bool b, char c1);
static_assert(has_consistent_identifier(parameters_of(^^fn)[2]));
static_assert(has_identifier(parameters_of(^^fn)[2]));
void fn(int a2, bool, char c2);
constexpr auto r_a2 = parameters_of(^^fn)[0];
@@ -230,16 +229,10 @@ constexpr auto r_a3 = parameters_of(^^fn)[0];
static_assert(parameters_of(^^fn).size() == 3);
static_assert(parameters_of(type_of(^^fn)) ==
std::vector {^^int, ^^bool, ^^char});
static_assert(any_identifier_of(parameters_of(^^fn)[0]) == "a1" ||
any_identifier_of(parameters_of(^^fn)[0]) == "a2" ||
any_identifier_of(parameters_of(^^fn)[0]) == "a3");
static_assert(!has_consistent_identifier(parameters_of(^^fn)[0]));
static_assert(any_identifier_of(parameters_of(^^fn)[1]) == "b");
static_assert(!has_identifier(parameters_of(^^fn)[0]));
static_assert(identifier_of(parameters_of(^^fn)[1]) == "b");
static_assert(has_consistent_identifier(parameters_of(^^fn)[1]));
static_assert(any_identifier_of(parameters_of(^^fn)[2]) == "c1" ||
any_identifier_of(parameters_of(^^fn)[2]) == "c2");
static_assert(!has_consistent_identifier(parameters_of(^^fn)[2]));
static_assert(has_identifier(parameters_of(^^fn)[1]));
static_assert(!has_identifier(parameters_of(^^fn)[2]));
static_assert(r_a2 == r_a3);
} // namespace with_ambiguous_names
@@ -289,4 +282,25 @@ void user(int) {
}
} // namespace mangle_reflection_of_function_parameter
// =================
// variable_of_tests
// =================
namespace variable_of_tests {
consteval int fn(int p) {
constexpr auto rp = parameters_of(^^fn)[0];
constexpr auto rv = variable_of(rp);
static_assert(is_function_parameter(rp));
static_assert(!is_function_parameter(rv));
static_assert(!is_variable(rp));
static_assert(is_variable(rv));
static_assert(^^p == rv);
return [:variable_of(parameters_of(^^fn)[0]):];
}
static_assert(fn(42) == 42);
} // namespace variable_of_tests
int main() { }