[clang] [clang]: reflection operator parsing for global namespace and primitive types (PR #164692)

Nhat Nguyen via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 22 12:48:25 PDT 2025


https://github.com/changkhothuychung updated https://github.com/llvm/llvm-project/pull/164692

>From 482e25e9ba7994194f564d3c5f34e57bc818ebf0 Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Wed, 22 Oct 2025 14:34:06 -0400
Subject: [PATCH 1/9] parsing global namespace and primitive types

---
 clang/include/clang/AST/ExprCXX.h             | 50 +++++++++++++++++
 clang/include/clang/AST/RecursiveASTVisitor.h |  4 ++
 .../clang/Basic/DiagnosticParseKinds.td       |  5 ++
 clang/include/clang/Basic/Features.def        |  2 +
 clang/include/clang/Basic/LangOptions.def     |  1 +
 clang/include/clang/Basic/StmtNodes.td        |  3 ++
 clang/include/clang/Basic/TokenKinds.def      |  1 +
 clang/include/clang/Driver/Options.td         |  9 +++-
 clang/include/clang/Parse/Parser.h            | 14 ++++-
 clang/include/clang/Sema/DeclSpec.h           |  2 +-
 clang/include/clang/Sema/Sema.h               | 11 ++++
 .../include/clang/Serialization/ASTBitCodes.h |  3 ++
 clang/lib/AST/ExprCXX.cpp                     | 34 ++++++++++++
 clang/lib/AST/ExprClassification.cpp          |  1 +
 clang/lib/AST/ExprConstant.cpp                |  1 +
 clang/lib/AST/StmtPrinter.cpp                 |  6 +++
 clang/lib/AST/StmtProfile.cpp                 |  5 ++
 clang/lib/Lex/Lexer.cpp                       |  3 ++
 clang/lib/Parse/CMakeLists.txt                |  1 +
 clang/lib/Parse/ParseExpr.cpp                 | 10 ++++
 clang/lib/Parse/ParseReflect.cpp              | 54 +++++++++++++++++++
 clang/lib/Parse/ParseTentative.cpp            |  3 ++
 clang/lib/Sema/SemaExceptionSpec.cpp          |  1 +
 clang/lib/Sema/SemaExpr.cpp                   | 19 +++++++
 clang/lib/Sema/TreeTransform.h                |  6 +++
 clang/lib/Serialization/ASTReaderStmt.cpp     |  9 ++++
 clang/lib/Serialization/ASTWriterStmt.cpp     |  6 +++
 .../Reflection/parsing-reflection.pass.cpp    | 21 ++++++++
 28 files changed, 281 insertions(+), 4 deletions(-)
 create mode 100644 clang/lib/Parse/ParseReflect.cpp
 create mode 100644 clang/test/Reflection/parsing-reflection.pass.cpp

diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 5f16bac94d5e6..5c8b2209d5364 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -5493,6 +5493,56 @@ class BuiltinBitCastExpr final
   }
 };
 
+/// Represents a C++2c reflect expression (P2996).
+class CXXReflectExpr : public Expr {
+
+  // Source locations.
+  SourceLocation OperatorLoc;
+  SourceRange OperandRange;
+
+  CXXReflectExpr(const ASTContext &C, QualType T, QualType Ty);
+  CXXReflectExpr(const ASTContext &C, QualType T, Decl *Arg, bool IsNamespace);
+  CXXReflectExpr(EmptyShell Empty);
+
+public:
+
+  static CXXReflectExpr *Create(ASTContext &C, SourceLocation OperatorLoc,
+                                SourceLocation ArgLoc, QualType Operand);
+
+  static CXXReflectExpr *Create(ASTContext &C, SourceLocation OperatorLoc,
+                                SourceLocation OperandLoc, Decl *Operand);
+
+  static CXXReflectExpr *CreateEmpty(ASTContext& C);
+
+  SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; }
+  SourceLocation getEndLoc() const LLVM_READONLY {
+    return OperandRange.getEnd();
+  }
+  SourceRange getSourceRange() const {
+    return SourceRange(getBeginLoc(), getEndLoc());
+  }
+
+  /// Returns location of the '^^'-operator.
+  SourceLocation getOperatorLoc() const { return OperatorLoc; }
+  SourceRange getOperandRange() const { return OperandRange; }
+
+  /// Sets the location of the '^^'-operator.
+  void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
+  void setOperandRange(SourceRange R) { OperandRange = R; }
+
+  child_range children() {
+    return child_range(child_iterator(), child_iterator());
+  }
+
+  const_child_range children() const {
+    return const_child_range(const_child_iterator(), const_child_iterator());
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == CXXReflectExprClass;
+  }
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_AST_EXPRCXX_H
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 7a2881f6124f3..7b8a678ffb861 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2883,6 +2883,10 @@ DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
   TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
 })
 
+DEF_TRAVERSE_STMT(CXXReflectExpr, {
+  // TODO
+})
+
 // These expressions all might take explicit template arguments.
 // We traverse those if so.  FIXME: implement these.
 DEF_TRAVERSE_STMT(CXXConstructExpr, {})
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index c724136a7fdaf..ea81a2332cd50 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1848,6 +1848,11 @@ def err_placeholder_expected_auto_or_decltype_auto : Error<
   "expected 'auto' or 'decltype(auto)' after concept name">;
 }
 
