[clang] [clang] reflection operator parsing for global namespace and primitive types (PR #164685)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 22 12:01:34 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: Nhat Nguyen (changkhothuychung)
<details>
<summary>Changes</summary>
First step in adding support for reflection, will add reflection operator parsing for the remaining cases in upcoming subsequent PRs.
---
Patch is 22.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/164685.diff
27 Files Affected:
- (modified) clang/include/clang/AST/ExprCXX.h (+50)
- (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+4)
- (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+5)
- (modified) clang/include/clang/Basic/Features.def (+2)
- (modified) clang/include/clang/Basic/LangOptions.def (+1)
- (modified) clang/include/clang/Basic/StmtNodes.td (+3)
- (modified) clang/include/clang/Basic/TokenKinds.def (+1)
- (modified) clang/include/clang/Driver/Options.td (+6-1)
- (modified) clang/include/clang/Parse/Parser.h (+6)
- (modified) clang/include/clang/Sema/Sema.h (+11)
- (modified) clang/include/clang/Serialization/ASTBitCodes.h (+3)
- (modified) clang/lib/AST/ExprCXX.cpp (+34)
- (modified) clang/lib/AST/ExprClassification.cpp (+1)
- (modified) clang/lib/AST/ExprConstant.cpp (+1)
- (modified) clang/lib/AST/StmtPrinter.cpp (+6)
- (modified) clang/lib/AST/StmtProfile.cpp (+5)
- (modified) clang/lib/Lex/Lexer.cpp (+3)
- (modified) clang/lib/Parse/CMakeLists.txt (+1)
- (modified) clang/lib/Parse/ParseExpr.cpp (+10)
- (added) clang/lib/Parse/ParseReflect.cpp (+54)
- (modified) clang/lib/Parse/ParseTentative.cpp (+3)
- (modified) clang/lib/Sema/SemaExceptionSpec.cpp (+1)
- (modified) clang/lib/Sema/SemaExpr.cpp (+19)
- (modified) clang/lib/Sema/TreeTransform.h (+6)
- (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+9)
- (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+6)
- (added) clang/test/Reflection/parsing-reflection.pass.cpp (+21)
``````````diff
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..b2051fb536432 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, "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..1880459fab52f 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">,
@@ -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..9b8d8f7633f4d 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.
@@ -5167,6 +5168,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,
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(PredefinedExp...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/164685
More information about the cfe-commits
mailing list