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

Reply via email to