+let CategoryName = "Reflection Issue" in {
+def err_cannot_reflect_operand : Error<
+  "cannot reflect the provided operand">;
+}
+
 def warn_max_tokens : Warning<
   "the number of preprocessor source tokens (%0) exceeds this token limit (%1)">,
   InGroup<MaxTokens>, DefaultIgnore;
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index 0e91b42a132c1..c9d24430326ff 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -380,6 +380,8 @@ FEATURE(cxx_abi_relative_vtable, LangOpts.CPlusPlus && LangOpts.RelativeCXXABIVT
 
 FEATURE(clang_atomic_attributes, true)
 
+FEATURE(reflection, LangOpts.Reflection)
+
 // CUDA/HIP Features
 FEATURE(cuda_noinline_keyword, LangOpts.CUDA)
 EXTENSION(cuda_implicit_host_device_templates, LangOpts.CUDA && LangOpts.OffloadImplicitHostDeviceTemplates)
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 84f5ab3443a59..b3d4936354e5e 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -498,6 +498,7 @@ LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
 LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety analysis for C++")
 
 LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
+LANGOPT(Reflection      , 1, 0, NotCompatible, "Experimental C++26 Reflection")
 
 #undef LANGOPT
 #undef ENUM_LANGOPT
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index bf3686bb372d5..987e1d1408e06 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -177,6 +177,9 @@ def CoyieldExpr : StmtNode<CoroutineSuspendExpr>;
 def ConceptSpecializationExpr : StmtNode<Expr>;
 def RequiresExpr : StmtNode<Expr>;
 
+// c++ 26 reflection
+def CXXReflectExpr : StmtNode<Expr>;
+
 // Obj-C Expressions.
 def ObjCStringLiteral : StmtNode<Expr>;
 def ObjCBoxedExpr : StmtNode<Expr>;
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 564d6010181cc..b7fef8b2de739 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -233,6 +233,7 @@ PUNCTUATOR(greatergreater,      ">>")
 PUNCTUATOR(greaterequal,        ">=")
 PUNCTUATOR(greatergreaterequal, ">>=")
 PUNCTUATOR(caret,               "^")
+PUNCTUATOR(caretcaret,          "^^")
 PUNCTUATOR(caretequal,          "^=")
 PUNCTUATOR(pipe,                "|")
 PUNCTUATOR(pipepipe,            "||")
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 6245cf33a0719..b3d6dbfb241d5 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3663,6 +3663,11 @@ defm application_extension : BoolFOption<"application-extension",
   PosFlag<SetTrue, [], [ClangOption, CC1Option],
           "Restrict code to those available for App Extensions">,
   NegFlag<SetFalse>>;
+defm reflection : BoolFOption<"reflection",
+  LangOpts<"Reflection">, DefaultFalse,
+  PosFlag<SetTrue, [], [ClangOption, CC1Option],
+          "Enable C++26 reflection">,
+  NegFlag<SetFalse>>;
 defm sized_deallocation : BoolFOption<"sized-deallocation",
   LangOpts<"SizedDeallocation">, Default<cpp14.KeyPath>,
   PosFlag<SetTrue, [], [], "Enable C++14 sized global deallocation functions">,
@@ -4346,7 +4351,7 @@ def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
   HelpText<"Do not process trigraph sequences">,
   Visibility<[ClangOption, CC1Option]>;
 def funique_source_file_names: Flag<["-"], "funique-source-file-names">, Group<f_Group>,
-  HelpText<"Allow the compiler to assume that each translation unit has a unique "                       
+  HelpText<"Allow the compiler to assume that each translation unit has a unique "
            "source file identifier (see -funique-source-file-identifier) at link time">;
 def fno_unique_source_file_names: Flag<["-"], "fno-unique-source-file-names">;
 def unique_source_file_identifier_EQ: Joined<["-"], "funique-source-file-identifier=">, Group<f_Group>,
@@ -7153,7 +7158,7 @@ defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;
 def shared_libflangrt : Flag<["-"], "shared-libflangrt">,
   HelpText<"Link the flang-rt shared library">, Group<Link_Group>,
   Visibility<[FlangOption]>, Flags<[NoArgumentUnused]>;
-def static_libflangrt : Flag<["-"], "static-libflangrt">, 
+def static_libflangrt : Flag<["-"], "static-libflangrt">,
   HelpText<"Link the flang-rt static library">, Group<Link_Group>,
   Visibility<[FlangOption]>, Flags<[NoArgumentUnused]>;
 
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index e301cf1080977..a494c734a074e 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -150,6 +150,7 @@ enum class TentativeCXXTypeIdContext {
   AsTemplateArgument,
   InTrailingReturnType,
   AsGenericSelectionArgument,
+  AsReflectionOperand
 };
 
 /// The kind of attribute specifier we have found.
@@ -1548,6 +1549,7 @@ class Parser : public CodeCompletionHandler {
     DSC_condition,          // condition declaration context
     DSC_association, // A _Generic selection expression's type association
     DSC_new,         // C++ new expression
+    DSC_reflect_operator
   };
 
   /// Is this a context in which we are parsing just a type-specifier (or
@@ -1561,6 +1563,7 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_top_level:
     case DeclSpecContext::DSC_objc_method_result:
     case DeclSpecContext::DSC_condition:
+    case DeclSpecContext::DSC_reflect_operator:
       return false;
 
     case DeclSpecContext::DSC_template_type_arg:
@@ -1619,6 +1622,7 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_conv_operator:
     case DeclSpecContext::DSC_template_arg:
     case DeclSpecContext::DSC_new:
+    case DeclSpecContext::DSC_reflect_operator:
       return AllowDefiningTypeSpec::No;
     }
     llvm_unreachable("Missing DeclSpecContext case");
@@ -1643,6 +1647,7 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_conv_operator:
     case DeclSpecContext::DSC_template_arg:
     case DeclSpecContext::DSC_new:
+    case DeclSpecContext::DSC_reflect_operator:
 
       return false;
     }
@@ -1663,6 +1668,7 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_association:
     case DeclSpecContext::DSC_conv_operator:
     case DeclSpecContext::DSC_new:
+    case DeclSpecContext::DSC_reflect_operator:
       return true;
 
     case DeclSpecContext::DSC_objc_method_result:
@@ -1694,6 +1700,7 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_template_arg:
     case DeclSpecContext::DSC_conv_operator:
     case DeclSpecContext::DSC_association:
+    case DeclSpecContext::DSC_reflect_operator:
       return ImplicitTypenameContext::No;
     }
     llvm_unreachable("Missing DeclSpecContext case");
