-
Notifications
You must be signed in to change notification settings - Fork 15k
[clang]: reflection operator parsing for global namespace and primitive types #164692
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
implement views::concat (P2542)
Revert "implement views::concat (P2542) "
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-modules Author: Nhat Nguyen (changkhothuychung) ChangesPatch is 23.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/164692.diff 28 Files Affected:
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/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:
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..8c974d949d87f
--- /dev/null
+++ b/clang/lib/Parse/ParseReflect.cpp
@@ -0,0 +1,61 @@
+//===--- 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/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,
+ ...
[truncated]
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
| ///@{ | ||
|
|
||
| //===--------------------------------------------------------------------===// | ||
| // Parses the operand of reflection operator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have a \param and \return
| } | ||
|
|
||
| void StmtPrinter::VisitCXXReflectExpr(CXXReflectExpr *S) { | ||
| // TODO(Reflection): Implement this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would think you could partially implement this but I guess you are avoiding it to keep things simple?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah im thinking since we don't have enough info in CXXReflectExpr yet, we can leave it for the next round. But let me know what you think we can show now.
clang/lib/Lex/Lexer.cpp
Outdated
| @@ -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 == '^') { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add a check for C++26 as well.
| Res = ParseUnaryExprOrTypeTraitExpression(); | ||
| break; | ||
| case tok::caretcaret: { | ||
| if (getLangOpts().Reflection) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I apologize but we should add tests in Objective-C to make sure we don't break things accidently. Maybe @rjmccall might be helpful here in guiding us on things to look out for here.
Co-authored-by: Shafik Yaghmour <shafik.yaghmour@intel.com>
If this is the decision, I think it will be better to explicitly diagnose for any code path that triggers serialization |
That seems pretty novel? We don't typically diagnose that sort of thing. |
|
Discussing offline-An experimental reflection flag is the best way forward for now. At least until we're out of 'experimental'. Another thing I was thinking: we should limit where we check it to JUST the places in parsing where we identify the operators. Else, we risk hiding bugs. 1 last thing: we should diagnose in non-reflection mode the token |
I just think, if users triggers serialization with reflection now, it is better to diagnose immediately instead of continue silently and the user may meet odd problems... |
Typically we count on the 'experimental' word in the flag to warn that. Do we otherwise diagnose in serialization? I'd rather us not try to do something new there. |
I just want to offer more info for users so that they can understand the status better and not confusing. This is a suggestion not a requirement. |
That’s a good idea, it’d be similar to the C++98 compatibility warning we have that suggests rewriting |
| /// Represents a C++26 reflect expression [expr.reflect]. The operand of of the | ||
| /// expression is either a: | ||
| /// - :: (global namespace) | ||
| /// - a reflection-name | ||
| /// - a type-id | ||
| /// - id-expression. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// Represents a C++26 reflect expression [expr.reflect]. The operand of of the | |
| /// expression is either a: | |
| /// - :: (global namespace) | |
| /// - a reflection-name | |
| /// - a type-id | |
| /// - id-expression. | |
| /// Represents a C++26 reflect expression [expr.reflect]. The operand of the | |
| /// expression is either: | |
| /// - :: (global namespace), | |
| /// - a reflection-name, | |
| /// - a type-id, or | |
| /// - an id-expression. |
This PR implements parsing the reflection operator (^^) for global namespace and primitive types. The goal is to keep the first PR simple. In subsequent PRs, parsing for the remaining requirements will be introduced.
Class
CXXReflectExpris introduced to represent the operand of the reflection operator. For now, in this PR, the type std::meta::info is not implemented yet, so when we construct an AST node CXXReflectExpr,VoidTyis used as placeholder type for now.The file
ParseReflect.cppis introduced, which for now only has the functionParseCXXReflectExpression. It parses the operand of the reflection operator.