-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[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. |
|
|
||
| // Not supported yet. | ||
| (void)^^a; // expected-error {{expected reflectable entity}} | ||
| (void)^^a::; // expected-error {{expected reflectable entity}} |
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.
There might be room for a better diagnostic for this case, but I personally think it's fine for now, and we can always work on improving it later.
@erichkeane @cor3ntin Wdyt?
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.
@katzdm, it is unclear to me (given the specific scope for the current PR) whether this will simply become undiagnosed in the future (and treated the same as ^^a).
|
I left a few more comments, but now I'm out of feedback. Looking forward to seeing this land once maintainers are happy with it!! 🚀 |
Sirraide
left a comment
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, I think we should be able to merge this soon.
Co-authored-by: Sirraide <[email protected]>
Co-authored-by: Sirraide <[email protected]>
Co-authored-by: Sirraide <[email protected]>
Co-authored-by: Sirraide <[email protected]>
Co-authored-by: Sirraide <[email protected]>
Sirraide
left a comment
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.
A few last comments
Co-authored-by: Sirraide <[email protected]>
Co-authored-by: Sirraide <[email protected]>
Sirraide
left a comment
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.
LGTM, but I’d say wait a day or two for someone else to approve this too or in case there are any other comments.
hubert-reinterpretcast
left a comment
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.
Mostly minor nits but some questions as well.
| CXXReflectExpr(const ASTContext &C, QualType T, QualType Ty); | ||
| CXXReflectExpr(const ASTContext &C, QualType T, Decl *Arg); |
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.
At least avoid two QualType arguments with vague names.
| CXXReflectExpr(const ASTContext &C, QualType T, QualType Ty); | |
| CXXReflectExpr(const ASTContext &C, QualType T, Decl *Arg); | |
| CXXReflectExpr(const ASTContext &C, QualType T, QualType Operand); | |
| CXXReflectExpr(const ASTContext &C, QualType T, Decl *Operand); |
|
|
||
| public: | ||
| static CXXReflectExpr *Create(ASTContext &C, SourceLocation OperatorLoc, | ||
| SourceLocation ArgLoc, QualType Operand); |
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.
Let's be consistent between Arg versus Operand.
| SourceLocation ArgLoc, QualType Operand); | |
| SourceLocation OperandLoc, QualType Operand); |
| 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()); | ||
| } |
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.
Add FIXMEs to implement these.
| ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, SourceLocation ArgLoc, | ||
| Decl *D); |
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.
| ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, SourceLocation ArgLoc, | |
| Decl *D); | |
| ExprResult ActOnCXXReflectExpr(SourceLocation OpLoc, | |
| SourceLocation OperandLoc, Decl *D); |
| return new (Mem) TypeTraitExpr(EmptyShell(), IsStoredAsBool); | ||
| } | ||
|
|
||
| CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, QualType Ty) |
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.
| CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, QualType Ty) | |
| CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, | |
| QualType Operand) |
| 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) |
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.
| CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, Decl *Arg) | |
| CXXReflectExpr::CXXReflectExpr(const ASTContext &C, QualType T, Decl *Operand) |
| SourceLocation OperandLoc, | ||
| Decl *Operand) { | ||
| CXXReflectExpr *E = new (C) CXXReflectExpr(C, C.VoidTy, Operand); | ||
|
|
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.
| SS.getScopeRep().getKind() == NestedNameSpecifier::Kind::Global) { | ||
| // global namespace ::. | ||
| Decl *TUDecl = Actions.getASTContext().getTranslationUnitDecl(); | ||
| return Actions.ActOnCXXReflectExpr(DoubleCaretLoc, SourceLocation(), |
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.
Why can't we get a source location for the operand here?
| SourceLocation ArgLoc, Decl *D) { | ||
| return BuildCXXReflectExpr(OpLoc, ArgLoc, D); |
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.
| SourceLocation ArgLoc, Decl *D) { | |
| return BuildCXXReflectExpr(OpLoc, ArgLoc, D); | |
| SourceLocation OperandLoc, Decl *D) { | |
| return BuildCXXReflectExpr(OpLoc, OperandLoc, D); |
|
|
||
| // Not supported yet. | ||
| (void)^^a; // expected-error {{expected reflectable entity}} | ||
| (void)^^a::; // expected-error {{expected reflectable entity}} |
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.
@katzdm, it is unclear to me (given the specific scope for the current PR) whether this will simply become undiagnosed in the future (and treated the same as ^^a).
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.
This implementation is based on the fork of @katzdm.
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.