diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-02-25 17:36:15 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-02-25 17:36:15 +0000 |
commit | ced8bdf74a4f2b67b060588a08af8e7dbb684b36 (patch) | |
tree | be41948058ac4ea75c795c6f95e146e5ea0f711b /clang/lib/Sema | |
parent | 6cd04ac9637508e996c12c88241cba18d3725cc3 (diff) | |
download | bcm5719-llvm-ced8bdf74a4f2b67b060588a08af8e7dbb684b36.tar.gz bcm5719-llvm-ced8bdf74a4f2b67b060588a08af8e7dbb684b36.zip |
Sema: Parenthesized bound destructor member expressions can be called
We would wrongfully reject (a.~A)() in both the destructor and
pseudo-destructor cases.
This fixes PR22668.
llvm-svn: 230512
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprMember.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaPseudoObject.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 8 |
7 files changed, 32 insertions, 59 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 409a1b6ebd5..bdaba9a7ce9 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -184,7 +184,7 @@ static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { return true; } - QualType ReturnTy = CE->getCallReturnType(); + QualType ReturnTy = CE->getCallReturnType(S.Context); QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() }; QualType BuiltinTy = S.Context.getFunctionType( ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo()); @@ -6860,7 +6860,7 @@ static bool CheckForReference(Sema &SemaRef, const Expr *E, if (!M->getMemberDecl()->getType()->isReferenceType()) return false; } else if (const CallExpr *Call = dyn_cast<CallExpr>(E)) { - if (!Call->getCallReturnType()->isReferenceType()) + if (!Call->getCallReturnType(SemaRef.Context)->isReferenceType()) return false; FD = Call->getDirectCallee(); } else { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1b2af7d0133..3725b2d1f3c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13966,7 +13966,17 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { // Bound member functions. case BuiltinType::BoundMember: { ExprResult result = E; - tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function), + const Expr *BME = E->IgnoreParens(); + PartialDiagnostic PD = PDiag(diag::err_bound_member_function); + // Try to give a nicer diagnostic if it is a bound member that we recognize. + if (isa<CXXPseudoDestructorExpr>(BME)) { + PD = PDiag(diag::err_dtor_expr_without_call) << /*pseudo-destructor*/ 1; + } else if (const auto *ME = dyn_cast<MemberExpr>(BME)) { + if (ME->getMemberNameInfo().getName().getNameKind() == + DeclarationName::CXXDestructorName) + PD = PDiag(diag::err_dtor_expr_without_call) << /*destructor*/ 0; + } + tryToRecoverWithCall(result, PD, /*complain*/ true); return result; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 0a6b0c85458..d24a653b348 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5164,7 +5164,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { if (Call == TopCall) continue; - if (CheckCallReturnType(Call->getCallReturnType(), + if (CheckCallReturnType(Call->getCallReturnType(Context), Call->getLocStart(), Call, Call->getDirectCallee())) return ExprError(); @@ -5365,20 +5365,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, return Base; } -ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, - Expr *MemExpr) { - SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc); - Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call) - << isa<CXXPseudoDestructorExpr>(MemExpr) - << FixItHint::CreateInsertion(ExpectedLParenLoc, "()"); - - return ActOnCallExpr(/*Scope*/ nullptr, - MemExpr, - /*LPLoc*/ ExpectedLParenLoc, - None, - /*RPLoc*/ ExpectedLParenLoc); -} - static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, tok::TokenKind& OpKind, SourceLocation OpLoc) { if (Base->hasPlaceholderType()) { @@ -5419,8 +5405,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, TypeSourceInfo *ScopeTypeInfo, SourceLocation CCLoc, SourceLocation TildeLoc, - PseudoDestructorTypeStorage Destructed, - bool HasTrailingLParen) { + PseudoDestructorTypeStorage Destructed) { TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); QualType ObjectType; @@ -5508,10 +5493,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, TildeLoc, Destructed); - if (HasTrailingLParen) - return Result; - - return DiagnoseDtorReference(Destructed.getLocation(), Result); + return Result; } ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, @@ -5521,8 +5503,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, UnqualifiedId &FirstTypeName, SourceLocation CCLoc, SourceLocation TildeLoc, - UnqualifiedId &SecondTypeName, - bool HasTrailingLParen) { + UnqualifiedId &SecondTypeName) { assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) && "Invalid first type name in pseudo-destructor"); @@ -5649,15 +5630,14 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS, ScopeTypeInfo, CCLoc, TildeLoc, - Destructed, HasTrailingLParen); + Destructed); } ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation TildeLoc, - const DeclSpec& DS, - bool HasTrailingLParen) { + const DeclSpec& DS) { QualType ObjectType; if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) return ExprError(); @@ -5673,7 +5653,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(), nullptr, SourceLocation(), TildeLoc, - Destructed, HasTrailingLParen); + Destructed); } ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index af1cf904611..002c823e3a8 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -969,8 +969,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, CXXScopeSpec TempSS(SS); RetryExpr = ActOnMemberAccessExpr( ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS, - TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl, - ExtraArgs->HasTrailingLParen); + TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl); } if (Trap.hasErrorOccurred()) RetryExpr = ExprError(); @@ -1591,9 +1590,6 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, /// possibilities, including destructor and operator references. /// /// \param OpKind either tok::arrow or tok::period -/// \param HasTrailingLParen whether the next token is '(', which -/// is used to diagnose mis-uses of special members that can -/// only be called /// \param ObjCImpDecl the current Objective-C \@implementation /// decl; this is an ugly hack around the fact that Objective-C /// \@implementations aren't properly put in the context chain @@ -1603,24 +1599,10 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, - Decl *ObjCImpDecl, - bool HasTrailingLParen) { + Decl *ObjCImpDecl) { if (SS.isSet() && SS.isInvalid()) return ExprError(); - // The only way a reference to a destructor can be used is to - // immediately call it. If the next token is not a '(', produce - // a diagnostic and build the call now. - if (!HasTrailingLParen && - Id.getKind() == UnqualifiedId::IK_DestructorName) { - ExprResult DtorAccess = - ActOnMemberAccessExpr(S, Base, OpLoc, OpKind, SS, TemplateKWLoc, Id, - ObjCImpDecl, /*HasTrailingLParen*/true); - if (DtorAccess.isInvalid()) - return DtorAccess; - return DiagnoseDtorReference(Id.getLocStart(), DtorAccess.get()); - } - // Warn about the explicit constructor calls Microsoft extension. if (getLangOpts().MicrosoftExt && Id.getKind() == UnqualifiedId::IK_ConstructorName) @@ -1653,8 +1635,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, NameInfo, TemplateArgs); } - ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl, - HasTrailingLParen}; + ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl}; return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs, &ExtraArgs); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 65ee2f59472..664b6a48482 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -11595,6 +11595,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, return MaybeBindToTemporary(call); } + if (isa<CXXPseudoDestructorExpr>(NakedMemExpr)) + return new (Context) + CallExpr(Context, MemExprE, Args, Context.VoidTy, VK_RValue, RParenLoc); + UnbridgedCastsSet UnbridgedCasts; if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) return ExprError(); diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index 89fb76cfceb..935128b7ecd 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -1442,7 +1442,7 @@ ExprResult MSPropertyOpBuilder::buildGet() { ExprResult GetterExpr = S.ActOnMemberAccessExpr( S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), - GetterName, nullptr, true); + GetterName, nullptr); if (GetterExpr.isInvalid()) { S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_accessor) << 0 /* getter */ @@ -1472,7 +1472,7 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, ExprResult SetterExpr = S.ActOnMemberAccessExpr( S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), - SetterName, nullptr, true); + SetterName, nullptr); if (SetterExpr.isInvalid()) { S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_accessor) << 1 /* setter */ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8cbc75a7ce1..e1d0d18dde4 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -10727,11 +10727,9 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, !BaseType->getAs<PointerType>()->getPointeeType() ->template getAs<RecordType>())){ // This pseudo-destructor expression is still a pseudo-destructor. - return SemaRef.BuildPseudoDestructorExpr(Base, OperatorLoc, - isArrow? tok::arrow : tok::period, - SS, ScopeType, CCLoc, TildeLoc, - Destroyed, - /*FIXME?*/true); + return SemaRef.BuildPseudoDestructorExpr( + Base, OperatorLoc, isArrow ? tok::arrow : tok::period, SS, ScopeType, + CCLoc, TildeLoc, Destroyed); } TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo(); |