@@ -5167,6 +5174,11 @@ class Parser : public CodeCompletionHandler {
   /// Implementations are in ParseHLSL.cpp
   ///@{
 
+
+    //===--------------------------------------------------------------------===//
+    // C++2c: Reflection [P2996]
+    ExprResult ParseCXXReflectExpression(SourceLocation OpLoc);
+
 private:
   bool MaybeParseHLSLAnnotations(Declarator &D,
                                  SourceLocation *EndLoc = nullptr,
@@ -7677,7 +7689,7 @@ class Parser : public CodeCompletionHandler {
   /// [GNU] asm-clobbers:
   ///         asm-string-literal
   ///         asm-clobbers ',' asm-string-literal
-  /// \endverbatim 
+  /// \endverbatim
   ///
   StmtResult ParseAsmStatement(bool &msAsm);
 
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index c1a99a1fddc80..0e7171f950ee7 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -1849,7 +1849,7 @@ enum class DeclaratorContext {
   AliasDecl,           // C++11 alias-declaration.
   AliasTemplate,       // C++11 alias-declaration template.
   RequiresExpr,        // C++2a requires-expression.
-  Association          // C11 _Generic selection expression association.
+  Association         // C11 _Generic selection expression association.
 };
 
 // Describes whether the current context is a context where an implicit
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f53aafdeb4f36..d07c1160023b3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14663,6 +14663,17 @@ class Sema final : public SemaBase {
   /// Implementations are in SemaConcept.cpp
   ///@{
 
+public:
+
+    ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, TypeSourceInfo* T);
+    ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc,
+                                 SourceLocation ArgLoc, Decl *D);
+
+    ExprResult BuildCXXReflectExpr(SourceLocation OperatorLoc,
+                                 SourceLocation OperandLoc, QualType T);
+    ExprResult BuildCXXReflectExpr(SourceLocation OperatorLoc,
+                                  SourceLocation OperandLoc, Decl *D);
+
 public:
   void PushSatisfactionStackEntry(const NamedDecl *D,
                                   const llvm::FoldingSetNodeID &ID) {
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 5d09d5536e5ab..b950c444d9aa2 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1925,6 +1925,9 @@ enum StmtCode {
   EXPR_CONCEPT_SPECIALIZATION,            // ConceptSpecializationExpr
   EXPR_REQUIRES,                          // RequiresExpr
 
+  // Reflection
+  EXPR_REFLECT,
+
   // CUDA
   EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
 
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 95de6a82a5270..b4758465f669a 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1939,6 +1939,40 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
   return new (Mem) TypeTraitExpr(EmptyShell(), IsStoredAsBool);
 }
 
+CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, QualType Ty)
+: Expr(CXXReflectExprClass, T, VK_PRValue, OK_Ordinary) {}
+
+CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, Decl *Arg, bool IsNamespace)
+: Expr(CXXReflectExprClass, T, VK_PRValue, OK_Ordinary) {}
+
+CXXReflectExpr::CXXReflectExpr(EmptyShell Empty)
+: Expr(CXXReflectExprClass, Empty) {}
+
+CXXReflectExpr *CXXReflectExpr::Create(ASTContext &C, SourceLocation OperatorLoc,
+                                SourceLocation OperandLoc, QualType Operand) {
+  CXXReflectExpr *E = new (C) CXXReflectExpr(C, C.DependentTy, Operand);
+  E->setOperatorLoc(OperatorLoc);
+  E->setOperandRange(OperandLoc);
+  return E;
+}
+
+CXXReflectExpr *CXXReflectExpr::Create(ASTContext &C,
+                                       SourceLocation OperatorLoc,
+                                       SourceLocation OperandLoc,
+                                       Decl *Operand) {
+  bool IsNamespace = isa<TranslationUnitDecl>(Operand);
+
+  CXXReflectExpr *E = new (C) CXXReflectExpr(C, C.DependentTy, Operand,
+                                             IsNamespace);
+  E->setOperatorLoc(OperatorLoc);
+  E->setOperandRange(OperandLoc);
+  return E;
+}
+
+CXXReflectExpr *CXXReflectExpr::CreateEmpty(ASTContext &C) {
+  return new (C) CXXReflectExpr(EmptyShell());
+}
+
 CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config,
                                        ArrayRef<Expr *> Args, QualType Ty,
                                        ExprValueKind VK, SourceLocation RP,
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index aeacd0dc765ef..4c53c316e989a 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -216,6 +216,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
   case Expr::SourceLocExprClass:
   case Expr::ConceptSpecializationExprClass:
   case Expr::RequiresExprClass:
+  case Expr::CXXReflectExprClass:
     return Cl::CL_PRValue;
 
   case Expr::EmbedExprClass:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index b706b14945b6d..0f14aa3c7258f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -18295,6 +18295,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
   case Expr::ArrayTypeTraitExprClass:
   case Expr::ExpressionTraitExprClass:
   case Expr::CXXNoexceptExprClass:
+  case Expr::CXXReflectExprClass:
     return NoDiag();
   case Expr::CallExprClass:
   case Expr::CXXOperatorCallExprClass: {
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 586c3000f105c..8e5bab721e8e4 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -2566,6 +2566,12 @@ void StmtPrinter::VisitCXXUnresolvedConstructExpr(
     OS << ')';
 }
 
+
+void StmtPrinter::VisitCXXReflectExpr(CXXReflectExpr *S) {
+  // TODO: Make this better.
+  OS << "^(...)";
+}
+
 void StmtPrinter::VisitCXXDependentScopeMemberExpr(
                                          CXXDependentScopeMemberExpr *Node) {
   if (!Node->isImplicitAccess()) {
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 589a156a2b6ea..ad37b5e71472e 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2164,6 +2164,11 @@ StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
   ID.AddInteger(Hasher.CalculateHash());
 }
 
+void StmtProfiler::VisitCXXReflectExpr(const CXXReflectExpr *E) {
+  VisitExpr(E);
+  // TODO: 
+}
+
 void
 StmtProfiler::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *S) {
   VisitExpr(S);
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index b282a600c0e56..5df36d041d0c1 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -4348,6 +4348,9 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
     if (Char == '=') {
       CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
       Kind = tok::caretequal;
+    } else if (LangOpts.Reflection && Char == '^') {
+      CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+      Kind = tok::caretcaret;
     } else {
       if (LangOpts.OpenCL && Char == '^')
         Diag(CurPtr, diag::err_opencl_logical_exclusive_or);
diff --git a/clang/lib/Parse/CMakeLists.txt b/clang/lib/Parse/CMakeLists.txt
index e6cbf3b868b7d..8dd120f529b13 100644
--- a/clang/lib/Parse/CMakeLists.txt
+++ b/clang/lib/Parse/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangParse
   ParseTentative.cpp
   Parser.cpp
   ParseOpenACC.cpp
+  ParseReflect.cpp
 
   LINK_LIBS
   clangAST
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 3515343202de1..22963d985b01b 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1208,6 +1208,13 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand,
     AllowSuffix = false;
     Res = ParseUnaryExprOrTypeTraitExpression();
     break;
+  case tok::caretcaret: {
+    if (getLangOpts().Reflection) {
+      SourceLocation FirstCaret = ConsumeToken(); // eat first '^'
+      Res = ParseCXXReflectExpression(/*OpLoc=*/FirstCaret);
+    }
+    break;
+  }
   case tok::ampamp: {      // unary-expression: '&&' identifier
     if (NotPrimaryExpression)
       *NotPrimaryExpression = true;
@@ -2249,6 +2256,9 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
   else if (getLangOpts().C2y && OpTok.is(tok::kw__Countof))
     Diag(OpTok, diag::warn_c2y_compat_keyword) << OpTok.getName();
 
+  if (OpTok.is(tok::caretcaret))
+    return ParseCXXReflectExpression(OpTok.getLocation());
+
   EnterExpressionEvaluationContext Unevaluated(
       Actions, Sema::ExpressionEvaluationContext::Unevaluated,
       Sema::ReuseLambdaContextDecl);
diff --git a/clang/lib/Parse/ParseReflect.cpp b/clang/lib/Parse/ParseReflect.cpp
new file mode 100644
index 0000000000000..817c885ab2804
--- /dev/null
+++ b/clang/lib/Parse/ParseReflect.cpp
@@ -0,0 +1,54 @@
+
+
+
+
+#include "clang/AST/LocInfoType.h"
+#include "clang/Basic/DiagnosticParse.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
+#include "clang/Sema/EnterExpressionEvaluationContext.h"
+using namespace clang;
+
+ExprResult Parser::ParseCXXReflectExpression(SourceLocation OpLoc) {
+  assert(Tok.is(tok::caretcaret) && "expected '^^'");
+  EnterExpressionEvaluationContext Unevaluated(
+      Actions, Sema::ExpressionEvaluationContext::Unevaluated);
+
+  SourceLocation OperandLoc = Tok.getLocation();
+
+  // Parse a leading nested-name-specifier
+  CXXScopeSpec SS;
+  if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+                                     /*ObjectHasErrors=*/false,
+                                     /*EnteringContext=*/false)) {
+    SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
+    return ExprError();
+  }
+
+  {
+    TentativeParsingAction TPA(*this);
+
+    if (SS.isValid() &&
+               SS.getScopeRep().getKind() == NestedNameSpecifier::Kind::Global) {
+      // Check for global namespace '^^::'
+      TPA.Commit();
+      Decl *TUDecl = Actions.getASTContext().getTranslationUnitDecl();
+      return Actions.ActOnCXXReflectExpr(OpLoc, SourceLocation(), TUDecl);
+    }
+    TPA.Revert();
+  }
+
+  if (isCXXTypeId(TentativeCXXTypeIdContext::AsReflectionOperand)) {
+    TypeResult TR = ParseTypeName(/*TypeOf=*/nullptr);
+    if (TR.isInvalid())
+      return ExprError();
+
+    TypeSourceInfo *TSI = nullptr;
+    QualType QT = Actions.GetTypeFromParser(TR.get(), &TSI);
+
+    return Actions.ActOnCXXReflectExpr(OpLoc, TSI);
+  }
+
+  Diag(OperandLoc, diag::err_cannot_reflect_operand);
+  return ExprError();
+}
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 82f2294ff5bb7..8a3ae2232767e 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -574,6 +574,9 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
     } else if (Context == TentativeCXXTypeIdContext::InTrailingReturnType) {
       TPR = TPResult::True;
       isAmbiguous = true;
+    } else if (Context == TentativeCXXTypeIdContext::AsReflectionOperand) {
+      TPR = TPResult::True;
+      isAmbiguous = true;
     } else
       TPR = TPResult::False;
   }
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index a0483c3027199..ff8d2139289a3 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1379,6 +1379,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
   case Expr::CXXNoexceptExprClass:
   case Expr::CXXNullPtrLiteralExprClass:
   case Expr::CXXPseudoDestructorExprClass:
+  case Expr::CXXReflectExprClass:
   case Expr::CXXScalarValueInitExprClass:
   case Expr::CXXThisExprClass:
   case Expr::CXXUuidofExprClass:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 06b2529011c74..95bc91ab29f90 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17760,6 +17760,25 @@ void Sema::PushExpressionEvaluationContextForFunction(
   }
 }
 
