diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 007ea380e51088..3d856cfa9947a3 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -5592,20 +5592,26 @@ class CXXExprSpliceExpr : public Expr { SourceLocation LSpliceLoc; Expr *Operand; SourceLocation RSpliceLoc; + bool AllowMemberReference; CXXExprSpliceExpr(QualType ResultTy, ExprValueKind ValueKind, SourceLocation LSpliceLoc, Expr *Operand, - SourceLocation RSpliceLoc); + SourceLocation RSpliceLoc, bool AllowMemberReference); public: static CXXExprSpliceExpr *Create(ASTContext &C, ExprValueKind ValueKind, SourceLocation LSpliceLoc, Expr *Operand, - SourceLocation RpliceLoc); + SourceLocation RSpliceLoc, + bool AllowMemberReference); Expr *getOperand() const { return Operand; } + bool allowMemberReference() const { + return AllowMemberReference; + } + SourceLocation getLSpliceLoc() const { return LSpliceLoc; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index fb2baed51f2be8..90b2094bc10c10 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3109,6 +3109,10 @@ def err_unsupported_splice_kind : Error< "%select{supported|implemented}2">; def err_using_dependent_namespace : Error< "dependent namespaces cannot appear in a using directive">; +def err_dependent_splice_implicit_member_reference : Error< + "cannot implicitly reference a class member through a splice">; +def note_dependent_splice_explicit_this_may_fix : Note< + "an explicit 'this' pointer may fix the problem">; // C++11 char16_t/char32_t def warn_cxx98_compat_unicode_type : Warning< diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ba91fd38386165..6248ebb30b7301 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3800,7 +3800,7 @@ class Parser : public CodeCompletionHandler { bool ParseCXXIndeterminateSplice(); TypeResult ParseCXXSpliceAsType(bool AllowDependent, bool Complain); - ExprResult ParseCXXSpliceAsExpr(); + ExprResult ParseCXXSpliceAsExpr(bool AllowMemberReference); DeclResult ParseCXXSpliceAsNamespace(); //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 12359e0049ee74..f146358f5edb85 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -14865,7 +14865,8 @@ class Sema final { bool Complain); ExprResult ActOnCXXSpliceExpectingExpr(SourceLocation LSplice, Expr *Operand, - SourceLocation RSplice); + SourceLocation RSplice, + bool AllowMemberReference); DeclResult ActOnCXXSpliceExpectingNamespace(SourceLocation LSplice, Expr *Operand, SourceLocation RSplice); @@ -14911,9 +14912,9 @@ class Sema final { SourceLocation LSpliceLoc, Expr *E, SourceLocation RSpliceLoc, bool Complain); - ExprResult BuildReflectionSpliceExpr(SourceLocation LSplice, - Expr *Operand, - SourceLocation RSplice); + ExprResult BuildReflectionSpliceExpr(SourceLocation LSplice, Expr *Operand, + SourceLocation RSplice, + bool AllowMemberReference); DeclResult BuildReflectionSpliceNamespace(SourceLocation LSplice, Expr *Operand, SourceLocation RSplice); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 93bf7e37c73f81..27ab7f0d0d13b9 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -2008,9 +2008,11 @@ CXXIndeterminateSpliceExpr *CXXIndeterminateSpliceExpr::Create( CXXExprSpliceExpr::CXXExprSpliceExpr(QualType ResultTy, ExprValueKind ValueKind, SourceLocation LSpliceLoc, Expr *Operand, - SourceLocation RSpliceLoc) + SourceLocation RSpliceLoc, + bool AllowMemberReference) : Expr(CXXExprSpliceExprClass, ResultTy, ValueKind, OK_Ordinary), - LSpliceLoc(LSpliceLoc), Operand(Operand), RSpliceLoc(RSpliceLoc) { + LSpliceLoc(LSpliceLoc), Operand(Operand), RSpliceLoc(RSpliceLoc), + AllowMemberReference(AllowMemberReference) { setDependence(computeDependence(this)); } @@ -2018,13 +2020,14 @@ CXXExprSpliceExpr *CXXExprSpliceExpr::Create(ASTContext &C, ExprValueKind ValueKind, SourceLocation LSpliceLoc, Expr *Operand, - SourceLocation RSpliceLoc) { + SourceLocation RSpliceLoc, + bool AllowMemberReference) { QualType ResultTy = Operand->getType(); if (Operand->isTypeDependent() || Operand->isValueDependent()) ResultTy = C.DependentTy; return new (C) CXXExprSpliceExpr(ResultTy, ValueKind, LSpliceLoc, Operand, - RSpliceLoc); + RSpliceLoc, AllowMemberReference); } StackLocationExpr::StackLocationExpr(QualType ResultTy, SourceRange Range, diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 453b3c586758c4..b96a0508d39b55 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1652,7 +1652,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, case tok::annot_splice: { // An 'annot_splice' was parsed by 'TryAnnotateTypeOrScopeToken', but it // could not be spliced as a type; it must be an expression. - Res = ParseCXXSpliceAsExpr(); + Res = ParseCXXSpliceAsExpr(/*AllowMemberReference=*/isAddressOfOperand); break; } @@ -2327,7 +2327,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { SourceLocation Loc = ConsumeToken(); Name.setIdentifier(Id, Loc); } else if (Tok.is(tok::annot_splice)) { - ExprResult Res = ParseCXXSpliceAsExpr(); + ExprResult Res = ParseCXXSpliceAsExpr(/*AllowMemberReference=*/true); if (!Res.isInvalid() && !Diags.hasErrorOccurred()) { LHS = Actions.ActOnMemberAccessExpr( getCurScope(), LHS.get(), OpLoc, OpKind, diff --git a/clang/lib/Parse/ParseReflect.cpp b/clang/lib/Parse/ParseReflect.cpp index a23318e6fdca7f..69e731383ef5d2 100644 --- a/clang/lib/Parse/ParseReflect.cpp +++ b/clang/lib/Parse/ParseReflect.cpp @@ -202,7 +202,7 @@ TypeResult Parser::ParseCXXSpliceAsType(bool AllowDependent, return Result; } -ExprResult Parser::ParseCXXSpliceAsExpr() { +ExprResult Parser::ParseCXXSpliceAsExpr(bool AllowMemberReference) { assert(Tok.is(tok::annot_splice) && "expected annot_splice"); Token Splice = Tok; @@ -211,7 +211,8 @@ ExprResult Parser::ParseCXXSpliceAsExpr() { assert(!ER.isInvalid()); ExprResult Result = Actions.ActOnCXXSpliceExpectingExpr( - Splice.getLocation(), ER.get(), Splice.getAnnotationEndLoc()); + Splice.getLocation(), ER.get(), Splice.getAnnotationEndLoc(), + AllowMemberReference); if (!Result.isInvalid()) ConsumeAnnotationToken(); diff --git a/clang/lib/Sema/SemaReflect.cpp b/clang/lib/Sema/SemaReflect.cpp index 90653cca413387..fbeaa5feb63883 100644 --- a/clang/lib/Sema/SemaReflect.cpp +++ b/clang/lib/Sema/SemaReflect.cpp @@ -253,8 +253,10 @@ TypeResult Sema::ActOnCXXSpliceExpectingType(SourceLocation LSpliceLoc, ExprResult Sema::ActOnCXXSpliceExpectingExpr(SourceLocation LSpliceLoc, Expr *Operand, - SourceLocation RSpliceLoc) { - return BuildReflectionSpliceExpr(LSpliceLoc, Operand, RSpliceLoc); + SourceLocation RSpliceLoc, + bool AllowMemberReference) { + return BuildReflectionSpliceExpr(LSpliceLoc, Operand, RSpliceLoc, + AllowMemberReference); } DeclResult Sema::ActOnCXXSpliceExpectingNamespace(SourceLocation LSpliceLoc, @@ -608,7 +610,8 @@ QualType Sema::BuildReflectionSpliceTypeLoc(TypeLocBuilder &TLB, ExprResult Sema::BuildReflectionSpliceExpr(SourceLocation LSplice, Expr *Operand, - SourceLocation RSplice) { + SourceLocation RSplice, + bool AllowMemberReference) { if (isa(Operand) && !Operand->isTypeDependent() && !Operand->isValueDependent()) { SmallVector Diags; @@ -630,14 +633,30 @@ ExprResult Sema::BuildReflectionSpliceExpr(SourceLocation LSplice, switch (RV.getKind()) { case ReflectionValue::RK_declaration: { + Decl *TheDecl = RV.getAsDecl(); + + // Class members may not be implicitly referenced through a splice. + if (!AllowMemberReference && + (isa(TheDecl) || + (isa(TheDecl) && + dyn_cast(TheDecl)->isInstance()))) { + Diag(Operand->getExprLoc(), + diag::err_dependent_splice_implicit_member_reference) + << Operand->getSourceRange(); + Diag(Operand->getExprLoc(), + diag::note_dependent_splice_explicit_this_may_fix); + return ExprError(); + } + // Create a new DeclRefExpr, since the operand of the reflect expression // was parsed in an unevaluated context (but a splice expression is not // necessarily, and frequently not, in such a context). - Operand = CreateRefToDecl(*this, cast(RV.getAsDecl()), + Operand = CreateRefToDecl(*this, cast(TheDecl), Operand->getExprLoc()); MarkDeclRefReferenced(cast(Operand), nullptr); Operand = CXXExprSpliceExpr::Create(Context, Operand->getValueKind(), - LSplice, Operand, RSplice); + LSplice, Operand, RSplice, + AllowMemberReference); break; } case ReflectionValue::RK_const_value: { @@ -650,7 +669,7 @@ ExprResult Sema::BuildReflectionSpliceExpr(SourceLocation LSplice, cast(Operand), 0); } Operand = CXXExprSpliceExpr::Create(Context, VK_PRValue, LSplice, Operand, - RSplice); + RSplice, AllowMemberReference); break; } case ReflectionValue::RK_template: { @@ -670,7 +689,7 @@ ExprResult Sema::BuildReflectionSpliceExpr(SourceLocation LSplice, return Operand; } return CXXExprSpliceExpr::Create(Context, Operand->getValueKind(), LSplice, - Operand, RSplice); + Operand, RSplice, AllowMemberReference); } DeclResult Sema::BuildReflectionSpliceNamespace(SourceLocation LSplice, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 03f652bf44d5f7..d9da56fa5f0eff 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -8724,7 +8724,8 @@ TreeTransform::TransformCXXExprSpliceExpr(CXXExprSpliceExpr *E) { return ExprError(); return getSema().BuildReflectionSpliceExpr(E->getLSpliceLoc(), ER.get(), - E->getRSpliceLoc()); + E->getRSpliceLoc(), + E->allowMemberReference()); } template