https://github.com/changkhothuychung updated https://github.com/llvm/llvm-project/pull/190356
>From e41e160d5881b1383fcaa7fc847c1f5a375c0ac7 Mon Sep 17 00:00:00 2001 From: changkhothuychung <[email protected]> Date: Fri, 3 Apr 2026 11:48:07 -0400 Subject: [PATCH] initial commit --- clang/include/clang/AST/APValue.h | 37 ++++++++++- clang/include/clang/AST/ASTContext.h | 1 + clang/include/clang/AST/BuiltinTypes.def | 3 + clang/include/clang/AST/ExprCXX.h | 20 +++--- clang/include/clang/AST/Reflection.h | 25 ++++++++ clang/include/clang/AST/TypeBase.h | 5 ++ clang/include/clang/Basic/TargetInfo.h | 5 ++ clang/lib/AST/APValue.cpp | 22 +++++++ clang/lib/AST/ASTContext.cpp | 7 +++ clang/lib/AST/ExprCXX.cpp | 9 +-- clang/lib/AST/ExprConstant.cpp | 63 +++++++++++++++++++ clang/lib/AST/Type.cpp | 10 +++ clang/lib/Basic/TargetInfo.cpp | 2 + clang/lib/CodeGen/CodeGenModule.cpp | 3 + clang/lib/CodeGen/CodeGenTypes.cpp | 4 ++ clang/lib/CodeGen/ItaniumCXXABI.cpp | 1 + clang/lib/Sema/SemaExpr.cpp | 7 +++ clang/lib/Sema/SemaOverload.cpp | 16 +++++ clang/lib/Sema/TreeTransform.h | 5 +- .../CodeGenCXX/reflection-mangle-itanium.cpp | 4 ++ .../test/CodeGenCXX/reflection-mangle-ms.cpp | 3 + .../test/Parser/reflection-meta-info.fail.cpp | 21 +++++++ .../test/Parser/reflection-meta-info.pass.cpp | 39 ++++++++++++ 23 files changed, 298 insertions(+), 14 deletions(-) create mode 100644 clang/include/clang/AST/Reflection.h create mode 100644 clang/test/Parser/reflection-meta-info.fail.cpp create mode 100644 clang/test/Parser/reflection-meta-info.pass.cpp diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 8a2d6d434792a..efd293914ff32 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" @@ -140,7 +141,8 @@ class APValue { Struct, Union, MemberPointer, - AddrLabelDiff + AddrLabelDiff, + Reflection }; class alignas(uint64_t) LValueBase { @@ -304,12 +306,16 @@ class APValue { const AddrLabelExpr* LHSExpr; const AddrLabelExpr* RHSExpr; }; + struct ReflectionData { + const 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, Arr, StructData, - UnionData, AddrLabelDiffData> DataType; + UnionData, AddrLabelDiffData, ReflectionData> DataType; static const size_t DataSize = sizeof(DataType); DataType Data; @@ -396,6 +402,15 @@ 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. @@ -476,6 +491,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; @@ -651,6 +667,16 @@ class APValue { return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr; } + const ReflectionKind getReflectionOperandKind() const { + assert(isReflection() && "Invalid accessor"); + return ((const ReflectionData *)(const char *)&Data)->OperandKind; + } + + const void* getOpaqueReflectionOperand() 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); @@ -696,6 +722,13 @@ 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 05302c30d18d1..0f96ce9fc7f7b 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1315,6 +1315,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..87a376a839cda 100644 --- a/clang/include/clang/AST/BuiltinTypes.def +++ b/clang/include/clang/AST/BuiltinTypes.def @@ -226,6 +226,9 @@ FLOATING_TYPE(Ibm128, Ibm128Ty) // This is the type of C++0x 'nullptr'. BUILTIN_TYPE(NullPtr, NullPtrTy) +// 'std::meta::info' in C++ +BUILTIN_TYPE(MetaInfo, MetaInfoTy) + // The primitive Objective C 'id' type. The user-visible 'id' // type is a typedef of an ObjCObjectPointerType to an // ObjCObjectType with this as its base. In fact, this only ever diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index c40cd929b7408..824d96cb9dae1 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" @@ -5508,15 +5509,18 @@ class BuiltinBitCastExpr final /// - an id-expression. class CXXReflectExpr : public Expr { - // TODO(Reflection): add support for TemplateReference, NamespaceReference and - // DeclRefExpr - using operand_type = llvm::PointerUnion<const TypeSourceInfo *>; - SourceLocation CaretCaretLoc; - operand_type Operand; + private: + // TODO(Reflection): add support for TemplateReference, NamespaceReference and + // DeclRefExpr + using operand_type = llvm::PointerUnion<const TypeSourceInfo *>; - CXXReflectExpr(SourceLocation CaretCaretLoc, const TypeSourceInfo *TSI); - CXXReflectExpr(EmptyShell Empty); + SourceLocation CaretCaretLoc; + ReflectionKind Kind; + operand_type Operand; + + CXXReflectExpr(ASTContext &C, SourceLocation CaretCaretLoc, const TypeSourceInfo *TSI); + CXXReflectExpr(EmptyShell Empty); public: static CXXReflectExpr *Create(ASTContext &C, SourceLocation OperatorLoc, @@ -5538,6 +5542,8 @@ class CXXReflectExpr : public Expr { /// Returns location of the '^^'-operator. SourceLocation getOperatorLoc() const { return CaretCaretLoc; } + ReflectionKind getKind() const { return Kind; } + const void* getOpaqueValue() const { return Operand.getOpaqueValue(); } child_range children() { // TODO(Reflection) diff --git a/clang/include/clang/AST/Reflection.h b/clang/include/clang/AST/Reflection.h new file mode 100644 index 0000000000000..140f48af6efe3 --- /dev/null +++ b/clang/include/clang/AST/Reflection.h @@ -0,0 +1,25 @@ +//===--- 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 +namespace clang { + +// TODO(Reflection): Add support for Template, Namespace and DeclRefExpr. +enum class ReflectionKind { + Type +}; + +} + +#endif diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index 9402469f5e12b..bdbca5b8d9dae 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -2634,6 +2634,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isRecordType() const; bool isClassType() const; bool isStructureType() const; + bool isMetaInfoType() const; bool isStructureTypeWithFlexibleArrayMember() const; bool isObjCBoxableRecordType() const; bool isInterfaceType() const; @@ -8953,6 +8954,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/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index ec6cd2be7c3c5..a830d165de98c 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; @@ -824,6 +825,10 @@ class TargetInfo : public TransferrableTargetInfo, unsigned getIbm128Align() const { return Ibm128Align; } const llvm::fltSemantics &getIbm128Format() const { return *Ibm128Format; } + /// getMetaInfoWidth/Align - Returns the size/align of std::meta::info. + unsigned getMetaInfoWidth() const { return MetaInfoWidth; } + unsigned getMetaInfoAlign() const { return MetaInfoAlign; } + /// Return the mangled code of long double. virtual const char *getLongDoubleMangling() const { return "e"; } diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 2e1c8eb3726cf..803c54d4f1c07 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -377,6 +377,9 @@ APValue::APValue(const APValue &RHS) MakeAddrLabelDiff(); setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS()); break; + case Reflection: + MakeReflection(RHS.getReflectionOperandKind(), RHS.getOpaqueReflectionOperand()); + break; } } @@ -430,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; } @@ -439,6 +444,7 @@ bool APValue::needsCleanup() const { case None: case Indeterminate: case AddrLabelDiff: + case Reflection: return false; case Struct: case Union: @@ -486,6 +492,18 @@ static void profileIntValue(llvm::FoldingSetNodeID &ID, const llvm::APInt &V) { ID.AddInteger((uint32_t)V.extractBitsAsZExtValue(std::min(32u, N - I), I)); } +static void profileReflection(llvm::FoldingSetNodeID &ID, APValue V) { + ID.AddInteger(static_cast<int>(V.getReflectionOperandKind())); + switch (V.getReflectionOperandKind()) { + case ReflectionKind::Type: { + const TypeSourceInfo* info = static_cast<const TypeSourceInfo*>(V.getOpaqueReflectionOperand()); + ID.AddPointer((info->getType().getCanonicalType().getAsOpaquePtr())); + 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 @@ -624,6 +642,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!"); @@ -1139,6 +1160,7 @@ LinkageInfo LinkageComputer::getLVForValue(const APValue &V, case APValue::ComplexInt: case APValue::ComplexFloat: case APValue::Vector: + case APValue::Reflection: break; case APValue::AddrLabelDiff: diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index b74766dab38f8..937bcb17da44f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1452,6 +1452,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); @@ -2280,6 +2283,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: diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index bcc481fc8399f..489ad54b1509c 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -24,6 +24,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/LambdaCapture.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/Reflection.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" @@ -1942,15 +1943,15 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C, CXXReflectExpr::CXXReflectExpr(EmptyShell Empty) : Expr(CXXReflectExprClass, Empty) {} -CXXReflectExpr::CXXReflectExpr(SourceLocation CaretCaretLoc, +CXXReflectExpr::CXXReflectExpr(ASTContext &C, SourceLocation CaretCaretLoc, const TypeSourceInfo *TSI) - : Expr(CXXReflectExprClass, TSI->getType(), VK_PRValue, OK_Ordinary), - CaretCaretLoc(CaretCaretLoc), Operand(TSI) {} + : Expr(CXXReflectExprClass, C.MetaInfoTy, VK_PRValue, OK_Ordinary), + CaretCaretLoc(CaretCaretLoc), Kind(ReflectionKind::Type), Operand(TSI) {} CXXReflectExpr *CXXReflectExpr::Create(ASTContext &C, SourceLocation CaretCaretLoc, TypeSourceInfo *TSI) { - return new (C) CXXReflectExpr(CaretCaretLoc, TSI); + return new (C) CXXReflectExpr(C, CaretCaretLoc, TSI); } CXXReflectExpr *CXXReflectExpr::CreateEmpty(ASTContext &C) { diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5973315406aed..069c9b9116af6 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -51,6 +51,7 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/Reflection.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/TargetBuiltins.h" @@ -2469,6 +2470,8 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, Value.getUnionValue(), Kind, Value.getUnionField(), CheckedTemps); } if (Value.isStruct()) { + if (Type->isMetaInfoType()) + return true; auto *RD = Type->castAsRecordDecl(); if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) { unsigned BaseIndex = 0; @@ -10895,6 +10898,46 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { return true; } + +//===----------------------------------------------------------------------===// +// Reflection expression evaluation +//===----------------------------------------------------------------------===// + +namespace { +class ReflectionEvaluator + : public ExprEvaluatorBase<ReflectionEvaluator> { + + using BaseType = ExprEvaluatorBase<ReflectionEvaluator>; + + APValue &Result; +public: + ReflectionEvaluator(EvalInfo &E, APValue &Result) + : ExprEvaluatorBaseTy(E), Result(Result) {} + + bool Success(const APValue &V, const Expr *E) { + Result = V; + return true; + } + + bool VisitCXXReflectExpr(const CXXReflectExpr *E); +}; + +bool ReflectionEvaluator::VisitCXXReflectExpr(const CXXReflectExpr *E) { + switch (E->getKind()) { + case ReflectionKind::Type: { + APValue Result(ReflectionKind::Type, E->getOpaqueValue()); + return Success(Result, E); + } + } + llvm_unreachable("invalid reflection"); +} +} // end anonymous namespace + +static bool EvaluateReflection(const Expr *E, APValue &Result, EvalInfo &Info) { + assert(E->isPRValue() && E->getType()->isMetaInfoType()); + return ReflectionEvaluator(Info, Result).Visit(E); +} + //===----------------------------------------------------------------------===// // Member Pointer Evaluation //===----------------------------------------------------------------------===// @@ -18277,6 +18320,23 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, return Success(CmpResult::Equal, E); } + if (LHSTy->isMetaInfoType() && RHSTy->isMetaInfoType()) { + APValue LHSValue, RHSValue; + llvm::FoldingSetNodeID LID, RID; + if (!Evaluate(LHSValue, Info, E->getLHS())) + return false; + LHSValue.Profile(LID); + + if (!Evaluate(RHSValue, Info, E->getRHS())) + return false; + RHSValue.Profile(RID); + + if (LID == RID) + return Success(CmpResult::Equal, E); + else + return Success(CmpResult::Unequal, E); + } + return DoAfter(); } @@ -20432,6 +20492,9 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { } else if (T->isIntegralOrEnumerationType()) { if (!IntExprEvaluator(Info, Result).Visit(E)) return false; + } else if (T->isMetaInfoType()) { + if(!EvaluateReflection(E, Result, Info)) + return false; } else if (T->hasPointerRepresentation()) { LValue LV; if (!EvaluatePointer(E, LV, Info)) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index a85f08753a132..eebea6811b5c6 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3105,6 +3105,13 @@ bool Type::isLiteralType(const ASTContext &Ctx) const { return true; } + // C++26 [basic.types]p9: + // -- std::meta::info is a scalar type + // C++26 [basic.types]p10: + // -- a scalar type is a literal type + if(isMetaInfoType()) + return true; + // We treat _Atomic T as a literal type if T is a literal type. if (const auto *AT = BaseTy->getAs<AtomicType>()) return AT->getValueType()->isLiteralType(Ctx); @@ -3480,6 +3487,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { return "unsigned _Accum"; case ULongAccum: return "unsigned long _Accum"; + case BuiltinType::MetaInfo: + return "meta::info"; case BuiltinType::ShortFract: return "short _Fract"; case BuiltinType::Fract: @@ -5194,6 +5203,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { #include "clang/Basic/HLSLIntangibleTypes.def" case BuiltinType::BuiltinFn: case BuiltinType::NullPtr: + case BuiltinType::MetaInfo: case BuiltinType::IncompleteMatrixIdx: case BuiltinType::ArraySection: case BuiltinType::OMPArrayShaping: diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 794621c4b3e1f..3943347947d5c 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -125,6 +125,8 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) { LongDoubleAlign = 64; Float128Align = 128; Ibm128Align = 128; + MetaInfoWidth = 64; + MetaInfoAlign = 64; LargeArrayMinWidth = 0; LargeArrayAlign = 0; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 35ee108cdc4fc..fb341ba9615dc 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6085,6 +6085,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, if (getLangOpts().OpenCL && ASTTy->isSamplerT()) return; + if (getLangOpts().Reflection && ASTTy->isMetaInfoType()) + return; + // HLSL default buffer constants will be emitted during HLSLBufferDecl codegen if (getLangOpts().HLSL && D->getType().getAddressSpace() == LangAS::hlsl_constant) diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 6bd79056e599a..b17d38e659450 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -515,6 +515,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { ResultType = llvm::PointerType::getUnqual(getLLVMContext()); break; + case BuiltinType::MetaInfo: + ResultType = llvm::IntegerType::get(getLLVMContext(), 64); + break; + case BuiltinType::UInt128: case BuiltinType::Int128: ResultType = llvm::IntegerType::get(getLLVMContext(), 128); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 397db2ee59408..740a1bae37e8b 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3774,6 +3774,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { case BuiltinType::SatUFract: case BuiltinType::SatULongFract: case BuiltinType::BFloat16: + case BuiltinType::MetaInfo: return false; case BuiltinType::Dependent: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 82da5dc032237..91a51ee23c064 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -12890,6 +12890,13 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, *CCT, Loc, ComparisonCategoryUsage::OperatorInExpression); }; + if(LHSType->isMetaInfoType() && RHSType->isMetaInfoType()){ + if(!BinaryOperator::isEqualityOp(Opc)) { + return InvalidOperands(Loc, LHS, RHS); + } + return computeResultTy(); + } + if (!IsOrdered && LHSIsNull != RHSIsNull) { bool IsEquality = Opc == BO_EQ; if (RHSIsNull) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index c513e72db1094..26f1e8a6a70c8 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -9049,6 +9049,10 @@ class BuiltinCandidateTypeSet { /// candidate set. bool HasNullPtrType; + /// A flag indicating whether the reflection type was present in the + /// candidate set. + bool HasReflectionType; + /// Sema - The semantic analysis instance where we are building the /// candidate type set. Sema &SemaRef; @@ -9068,6 +9072,7 @@ class BuiltinCandidateTypeSet { : HasNonRecordTypes(false), HasArithmeticOrEnumeralTypes(false), HasNullPtrType(false), + HasReflectionType(false), SemaRef(SemaRef), Context(SemaRef.Context) { } @@ -9092,6 +9097,7 @@ class BuiltinCandidateTypeSet { bool hasNonRecordTypes() { return HasNonRecordTypes; } bool hasArithmeticOrEnumeralTypes() { return HasArithmeticOrEnumeralTypes; } bool hasNullPtrType() const { return HasNullPtrType; } + bool hasReflectionType() const { return HasReflectionType; } }; } // end anonymous namespace @@ -9273,6 +9279,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, MatrixTypes.insert(Ty); } else if (Ty->isNullPtrType()) { HasNullPtrType = true; + } else if (Ty->isMetaInfoType()) { + HasReflectionType = true; } else if (AllowUserConversions && TyIsRec) { // No conversion functions in incomplete types. if (!SemaRef.isCompleteType(Loc, Ty)) @@ -9752,6 +9760,14 @@ class BuiltinOperatorOverloadBuilder { S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } } + + if (CandidateTypes[ArgIdx].hasReflectionType()) { + CanQualType InfoTy = S.Context.getCanonicalType(S.Context.MetaInfoTy); + if (AddedTypes.insert(InfoTy).second) { + QualType ParamTypes[2] = { InfoTy, InfoTy }; + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); + } + } } } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 1a050bd6a8737..4cabed7aea323 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13079,7 +13079,10 @@ ExprResult TreeTransform<Derived>::TransformSYCLUniqueStableNameExpr( template <typename Derived> ExprResult TreeTransform<Derived>::TransformCXXReflectExpr(CXXReflectExpr *E) { // TODO(reflection): Implement its transform - assert(false && "not implemented yet"); + if (!E->isTypeDependent()) + return E; + + assert(false && "unknown or unimplemented reflection entities"); return ExprError(); } diff --git a/clang/test/CodeGenCXX/reflection-mangle-itanium.cpp b/clang/test/CodeGenCXX/reflection-mangle-itanium.cpp index a6266165e77f8..1530b4064169a 100644 --- a/clang/test/CodeGenCXX/reflection-mangle-itanium.cpp +++ b/clang/test/CodeGenCXX/reflection-mangle-itanium.cpp @@ -1,6 +1,10 @@ // RUN: %clang_cc1 -std=c++26 -freflection -triple x86_64-unknown-linux-gnu \ // RUN: -emit-llvm -o - %s -verify +constexpr auto r = ^^int; +constexpr auto q = r; + + int main() { (void)(^^int); // expected-error {{cannot compile this scalar expression yet}} return 0; diff --git a/clang/test/CodeGenCXX/reflection-mangle-ms.cpp b/clang/test/CodeGenCXX/reflection-mangle-ms.cpp index 327bc0111bae8..224049521e77e 100644 --- a/clang/test/CodeGenCXX/reflection-mangle-ms.cpp +++ b/clang/test/CodeGenCXX/reflection-mangle-ms.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++26 -freflection -triple x86_64-pc-windows-msvc \ // RUN: -emit-llvm -o - %s -verify +constexpr auto r = ^^int; +constexpr auto q = r; + int main() { (void)(^^int); // expected-error {{cannot compile this scalar expression yet}} return 0; diff --git a/clang/test/Parser/reflection-meta-info.fail.cpp b/clang/test/Parser/reflection-meta-info.fail.cpp new file mode 100644 index 0000000000000..2eade98ea6c5d --- /dev/null +++ b/clang/test/Parser/reflection-meta-info.fail.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 %s -std=c++26 -freflection -fsyntax-only -verify + +using info = decltype(^^int); + +struct X { int a; }; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'meta::info' to 'const X' for 1st argument}} \ + // expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'meta::info' to 'X' for 1st argument}} \ + // expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} +template <typename T = X, auto ptm = &X::a> +constexpr auto ptmOp = ((T)(^^int)).*ptm; // expected-error {{no matching conversion for C-style cast from 'meta::info' to 'X'}} +constexpr auto var = ptmOp<>; // expected-note {{in instantiation of variable template specialization 'ptmOp' requested here}} + +consteval void test() +{ + (^^char)++; // expected-error {{cannot increment value of type 'meta::info'}} + (^^short)++; // expected-error {{cannot increment value of type 'meta::info'}} + (^^int)++; // expected-error {{cannot increment value of type 'meta::info'}} + + (^^char)--; // expected-error {{cannot decrement value of type 'meta::info'}} + (^^short)--; // expected-error {{cannot decrement value of type 'meta::info'}} + (^^int)--; // expected-error {{cannot decrement value of type 'meta::info'}} +} diff --git a/clang/test/Parser/reflection-meta-info.pass.cpp b/clang/test/Parser/reflection-meta-info.pass.cpp new file mode 100644 index 0000000000000..843227000bcec --- /dev/null +++ b/clang/test/Parser/reflection-meta-info.pass.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 %s -std=c++26 -freflection -fsyntax-only + +using info = decltype(^^int); + +consteval void test() +{ + constexpr auto r = ^^int; + constexpr auto q = ^^int; + + static_assert(__is_same(decltype(^^int), info)); + static_assert(__is_same(decltype(^^float), info)); + static_assert(__is_same(decltype(^^double), info)); + static_assert(__is_same(decltype(^^long), info)); + static_assert(__is_same(decltype(^^long long), info)); + static_assert(__is_same(decltype(^^short), info)); + static_assert(__is_same(decltype(^^char), info)); + static_assert(__is_same(decltype(^^unsigned char), info)); + static_assert(__is_same(decltype(^^unsigned short), info)); + static_assert(__is_same(decltype(^^unsigned int), info)); + static_assert(__is_same(decltype(^^unsigned long), info)); + static_assert(__is_same(decltype(^^unsigned long long), info)); + + static_assert(__is_same(decltype(^^int), decltype(^^int))); + static_assert(__is_same(decltype(^^int), decltype(^^float))); + static_assert(__is_same(decltype(^^int), decltype(^^char))); + static_assert(__is_same(decltype(^^double), decltype(^^float))); + + static_assert(!__is_same(decltype(^^int), int)); + + static_assert(sizeof(^^int) == sizeof(^^float)); + static_assert(sizeof(^^int) == 8); + + + static_assert(^^int == ^^int); + static_assert(^^int != ^^float); + static_assert(^^float != ^^int); + static_assert(!(^^float == ^^int)); + static_assert(r == q); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