+ExprResult Sema::ActOnCXXReflectExpr(SourceLocation OpLoc, TypeSourceInfo* TSI) {
+  return BuildCXXReflectExpr(OpLoc, TSI->getTypeLoc().getBeginLoc(), TSI->getType());
+}
+
+ExprResult Sema::ActOnCXXReflectExpr(SourceLocation OpLoc,
+                                     SourceLocation ArgLoc, Decl *D) {
+  return BuildCXXReflectExpr(OpLoc, ArgLoc, D);
+}
+
+ExprResult Sema::BuildCXXReflectExpr(SourceLocation OperatorLoc,
+                                     SourceLocation OperandLoc, QualType T) {
+  return CXXReflectExpr::Create(Context, OperatorLoc, OperandLoc, T);
+}
+
+ExprResult Sema::BuildCXXReflectExpr(SourceLocation OperatorLoc,
+                                     SourceLocation OperandLoc, Decl *D) {
+  return CXXReflectExpr::Create(Context, OperatorLoc, OperandLoc, D);
+}
+
 namespace {
 
 const DeclRefExpr *CheckPossibleDeref(Sema &S, const Expr *PossibleDeref) {
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 6967301483361..6620c422331e4 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -12873,6 +12873,12 @@ ExprResult TreeTransform<Derived>::TransformSYCLUniqueStableNameExpr(
       E->getLocation(), E->getLParenLocation(), E->getRParenLocation(), NewT);
 }
 
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformCXXReflectExpr(CXXReflectExpr *E) {
+  // No subexpressions to recurse over in PR1.
+  return E;
+}
+
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 70b898a53fcbd..df65909292863 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -529,6 +529,11 @@ void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) {
   }
 }
 
