[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