[libcxx-commits] [clang] [libcxx] [lldb] [clang]: implement std::meta::is_type (PR #211653)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jul 23 12:53:35 PDT 2026
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
More information about the libcxx-commits
mailing list