+
+void ASTStmtReader::VisitCXXReflectExpr(CXXReflectExpr *E) {
+  llvm_unreachable("unimplemented");
+}
+
 void ASTStmtReader::VisitSYCLKernelCallStmt(SYCLKernelCallStmt *S) {
   VisitStmt(S);
   S->setOriginalStmt(cast<CompoundStmt>(Record.readSubStmt()));
@@ -4520,6 +4525,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
     case EXPR_HLSL_OUT_ARG:
       S = HLSLOutArgExpr::CreateEmpty(Context);
       break;
+    case EXPR_REFLECT: {
+      S = CXXReflectExpr::CreateEmpty(Context);
+      break;
+    }
     }
 
     // We hit a STMT_STOP, so we're done with this expression.
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index ebda91e3819c3..1c0ac710cdc98 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -466,6 +466,12 @@ void ASTStmtWriter::VisitCoyieldExpr(CoyieldExpr *E) {
   Code = serialization::EXPR_COYIELD;
 }
 
+void ASTStmtWriter::VisitCXXReflectExpr(CXXReflectExpr *E) {
+  VisitExpr(E);
+  Record.AddSourceLocation(E->getOperatorLoc());
+  Code = serialization::EXPR_REFLECT;
+}
+
 void ASTStmtWriter::VisitDependentCoawaitExpr(DependentCoawaitExpr *E) {
   VisitExpr(E);
   Record.AddSourceLocation(E->getKeywordLoc());
diff --git a/clang/test/Reflection/parsing-reflection.pass.cpp b/clang/test/Reflection/parsing-reflection.pass.cpp
new file mode 100644
index 0000000000000..22101970bd2bd
--- /dev/null
+++ b/clang/test/Reflection/parsing-reflection.pass.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -std=c++23 -freflection
+
+
+int main()
+{
+    (void)(^^::);
+    (void)(^^void);
+    (void)(^^bool);
+    (void)(^^char);
+    (void)(^^signed char);
+    (void)(^^unsigned char);
+    (void)(^^short);
+    (void)(^^unsigned short);
+    (void)(^^int);
+    (void)(^^unsigned int);
+    (void)(^^long);
+    (void)(^^unsigned long);
+    (void)(^^long long);
+    (void)(^^float);
+    (void)(^^double);
+}

>From c2d6d7ee7c8be9e4800f7e7716a437ad04973604 Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Wed, 22 Oct 2025 14:41:01 -0400
Subject: [PATCH 2/9] cleanup

---
 clang/include/clang/Parse/Parser.h  | 8 +-------
 clang/include/clang/Sema/DeclSpec.h | 2 +-
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index a494c734a074e..b9dfd440c7313 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1548,8 +1548,7 @@ class Parser : public CodeCompletionHandler {
                             // 'instancetype'
     DSC_condition,          // condition declaration context
     DSC_association, // A _Generic selection expression's type association
-    DSC_new,         // C++ new expression
-    DSC_reflect_operator
+    DSC_new          // C++ new expression
   };
 
   /// Is this a context in which we are parsing just a type-specifier (or
@@ -1563,7 +1562,6 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_top_level:
     case DeclSpecContext::DSC_objc_method_result:
     case DeclSpecContext::DSC_condition:
-    case DeclSpecContext::DSC_reflect_operator:
       return false;
 
     case DeclSpecContext::DSC_template_type_arg:
@@ -1622,7 +1620,6 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_conv_operator:
     case DeclSpecContext::DSC_template_arg:
     case DeclSpecContext::DSC_new:
-    case DeclSpecContext::DSC_reflect_operator:
       return AllowDefiningTypeSpec::No;
     }
     llvm_unreachable("Missing DeclSpecContext case");
@@ -1647,7 +1644,6 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_conv_operator:
     case DeclSpecContext::DSC_template_arg:
     case DeclSpecContext::DSC_new:
-    case DeclSpecContext::DSC_reflect_operator:
 
       return false;
     }
@@ -1668,7 +1664,6 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_association:
     case DeclSpecContext::DSC_conv_operator:
     case DeclSpecContext::DSC_new:
-    case DeclSpecContext::DSC_reflect_operator:
       return true;
 
     case DeclSpecContext::DSC_objc_method_result:
@@ -1700,7 +1695,6 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_template_arg:
     case DeclSpecContext::DSC_conv_operator:
     case DeclSpecContext::DSC_association:
-    case DeclSpecContext::DSC_reflect_operator:
       return ImplicitTypenameContext::No;
     }
     llvm_unreachable("Missing DeclSpecContext case");
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 0e7171f950ee7..c1a99a1fddc80 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -1849,7 +1849,7 @@ enum class DeclaratorContext {
   AliasDecl,           // C++11 alias-declaration.
   AliasTemplate,       // C++11 alias-declaration template.
   RequiresExpr,        // C++2a requires-expression.
-  Association         // C11 _Generic selection expression association.
+  Association          // C11 _Generic selection expression association.
 };
 
 // Describes whether the current context is a context where an implicit

