llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-libcxx Author: Nhat Nguyen (changkhothuychung) <details> <summary>Changes</summary> This PR implements `std::meta::is_type(info)` by introducing a builtin `__builtin_meta_is_type`. It also includes two feature-test macros `__cpp_impl_reflection` and `__cpp_lib_reflection` introduced in [P2996 ](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2996r13.html). `__cpp_impl_reflection` is only enabled when `-freflection` is on, and `__cpp_lib_reflection` depends on `__cpp_impl_reflection`. Header `<meta>` is created in libc++. --- Patch is 98.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/211653.diff 79 Files Affected: - (modified) clang/include/clang/AST/APValue.h (+39-4) - (modified) clang/include/clang/AST/ASTContext.h (+1) - (modified) clang/include/clang/AST/BuiltinTypes.def (+3) - (modified) clang/include/clang/AST/ExprCXX.h (+16-5) - (modified) clang/include/clang/AST/PropertiesBase.td (+25) - (added) clang/include/clang/AST/Reflection.h (+39) - (modified) clang/include/clang/AST/TypeBase.h (+5) - (modified) clang/include/clang/Basic/Builtins.td (+6) - (modified) clang/include/clang/Basic/TargetInfo.h (+6) - (modified) clang/include/clang/Serialization/ASTBitCodes.h (+4-1) - (modified) clang/lib/AST/APValue.cpp (+79) - (modified) clang/lib/AST/ASTContext.cpp (+12) - (modified) clang/lib/AST/ASTImporter.cpp (+33-1) - (modified) clang/lib/AST/ByteCode/Compiler.cpp (+20) - (modified) clang/lib/AST/ByteCode/Compiler.h (+1) - (modified) clang/lib/AST/ByteCode/Context.cpp (+3) - (modified) clang/lib/AST/ByteCode/Descriptor.cpp (+1) - (modified) clang/lib/AST/ByteCode/Disasm.cpp (+2) - (modified) clang/lib/AST/ByteCode/Interp.cpp (+1-1) - (modified) clang/lib/AST/ByteCode/Interp.h (+7) - (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+10) - (modified) clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp (+1-1) - (modified) clang/lib/AST/ByteCode/InterpStack.h (+3) - (modified) clang/lib/AST/ByteCode/InterpState.cpp (+1) - (modified) clang/lib/AST/ByteCode/Opcodes.td (+8-1) - (modified) clang/lib/AST/ByteCode/PrimType.cpp (+1) - (modified) clang/lib/AST/ByteCode/PrimType.h (+6) - (modified) clang/lib/AST/ByteCode/Program.cpp (+1) - (modified) clang/lib/AST/ByteCode/Program.h (+1) - (added) clang/lib/AST/ByteCode/Reflect.h (+62) - (modified) clang/lib/AST/ExprCXX.cpp (+6-5) - (modified) clang/lib/AST/ExprConstant.cpp (+83-1) - (modified) clang/lib/AST/ItaniumMangle.cpp (+70-3) - (modified) clang/lib/AST/MicrosoftMangle.cpp (+5) - (modified) clang/lib/AST/NSAPI.cpp (+1) - (modified) clang/lib/AST/StmtPrinter.cpp (+9-2) - (modified) clang/lib/AST/TextNodeDumper.cpp (+16) - (modified) clang/lib/AST/Type.cpp (+10) - (modified) clang/lib/AST/TypeLoc.cpp (+1) - (modified) clang/lib/Basic/TargetInfo.cpp (+2) - (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+2) - (modified) clang/lib/CodeGen/CGExprConstant.cpp (+2) - (modified) clang/lib/CodeGen/CodeGenModule.cpp (+2) - (modified) clang/lib/CodeGen/CodeGenTypes.cpp (+7) - (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1) - (modified) clang/lib/CodeGen/QualTypeMapper.cpp (+3) - (modified) clang/lib/Frontend/InitPreprocessor.cpp (+4) - (modified) clang/lib/Sema/SemaExpr.cpp (+12-1) - (modified) clang/lib/Sema/SemaOverload.cpp (+18-5) - (modified) clang/lib/Sema/SemaTemplate.cpp (+16-1) - (modified) clang/lib/Sema/TreeTransform.h (+13-1) - (modified) clang/lib/Serialization/ASTCommon.cpp (+3) - (modified) clang/lib/Serialization/ASTReader.cpp (+3) - (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+13-2) - (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+13-2) - (modified) clang/lib/UnifiedSymbolResolution/USRGeneration.cpp (+3) - (added) clang/test/AST/ast-dump-APValue-reflection.cpp (+14) - (added) clang/test/CodeGenCXX/reflection-emit-meta-info-itanium.cpp (+7) - (renamed) clang/test/CodeGenCXX/reflection-emit-meta-info-ms.cpp () - (modified) clang/test/CodeGenCXX/reflection-mangle-itanium.cpp (+40-2) - (added) clang/test/PCH/reflection.cpp (+14) - (added) clang/test/PCH/reflection_include.h (+1) - (added) clang/test/Sema/reflection-meta-info.fail.cpp (+56) - (added) clang/test/Sema/reflection-meta-info.pass.cpp (+77) - (added) clang/test/SemaCXX/builtin-meta-is-type.cpp (+48) - (modified) clang/test/SemaCXX/consteval-builtin.cpp (+18) - (modified) clang/tools/libclang/CIndex.cpp (+1) - (modified) clang/unittests/AST/ASTImporterTest.cpp (+29) - (modified) clang/utils/TableGen/ClangBuiltinsEmitter.cpp (+1) - (modified) libcxx/docs/FeatureTestMacroTable.rst (+2) - (modified) libcxx/include/CMakeLists.txt (+1) - (added) libcxx/include/meta (+38) - (modified) libcxx/include/module.modulemap.in (+5) - (modified) libcxx/include/version (+4) - (added) libcxx/test/std/language.support/support.limits/support.limits.general/meta.version.compile.pass.cpp (+68) - (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+33) - (added) libcxx/test/std/meta/is_type.compile.pass.cpp (+51) - (modified) libcxx/utils/generate_feature_test_macro_components.py (+7) - (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+3) ``````````diff diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 9293266a41256..2f6efc670b6e8 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_APVALUE_H #define LLVM_CLANG_AST_APVALUE_H +#include "clang/AST/Reflection.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/APFixedPoint.h" #include "llvm/ADT/APFloat.h" @@ -141,7 +142,8 @@ class APValue { Struct, Union, MemberPointer, - AddrLabelDiff + AddrLabelDiff, + Reflection }; class alignas(uint64_t) LValueBase { @@ -315,12 +317,21 @@ class APValue { const AddrLabelExpr* LHSExpr; const AddrLabelExpr* RHSExpr; }; + struct ReflectionData { + // OperandKind will eventually have support for + // TypeSourceInfo, TemplateReference, NamespaceReference, DeclRefExpr. + // Operand stores the opaque pointer of the reflection operand. + // Depending on the value of OperandKind, we can perform the + // corresponding cast to the associated type. + ReflectionKind OperandKind; + const void *Operand; + }; struct MemberPointerData; // We ensure elsewhere that Data is big enough for LV and MemberPointerData. - typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, - ComplexAPFloat, Vec, Mat, Arr, StructData, - UnionData, AddrLabelDiffData> + typedef llvm::AlignedCharArrayUnion< + void *, APSInt, APFloat, ComplexAPSInt, ComplexAPFloat, Vec, Mat, Arr, + StructData, UnionData, AddrLabelDiffData, ReflectionData> DataType; static const size_t DataSize = sizeof(DataType); @@ -415,6 +426,14 @@ class APValue { : Kind(None), AllowConstexprUnknown(false) { MakeArray(InitElts, Size); } + + /// Creates a new Reflection APValue. + /// \param OperandKind The kind of reflection. + /// \param Operand The entity being reflected. + APValue(ReflectionKind OperandKind, const void *Operand) : Kind(None) { + MakeReflection(OperandKind, Operand); + } + /// Creates a new struct APValue. /// \param UninitStruct Marker. Pass an empty UninitStruct. /// \param NumBases Number of bases. @@ -498,6 +517,7 @@ class APValue { bool isUnion() const { return Kind == Union; } bool isMemberPointer() const { return Kind == MemberPointer; } bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } + bool isReflection() const { return Kind == Reflection; } void dump() const; void dump(raw_ostream &OS, const ASTContext &Context) const; @@ -717,6 +737,16 @@ class APValue { return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr; } + ReflectionKind getReflectionOperandKind() const { + assert(isReflection() && "Invalid accessor"); + return ((const ReflectionData *)(const char *)&Data)->OperandKind; + } + + const void *getReflectionOpaqueOperand() const { + assert(isReflection() && "Invalid accessor"); + return ((const ReflectionData *)(const char *)&Data)->Operand; + } + void setInt(APSInt I) { assert(isInt() && "Invalid accessor"); *(APSInt *)(char *)&Data = std::move(I); @@ -767,6 +797,11 @@ class APValue { private: void DestroyDataAndMakeUninit(); + void MakeReflection(ReflectionKind OperandKind, const void *Operand) { + assert(isAbsent() && "Bad state change"); + new ((void *)(char *)Data.buffer) ReflectionData{OperandKind, Operand}; + Kind = Reflection; + } void MakeInt() { assert(isAbsent() && "Bad state change"); new ((void *)&Data) APSInt(1); diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 7ed6509c3c16c..05dfec8c37586 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1351,6 +1351,7 @@ class ASTContext : public RefCountedBase<ASTContext> { CanQualType BFloat16Ty; CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 CanQualType VoidPtrTy, NullPtrTy; + CanQualType MetaInfoTy; CanQualType DependentTy, OverloadTy, BoundMemberTy, UnresolvedTemplateTy, UnknownAnyTy; CanQualType BuiltinFnTy; diff --git a/clang/include/clang/AST/BuiltinTypes.def b/clang/include/clang/AST/BuiltinTypes.def index 444be4311a743..ee2f3f0365126 100644 --- a/clang/include/clang/AST/BuiltinTypes.def +++ b/clang/include/clang/AST/BuiltinTypes.def @@ -223,6 +223,9 @@ FLOATING_TYPE(Ibm128, Ibm128Ty) //===- Language-specific types --------------------------------------------===// +// 'std::meta::info' in C++ +BUILTIN_TYPE(MetaInfo, MetaInfoTy) + // This is the type of C++0x 'nullptr'. BUILTIN_TYPE(NullPtr, NullPtrTy) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 757f2137c90dc..4ed388877a2ab 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -25,6 +25,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/OperationKinds.h" +#include "clang/AST/Reflection.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/TemplateBase.h" @@ -5502,37 +5503,47 @@ class BuiltinBitCastExpr final /// - a type-id, or /// - an id-expression. class CXXReflectExpr : public Expr { + friend class ASTStmtReader; + friend class ASTStmtWriter; +private: // TODO(Reflection): add support for TemplateReference, NamespaceReference and // DeclRefExpr - using operand_type = llvm::PointerUnion<const TypeSourceInfo *>; + using operand_type = llvm::PointerUnion<TypeSourceInfo *>; SourceLocation CaretCaretLoc; + ReflectionKind Kind; operand_type Operand; - CXXReflectExpr(SourceLocation CaretCaretLoc, const TypeSourceInfo *TSI); + CXXReflectExpr(ASTContext &C, SourceLocation CaretCaretLoc, + TypeSourceInfo *TSI); CXXReflectExpr(EmptyShell Empty); public: static CXXReflectExpr *Create(ASTContext &C, SourceLocation OperatorLoc, - TypeSourceInfo *TL); + TypeSourceInfo *TSI); static CXXReflectExpr *CreateEmpty(ASTContext &C); SourceLocation getBeginLoc() const LLVM_READONLY { return llvm::TypeSwitch<operand_type, SourceLocation>(Operand) - .Case<const TypeSourceInfo *>( + .Case<TypeSourceInfo *>( [](auto *Ptr) { return Ptr->getTypeLoc().getBeginLoc(); }); } SourceLocation getEndLoc() const LLVM_READONLY { return llvm::TypeSwitch<operand_type, SourceLocation>(Operand) - .Case<const TypeSourceInfo *>( + .Case<TypeSourceInfo *>( [](auto *Ptr) { return Ptr->getTypeLoc().getEndLoc(); }); } /// Returns location of the '^^'-operator. SourceLocation getOperatorLoc() const { return CaretCaretLoc; } + ReflectionKind getKind() const { return Kind; } + void *getOpaqueValue() const { return Operand.getOpaqueValue(); } + TypeSourceInfo *getTypeSourceInfo() const { + return cast<TypeSourceInfo *>(Operand); + } child_range children() { // TODO(Reflection) diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 25ef4c26a9aa1..9a5c683fbf693 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -603,6 +603,31 @@ let Class = PropertyTypeCase<APValue, "LValue"> in { }]>; } +def ReflectionKind : EnumPropertyType<"ReflectionKind">; + +let Class = PropertyTypeCase<APValue, "Reflection"> in { + def : Property<"reflectionKind", ReflectionKind> { + let Read = [{ node.getReflectionOperandKind() }]; + } + def : Property<"reflectionType", QualType> { + let Conditional = [{ reflectionKind == ReflectionKind::Type }]; + let Read = [{ + QualType::getFromOpaquePtr(node.getReflectionOpaqueOperand()) + }]; + } + def : Creator<[{ + switch (reflectionKind) { + // TODO(Reflection): Add support for TypeSourceInfo, NamespaceReference + // TemplateReference and DeclRefExpr + case ReflectionKind::Null: + return APValue(reflectionKind, nullptr); + case ReflectionKind::Type: + return APValue(reflectionKind, (*reflectionType).getAsOpaquePtr()); + } + llvm_unreachable("unimplemented or unknow reflection entities"); + }]>; +} + // Type cases for DeclarationName. def : PropertyTypeKind<DeclarationName, DeclarationNameKind, "node.getNameKind()">; diff --git a/clang/include/clang/AST/Reflection.h b/clang/include/clang/AST/Reflection.h new file mode 100644 index 0000000000000..732aefde80885 --- /dev/null +++ b/clang/include/clang/AST/Reflection.h @@ -0,0 +1,39 @@ +//===--- Reflection.h - Kind of reflection operands ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the kinds of reflection operands. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_REFLECTION_H +#define LLVM_CLANG_AST_REFLECTION_H + +#include "llvm/Support/raw_ostream.h" + +namespace clang { + +// TODO(Reflection): Add support for Template, Namespace and DeclRefExpr. +enum class ReflectionKind { Null, Type }; + +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + ReflectionKind Kind) { + switch (Kind) { + case ReflectionKind::Type: + OS << "type"; + break; + case ReflectionKind::Null: + OS << "null"; + break; + } + + return OS; +} + +} // namespace clang + +#endif diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index c9658775f0470..4886db6998b45 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -2766,6 +2766,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isUndeducedAutoType() const; // C++11 auto or // C++14 decltype(auto) bool isTypedefNameType() const; // typedef or alias template + bool isMetaInfoType() const; // C++26 std::meta::info #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ bool is##Id##Type() const; @@ -9051,6 +9052,10 @@ inline bool Type::isVoidType() const { return isSpecificBuiltinType(BuiltinType::Void); } +inline bool Type::isMetaInfoType() const { + return isSpecificBuiltinType(BuiltinType::MetaInfo); +} + inline bool Type::isHalfType() const { // FIXME: Should we allow complex __fp16? Probably not. return isSpecificBuiltinType(BuiltinType::Half); diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 344a712ddc585..244a791938093 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1207,6 +1207,12 @@ def IsWithinLifetime : LangBuiltin<"CXX_LANG"> { let Prototype = "bool(void*)"; } +def MetaIsType : LangBuiltin<"CXX_LANG"> { + let Spellings = ["__builtin_meta_is_type"]; + let Attributes = [NoThrow, Consteval]; + let Prototype = "bool(std::meta::info)"; +} + def ClearPadding : Builtin { let Spellings = ["__builtin_clear_padding"]; let Attributes = [NoThrow, CustomTypeChecking]; diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 3aba4d261a651..dacc1d3a5d9ea 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -96,6 +96,7 @@ struct TransferrableTargetInfo { unsigned char FloatWidth, FloatAlign; unsigned char DoubleWidth, DoubleAlign; unsigned char LongDoubleWidth, LongDoubleAlign, Float128Align, Ibm128Align; + unsigned char MetaInfoWidth, MetaInfoAlign; unsigned char LargeArrayMinWidth, LargeArrayAlign; unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; @@ -828,6 +829,11 @@ class TargetInfo : public TransferrableTargetInfo, unsigned getIbm128Align() const { return Ibm128Align; } const llvm::fltSemantics &getIbm128Format() const { return *Ibm128Format; } + /// Returns the size of std::meta::info. + unsigned getMetaInfoWidth() const { return MetaInfoWidth; } + /// eturns the align of std::meta::info. + unsigned getMetaInfoAlign() const { return MetaInfoAlign; } + /// Return the mangled code of long double. virtual const char *getLongDoubleMangling() const { return "e"; } diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 671341488278e..e36e6ea29810f 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1155,6 +1155,9 @@ enum PredefinedTypeIDs { #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID, #include "clang/Basic/HLSLIntangibleTypes.def" + /// C++26 std::meta::info type. + PREDEF_TYPE_META_INFO_ID, + /// The placeholder type for unresolved templates. PREDEF_TYPE_UNRESOLVED_TEMPLATE, // Sentinel value. Considered a predefined type but not useable as one. @@ -1166,7 +1169,7 @@ enum PredefinedTypeIDs { /// /// Type IDs for non-predefined types will start at /// NUM_PREDEF_TYPE_IDs. -const unsigned NUM_PREDEF_TYPE_IDS = 529; +const unsigned NUM_PREDEF_TYPE_IDS = 530; // Ensure we do not overrun the predefined types we reserved // in the enum PredefinedTypeIDs above. diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 727e5f8c00a10..1849562952fb7 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -374,6 +374,10 @@ APValue::APValue(const APValue &RHS) MakeAddrLabelDiff(); setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS()); break; + case Reflection: + MakeReflection(RHS.getReflectionOperandKind(), + RHS.getReflectionOpaqueOperand()); + break; } } @@ -429,6 +433,8 @@ void APValue::DestroyDataAndMakeUninit() { ((MemberPointerData *)(char *)&Data)->~MemberPointerData(); else if (Kind == AddrLabelDiff) ((AddrLabelDiffData *)(char *)&Data)->~AddrLabelDiffData(); + else if (Kind == Reflection) + ((ReflectionData *)(char *)&Data)->~ReflectionData(); Kind = None; AllowConstexprUnknown = false; } @@ -438,6 +444,7 @@ bool APValue::needsCleanup() const { case None: case Indeterminate: case AddrLabelDiff: + case Reflection: return false; case Struct: case Union: @@ -486,6 +493,61 @@ static void profileIntValue(llvm::FoldingSetNodeID &ID, const llvm::APInt &V) { ID.AddInteger((uint32_t)V.extractBitsAsZExtValue(std::min(32u, N - I), I)); } +/// [expr.reflect] p5, if a reflect-expression R matches the form +/// ^^reflection-name it is interpreted as such; the identifier is looked up +/// and the representation of R is determined as follows: +/// - if lookup finds a type alias A, R represents the type the underlying +/// entity of A if A was introduced by the declaration of a template +/// parameter; otherwise, R represents A. + +/// [expr.reflect] p6, Given reflect-expression R of the form ^^type-id, +/// if type-id is neither a placeholder type nor +/// in the form of nested-name-specifier_opt template_opt simple-template-id +/// then R represents the type denoted by the type-id + +// In particular, this means that e.g. '^^const Alias' is reflection of +// a type, not an alias. For example: +// +// using foo = const int; +// ^^int // Type +// ^^const int // Type +// ^^foo // Alias +// ^^const foo // Type +static bool isTypeAliasAsReflectionName(QualType QT) { + return QT.getLocalQualifiers() == Qualifiers{}; +} + +/// Unwrap reflected type for profiling +static void profileTypeReflection(llvm::FoldingSetNodeID &ID, QualType QT) { + // TODO(Reflection) + + if (isTypeAliasAsReflectionName(QT)) { + if (const auto *TDT = QT->getAs<TypedefType>()) { + ID.AddBoolean(true); + ID.AddPointer(TDT->getDecl()->getCanonicalDecl()); + return; + } + } + + ID.AddBoolean(false); + QT.getCanonicalType().Profile(ID); +} + +static void profileReflection(llvm::FoldingSetNodeID &ID, APValue V) { + ID.AddInteger(static_cast<int>(V.getReflectionOperandKind())); + switch (V.getReflectionOperandKind()) { + case ReflectionKind::Null: + return; + case ReflectionKind::Type: { + const TypeSourceInfo *Info = + static_cast<const TypeSourceInfo *>(V.getReflectionOpaqueOperand()); + profileTypeReflection(ID, Info->getType()); + return; + } + } + assert(false && "unknown or unimplemented reflection entities"); +} + void APValue::Profile(llvm::FoldingSetNodeID &ID) const { // Note that our profiling assumes that only APValues of the same type are // ever compared. As a result, we don't consider collisions that could only @@ -632,6 +694,9 @@ void APValue::Profile(llvm::FoldingSetNodeID &ID) const { for (const CXXRecordDecl *D : getMemberPointerPath()) ID.AddPointer(D); return; + case Reflection: + profileReflection(ID, *this); + return; } llvm_unreachable("Unknown APValue kind!"); @@ -986,6 +1051,19 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy, Out << " - "; Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName(); return; + case APValue::Reflection: + switch (getReflectionOperandKind()) { + case ReflectionKind::Null: + Out << "std::meta::info{}"; + break; + case ReflectionKind::Type: { + const auto *TInfo = + static_cast<const TypeSourceInfo *>(getReflectionOpaqueOperand()); + Out << "^^" << TInfo->getType().stream(Policy); + break; + } + } + return; } llvm_unreachable("Unknown APValue kind!"); } @@ -1176,6 +1254,7 @@ LinkageInfo LinkageComputer::getLVForValue(const APValue &V, case APValue::ComplexInt: case APValue::ComplexFloat: case APValue::Vector: + case APValue::Reflection: case APValue::Matrix: break; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2228811546c0f..eef973690a350 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1511,6 +1511,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, // nullptr type (C++0x 2.14.7) InitBuiltinType(NullPtrTy, BuiltinType::NullPtr); + // std::meta::info type (C++26 21.4.1) + InitBuiltinType(MetaInfoTy, BuiltinType::MetaInfo); + // half type (OpenCL 6.1.1.1) / ARM NEON __fp16 InitBuiltinType(HalfTy, BuiltinType::Half); @@ -2366,6 +2369,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getPointerWidth(LangAS::Default); Align = Target->getPointerAlign(LangAS::Default); break; + case BuiltinType::MetaInfo: + Width = Target->getMetaInfoWidth(); + Align = Target->getMetaInfoAlign(); + break; case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: @@ -3568,6 +3575,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, case BuiltinType::VectorPair: case BuiltinType::DMR1024: case BuiltinType::DMR2048: + case BuiltinType::MetaInfo: OS << "?"; return; @@ -9325,6 +9333,7 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C, case BuiltinType::OCLReserveID: case BuiltinType::OCLSampler: case BuiltinType::Dependent: + case BuiltinType::MetaInfo: #define PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: #include "clang/Basic/PPCTypes.def" @@ -12826,6 +12835,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, case 'M': Type = Context.getObjCSuperType(); break; + case 'r': + Type = Context.MetaInfoTy; + break; case 'a': Type = Context.getBuiltinVaListType(); assert(!Type.isNull() && "builtin va list type not initialized!"); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index db7d223d56af3..7e726eb155d38 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -686,6 +686,7 @@ namespace clang { ExpectedStmt VisitCXXThisExpr(CXXThisExpr *E); Expecte... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/211653 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
