From 2a631b61e3ef7cd1d436e9714b0df0654a94c10b Mon Sep 17 00:00:00 2001 From: Dan Katz Date: Thu, 19 Jun 2025 19:17:03 +0300 Subject: [PATCH] Separate parameter/variable reflections. --- clang/include/clang/AST/APValue.h | 5 + clang/include/clang/AST/PropertiesBase.td | 7 + clang/include/clang/AST/RecursiveASTVisitor.h | 4 + clang/include/clang/AST/Reflection.h | 5 + clang/lib/AST/APValue.cpp | 18 ++ clang/lib/AST/ComputeDependence.cpp | 8 + clang/lib/AST/ExprConstantMeta.cpp | 211 ++++++++++-------- clang/lib/AST/ItaniumMangle.cpp | 23 +- clang/lib/AST/MicrosoftMangle.cpp | 1 + clang/lib/Sema/SemaReflect.cpp | 2 + clang/lib/Sema/TreeTransform.h | 8 + libcxx/include/experimental/meta | 24 +- .../reflection/p3096-fn-parameters.pass.cpp | 62 +++-- 13 files changed, 237 insertions(+), 141 deletions(-) diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index bc5b5b3ba7e1..2f0e967617fc 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -40,6 +40,7 @@ template 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; diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index c080e0d344ff..a5c6fba032ec 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -507,6 +507,10 @@ let Class = PropertyTypeCase 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 in { case ReflectionKind::EntityProxy: V = APValue(kind, *baseEntityProxy); break; + case ReflectionKind::Parameter: + V = APValue(kind, *baseParameter); + break; case ReflectionKind::BaseSpecifier: V = APValue( kind, diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 11ce039da524..0fcc4b1bd03f 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -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; diff --git a/clang/include/clang/AST/Reflection.h b/clang/include/clang/AST/Reflection.h index 7e80f5d17c07..d51d4044ab9e 100644 --- a/clang/include/clang/AST/Reflection.h +++ b/clang/include/clang/AST/Reflection.h @@ -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. diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 55c2ff9fc5bf..1bd8b48ecb4b 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -552,6 +552,13 @@ static void profileReflection(llvm::FoldingSetNodeID &ID, APValue V) { ID.AddPointer(TDecl); return; } + case ReflectionKind::Parameter: { + ParmVarDecl *PVD = dyn_cast(V.getReflectedParameter()); + if (auto *FD = dyn_cast(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(getOpaqueReflectionData())); } +ParmVarDecl *APValue::getReflectedParameter() const { + assert(getReflectionKind() == ReflectionKind::Parameter && + "not a reflection of a parameter"); + return reinterpret_cast( + const_cast(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: diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 3a49b0e7cd73..f5c09687d817 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -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(); diff --git a/clang/lib/AST/ExprConstantMeta.cpp b/clang/lib/AST/ExprConstantMeta.cpp index 3ea0450e5572..0808f3124833 100644 --- a/clang/lib/AST/ExprConstantMeta.cpp +++ b/clang/lib/AST/ExprConstantMeta.cpp @@ -625,13 +625,6 @@ static bool get_ith_parameter_of(APValue &Result, ASTContext &C, QualType ResultTy, SourceRange Range, ArrayRef 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 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 Args, Decl *ContainingDecl); +static bool variable_of(APValue &Result, ASTContext &C, MetaActions &Meta, + EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection, + QualType ResultTy, SourceRange Range, + ArrayRef 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(D)) return APValue(ReflectionKind::EntityProxy, D); + else if (isa(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(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(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(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(D)) { - std::string Name; - (void) getParameterName(PVD, Name); - - HasIdentifier = !Name.empty(); - break; - } else if (auto *FD = dyn_cast(D); + if (auto *FD = dyn_cast(D); FD && FD->getTemplateSpecializationArgs()) break; else if (isa(D)) break; + else if (auto *PVD = dyn_cast(D)) { + std::string Name; + (void) getParameterName(PVD, Name); + HasIdentifier = !Name.empty(); + } else if (auto *ND = dyn_cast(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(VD)) Meta.EnsureInstantiationOfExceptionSpec(Range.getBegin(), FD); - bool DropCV = isa(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(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(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(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 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(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(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(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(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 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(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) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 230705d22713..f35b00b7b68f 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4993,7 +4993,7 @@ void CXXNameMangler::mangleReflection(const APValue &R) { Out << 'd'; Decl *D = R.getReflectedDecl(); - if (auto * ED = dyn_cast(D)) { + if (auto *ED = dyn_cast(D)) { mangleIntegerLiteral(ED->getType(), ED->getInitVal()); } else if (auto *CD = dyn_cast(D)) { GlobalDecl GD(CD, Ctor_Complete); @@ -5001,20 +5001,23 @@ void CXXNameMangler::mangleReflection(const APValue &R) { } else if (auto *DD = dyn_cast(D)) { GlobalDecl GD(DD, Dtor_Complete); mangle(GD); - } else if (auto *PVD = dyn_cast(D)) { - if (const FunctionDecl *Func - = dyn_cast(PVD->getDeclContext())) { - Out << 'p'; - unsigned Num = Func->getNumParams() - PVD->getFunctionScopeIndex(); - if (Num > 1) - mangleNumber(Num - 2); - Out << '_'; - } } else { mangle(cast(D)); } break; } + case ReflectionKind::Parameter: { + auto *PVD = R.getReflectedParameter(); + if (const FunctionDecl *Func + = dyn_cast(PVD->getDeclContext())) { + Out << 'p'; + unsigned Num = Func->getNumParams() - PVD->getFunctionScopeIndex(); + if (Num > 1) + mangleNumber(Num - 2); + Out << '_'; + } + break; + } case ReflectionKind::Template: { Out << 't'; diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 3cc3351f7c0e..d08d5482b1a6 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -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: diff --git a/clang/lib/Sema/SemaReflect.cpp b/clang/lib/Sema/SemaReflect.cpp index 482a4d8671bc..7f0a31c14fb0 100644 --- a/clang/lib/Sema/SemaReflect.cpp +++ b/clang/lib/Sema/SemaReflect.cpp @@ -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) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index aefe7a15d25d..fbe8379cc4b0 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -9071,6 +9071,14 @@ TreeTransform::TransformCXXReflectExpr(CXXReflectExpr *E) { E->getOperandRange().getBegin(), cast(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(), diff --git a/libcxx/include/experimental/meta b/libcxx/include/experimental/meta index 6bb25cfd39cd..4ec4393c9e35 100644 --- a/libcxx/include/experimental/meta +++ b/libcxx/include/experimental/meta @@ -340,14 +340,12 @@ consteval auto is_entity_proxy(info) -> bool; // function parameters (P3096) consteval auto parameters_of(info) -> vector; -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; @@ -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 { return vector{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) diff --git a/libcxx/test/std/experimental/reflection/p3096-fn-parameters.pass.cpp b/libcxx/test/std/experimental/reflection/p3096-fn-parameters.pass.cpp index 909382477475..34ce2ae294cb 100644 --- a/libcxx/test/std/experimental/reflection/p3096-fn-parameters.pass.cpp +++ b/libcxx/test/std/experimental/reflection/p3096-fn-parameters.pass.cpp @@ -53,17 +53,17 @@ static_assert(parameters_of(type_of(^^fn)) == std::vector {^^int, ^^bool, ^^const S &}); 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 &); 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() { }