>From 7c7ac796acd4359e367599a057ae67e72f7f0622 Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Wed, 22 Oct 2025 14:50:35 -0400
Subject: [PATCH 3/9] cleanup

---
 clang/include/clang/Basic/LangOptions.def | 2 +-
 clang/include/clang/Driver/Options.td     | 2 +-
 clang/include/clang/Parse/Parser.h        | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index b3d4936354e5e..b2051fb536432 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -498,7 +498,7 @@ LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
 LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety analysis for C++")
 
 LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
-LANGOPT(Reflection      , 1, 0, NotCompatible, "Experimental C++26 Reflection")
+LANGOPT(Reflection      , 1, 0, NotCompatible, "C++26 Reflection")
 
 #undef LANGOPT
 #undef ENUM_LANGOPT
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index b3d6dbfb241d5..1880459fab52f 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4351,7 +4351,7 @@ def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
   HelpText<"Do not process trigraph sequences">,
   Visibility<[ClangOption, CC1Option]>;
 def funique_source_file_names: Flag<["-"], "funique-source-file-names">, Group<f_Group>,
-  HelpText<"Allow the compiler to assume that each translation unit has a unique "
+  HelpText<"Allow the compiler to assume that each translation unit has a unique "                       
            "source file identifier (see -funique-source-file-identifier) at link time">;
 def fno_unique_source_file_names: Flag<["-"], "fno-unique-source-file-names">;
 def unique_source_file_identifier_EQ: Joined<["-"], "funique-source-file-identifier=">, Group<f_Group>,
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index b9dfd440c7313..9b8d8f7633f4d 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1548,7 +1548,7 @@ class Parser : public CodeCompletionHandler {
                             // 'instancetype'
     DSC_condition,          // condition declaration context
     DSC_association, // A _Generic selection expression's type association
-    DSC_new          // C++ new expression
+    DSC_new,         // C++ new expression
   };
 
   /// Is this a context in which we are parsing just a type-specifier (or
@@ -7683,7 +7683,7 @@ class Parser : public CodeCompletionHandler {
   /// [GNU] asm-clobbers:
   ///         asm-string-literal
   ///         asm-clobbers ',' asm-string-literal
-  /// \endverbatim
+  /// \endverbatim 
   ///
   StmtResult ParseAsmStatement(bool &msAsm);
 

>From 61c7f94abc617fd39ae49ab0a2614a7ad45c6acb Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Wed, 22 Oct 2025 14:51:44 -0400
Subject: [PATCH 4/9] cleanup

---
 clang/include/clang/Driver/Options.td | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 1880459fab52f..2218a767f0c7a 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4351,7 +4351,7 @@ def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
   HelpText<"Do not process trigraph sequences">,
   Visibility<[ClangOption, CC1Option]>;
 def funique_source_file_names: Flag<["-"], "funique-source-file-names">, Group<f_Group>,
-  HelpText<"Allow the compiler to assume that each translation unit has a unique "                       
+  HelpText<"Allow the compiler to assume that each translation unit has a unique "
            "source file identifier (see -funique-source-file-identifier) at link time">;
 def fno_unique_source_file_names: Flag<["-"], "fno-unique-source-file-names">;
 def unique_source_file_identifier_EQ: Joined<["-"], "funique-source-file-identifier=">, Group<f_Group>,
@@ -7158,7 +7158,7 @@ defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;
 def shared_libflangrt : Flag<["-"], "shared-libflangrt">,
   HelpText<"Link the flang-rt shared library">, Group<Link_Group>,
   Visibility<[FlangOption]>, Flags<[NoArgumentUnused]>;
-def static_libflangrt : Flag<["-"], "static-libflangrt">,
+def static_libflangrt : Flag<["-"], "static-libflangrt">, 
   HelpText<"Link the flang-rt static library">, Group<Link_Group>,
   Visibility<[FlangOption]>, Flags<[NoArgumentUnused]>;
 

>From 78fe7c41cd8ddee55ac7c9366a673db88b561d2d Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Wed, 22 Oct 2025 14:52:49 -0400
Subject: [PATCH 5/9] cleanup

---
 clang/include/clang/Driver/Options.td | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 2218a767f0c7a..1880459fab52f 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4351,7 +4351,7 @@ def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
   HelpText<"Do not process trigraph sequences">,
   Visibility<[ClangOption, CC1Option]>;
 def funique_source_file_names: Flag<["-"], "funique-source-file-names">, Group<f_Group>,
-  HelpText<"Allow the compiler to assume that each translation unit has a unique "
+  HelpText<"Allow the compiler to assume that each translation unit has a unique "                       
            "source file identifier (see -funique-source-file-identifier) at link time">;
 def fno_unique_source_file_names: Flag<["-"], "fno-unique-source-file-names">;
 def unique_source_file_identifier_EQ: Joined<["-"], "funique-source-file-identifier=">, Group<f_Group>,
@@ -7158,7 +7158,7 @@ defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;
 def shared_libflangrt : Flag<["-"], "shared-libflangrt">,
   HelpText<"Link the flang-rt shared library">, Group<Link_Group>,
   Visibility<[FlangOption]>, Flags<[NoArgumentUnused]>;
-def static_libflangrt : Flag<["-"], "static-libflangrt">, 
+def static_libflangrt : Flag<["-"], "static-libflangrt">,
   HelpText<"Link the flang-rt static library">, Group<Link_Group>,
   Visibility<[FlangOption]>, Flags<[NoArgumentUnused]>;
 

>From 5ae087341d1f4a397edea5a1c24917e86f6cbca0 Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Wed, 22 Oct 2025 15:22:39 -0400
Subject: [PATCH 6/9] add dummy mangling

---
 clang/lib/AST/ItaniumMangle.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 2173aed5b45af..18bd38c66b5e9 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4945,6 +4945,12 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
     E = cast<ConstantExpr>(E)->getSubExpr();
     goto recurse;
 
+  case Expr::CXXReflectExprClass: {
+    // TODO: implement this after introducing std::meta::info
+    // and add info in APValue
+    break;
+  }
+
   // FIXME: invent manglings for all these.
   case Expr::BlockExprClass:
   case Expr::ChooseExprClass:

>From 4503b11a2036e0f66ab5e789296bf6bc98a4d867 Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Wed, 22 Oct 2025 15:22:49 -0400
Subject: [PATCH 7/9] add file description

---
 clang/lib/Parse/ParseReflect.cpp | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Parse/ParseReflect.cpp b/clang/lib/Parse/ParseReflect.cpp
index 817c885ab2804..8c974d949d87f 100644
--- a/clang/lib/Parse/ParseReflect.cpp
+++ b/clang/lib/Parse/ParseReflect.cpp
@@ -1,11 +1,18 @@
-
-
-
+//===--- ParseReflect.cpp - C++2c Reflection Parsing ---------------------===//
+//
+// 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 implements parsing for reflection facilities.
+//
+//===----------------------------------------------------------------------===//
 
 #include "clang/AST/LocInfoType.h"
 #include "clang/Basic/DiagnosticParse.h"
 #include "clang/Parse/Parser.h"
-#include "clang/Parse/RAIIObjectsForParser.h"
 #include "clang/Sema/EnterExpressionEvaluationContext.h"
 using namespace clang;
 

>From 4852569077792a3432c3f1954749b647dd9430a7 Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Wed, 22 Oct 2025 15:44:44 -0400
Subject: [PATCH 8/9] clang format

---
 clang/include/clang/AST/ExprCXX.h             |  3 +--
 clang/include/clang/AST/RecursiveASTVisitor.h |  4 +---
 clang/include/clang/Parse/Parser.h            |  8 ++++----
 clang/include/clang/Sema/Sema.h               | 16 +++++++--------
 clang/lib/AST/ExprCXX.cpp                     | 20 +++++++++++--------
 clang/lib/AST/StmtPrinter.cpp                 |  1 -
 clang/lib/AST/StmtProfile.cpp                 |  2 +-
 clang/lib/Parse/ParseReflect.cpp              |  2 +-
 clang/lib/Sema/SemaExpr.cpp                   |  6 ++++--
 clang/lib/Serialization/ASTReaderStmt.cpp     |  1 -
 10 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 5c8b2209d5364..be2e5ef8644ee 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -5505,14 +5505,13 @@ class CXXReflectExpr : public Expr {
   CXXReflectExpr(EmptyShell Empty);
 
 public:
-
   static CXXReflectExpr *Create(ASTContext &C, SourceLocation OperatorLoc,
                                 SourceLocation ArgLoc, QualType Operand);
 
   static CXXReflectExpr *Create(ASTContext &C, SourceLocation OperatorLoc,
                                 SourceLocation OperandLoc, Decl *Operand);
 
-  static CXXReflectExpr *CreateEmpty(ASTContext& C);
+  static CXXReflectExpr *CreateEmpty(ASTContext &C);
 
   SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; }
   SourceLocation getEndLoc() const LLVM_READONLY {
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 7b8a678ffb861..827b38a030409 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2883,9 +2883,7 @@ DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
   TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
 })
 
-DEF_TRAVERSE_STMT(CXXReflectExpr, {
-  // TODO
-})
+DEF_TRAVERSE_STMT(CXXReflectExpr, {/*TODO*/})
 
 // These expressions all might take explicit template arguments.
 // We traverse those if so.  FIXME: implement these.
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 9b8d8f7633f4d..c819f18675f5d 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -5169,9 +5169,9 @@ class Parser : public CodeCompletionHandler {
   ///@{
 
 
-    //===--------------------------------------------------------------------===//
-    // C++2c: Reflection [P2996]
-    ExprResult ParseCXXReflectExpression(SourceLocation OpLoc);
+  //===--------------------------------------------------------------------===//
+  // C++2c: Reflection [P2996]
+  ExprResult ParseCXXReflectExpression(SourceLocation OpLoc);
 
 private:
   bool MaybeParseHLSLAnnotations(Declarator &D,
@@ -7683,7 +7683,7 @@ class Parser : public CodeCompletionHandler {
   /// [GNU] asm-clobbers:
   ///         asm-string-literal
   ///         asm-clobbers ',' asm-string-literal
-  /// \endverbatim 
+  /// \endverbatim
   ///
   StmtResult ParseAsmStatement(bool &msAsm);
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d07c1160023b3..dd1c577f7b45d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14665,14 +14665,14 @@ class Sema final : public SemaBase {
 
 public:
 
-    ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, TypeSourceInfo* T);
-    ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc,
-                                 SourceLocation ArgLoc, Decl *D);
-
-    ExprResult BuildCXXReflectExpr(SourceLocation OperatorLoc,
-                                 SourceLocation OperandLoc, QualType T);
-    ExprResult BuildCXXReflectExpr(SourceLocation OperatorLoc,
-                                  SourceLocation OperandLoc, Decl *D);
+  ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, TypeSourceInfo* T);
+  ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, SourceLocation ArgLoc,
+                                 Decl *D);
+
+  ExprResult BuildCXXReflectExpr(SourceLocation OperatorLoc,
+                                SourceLocation OperandLoc, QualType T);
+  ExprResult BuildCXXReflectExpr(SourceLocation OperatorLoc,
+                                SourceLocation OperandLoc, Decl *D);
 
 public:
   void PushSatisfactionStackEntry(const NamedDecl *D,
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index b4758465f669a..f3cf5620ed52d 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1940,16 +1940,19 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
 }
 
 CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, QualType Ty)
-: Expr(CXXReflectExprClass, T, VK_PRValue, OK_Ordinary) {}
+    : Expr(CXXReflectExprClass, T, VK_PRValue, OK_Ordinary) {}
 
-CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, Decl *Arg, bool IsNamespace)
-: Expr(CXXReflectExprClass, T, VK_PRValue, OK_Ordinary) {}
+CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, Decl *Arg,
+                               bool IsNamespace)
+    : Expr(CXXReflectExprClass, T, VK_PRValue, OK_Ordinary) {}
 
 CXXReflectExpr::CXXReflectExpr(EmptyShell Empty)
-: Expr(CXXReflectExprClass, Empty) {}
+    : Expr(CXXReflectExprClass, Empty) {}
 
-CXXReflectExpr *CXXReflectExpr::Create(ASTContext &C, SourceLocation OperatorLoc,
-                                SourceLocation OperandLoc, QualType Operand) {
+CXXReflectExpr *CXXReflectExpr::Create(ASTContext &C,
+                                       SourceLocation OperatorLoc,
+                                       SourceLocation OperandLoc,
+                                       QualType Operand) {
   CXXReflectExpr *E = new (C) CXXReflectExpr(C, C.DependentTy, Operand);
   E->setOperatorLoc(OperatorLoc);
   E->setOperandRange(OperandLoc);
@@ -1962,8 +1965,9 @@ CXXReflectExpr *CXXReflectExpr::Create(ASTContext &C,
                                        Decl *Operand) {
   bool IsNamespace = isa<TranslationUnitDecl>(Operand);
 
-  CXXReflectExpr *E = new (C) CXXReflectExpr(C, C.DependentTy, Operand,
-                                             IsNamespace);
+  CXXReflectExpr *E =
+      new (C) CXXReflectExpr(C, C.DependentTy, Operand, IsNamespace);
+
   E->setOperatorLoc(OperatorLoc);
   E->setOperandRange(OperandLoc);
   return E;
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 8e5bab721e8e4..e3073da1eec9d 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -2566,7 +2566,6 @@ void StmtPrinter::VisitCXXUnresolvedConstructExpr(
     OS << ')';
 }
 
-
 void StmtPrinter::VisitCXXReflectExpr(CXXReflectExpr *S) {
   // TODO: Make this better.
   OS << "^(...)";
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index ad37b5e71472e..56bbffdebb276 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2166,7 +2166,7 @@ StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
 
 void StmtProfiler::VisitCXXReflectExpr(const CXXReflectExpr *E) {
   VisitExpr(E);
-  // TODO: 
+  // TODO:
 }
 
 void
diff --git a/clang/lib/Parse/ParseReflect.cpp b/clang/lib/Parse/ParseReflect.cpp
index 8c974d949d87f..541cbd90261ea 100644
--- a/clang/lib/Parse/ParseReflect.cpp
+++ b/clang/lib/Parse/ParseReflect.cpp
@@ -36,7 +36,7 @@ ExprResult Parser::ParseCXXReflectExpression(SourceLocation OpLoc) {
     TentativeParsingAction TPA(*this);
 
     if (SS.isValid() &&
-               SS.getScopeRep().getKind() == NestedNameSpecifier::Kind::Global) {
+        SS.getScopeRep().getKind() == NestedNameSpecifier::Kind::Global) {
       // Check for global namespace '^^::'
       TPA.Commit();
       Decl *TUDecl = Actions.getASTContext().getTranslationUnitDecl();
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 95bc91ab29f90..239e3382c1ff6 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17760,8 +17760,10 @@ void Sema::PushExpressionEvaluationContextForFunction(
   }
 }
 
-ExprResult Sema::ActOnCXXReflectExpr(SourceLocation OpLoc, TypeSourceInfo* TSI) {
-  return BuildCXXReflectExpr(OpLoc, TSI->getTypeLoc().getBeginLoc(), TSI->getType());
+ExprResult Sema::ActOnCXXReflectExpr(SourceLocation OpLoc,
+                                     TypeSourceInfo *TSI) {
+  return BuildCXXReflectExpr(OpLoc, TSI->getTypeLoc().getBeginLoc(),
+                             TSI->getType());
 }
 
 ExprResult Sema::ActOnCXXReflectExpr(SourceLocation OpLoc,
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index df65909292863..c127ceac245d0 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -529,7 +529,6 @@ void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) {
   }
 }
 
-
 void ASTStmtReader::VisitCXXReflectExpr(CXXReflectExpr *E) {
   llvm_unreachable("unimplemented");
 }

>From d3f0f70c9128dbb549e0d056c41777c4c05b90e7 Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Wed, 22 Oct 2025 15:48:01 -0400
Subject: [PATCH 9/9] clang format

---
 clang/include/clang/Parse/Parser.h | 1 -
 clang/include/clang/Sema/Sema.h    | 6 +++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index c819f18675f5d..6fab68c1a1689 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -5168,7 +5168,6 @@ class Parser : public CodeCompletionHandler {
   /// Implementations are in ParseHLSL.cpp
   ///@{
 
-
   //===--------------------------------------------------------------------===//
   // C++2c: Reflection [P2996]
   ExprResult ParseCXXReflectExpression(SourceLocation OpLoc);
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index dd1c577f7b45d..12ee9e348ef01 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14665,14 +14665,14 @@ class Sema final : public SemaBase {
 
 public:
 
-  ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, TypeSourceInfo* T);
+  ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, TypeSourceInfo *T);
   ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, SourceLocation ArgLoc,
                                  Decl *D);
 
   ExprResult BuildCXXReflectExpr(SourceLocation OperatorLoc,
-                                SourceLocation OperandLoc, QualType T);
+                                 SourceLocation OperandLoc, QualType T);
   ExprResult BuildCXXReflectExpr(SourceLocation OperatorLoc,
-                                SourceLocation OperandLoc, Decl *D);
+                                 SourceLocation OperandLoc, Decl *D);
 
 public:
   void PushSatisfactionStackEntry(const NamedDecl *D,



More information about the cfe-commits mailing list