diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 30 |
3 files changed, 27 insertions, 9 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 8fca14ff989..da923c489d4 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -956,7 +956,8 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) { OpLoc, OpKind, Tok.getLocation(), Tok.getIdentifierInfo(), - &SS); + SS, + NextToken().is(tok::l_paren)); ConsumeToken(); } else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) { // We have a reference to a member operator, e.g., t.operator int or diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 78e71bcab8e..d088387b055 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1998,7 +1998,8 @@ public: tok::TokenKind OpKind, SourceLocation ClassNameLoc, IdentifierInfo *ClassName, - const CXXScopeSpec *SS = 0); + const CXXScopeSpec &SS, + bool HasTrailingLParen); virtual OwningExprResult ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 4d49f87a9a8..99d80944baa 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1817,16 +1817,17 @@ Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, tok::TokenKind OpKind, SourceLocation ClassNameLoc, IdentifierInfo *ClassName, - const CXXScopeSpec *SS) { - if (SS && SS->isInvalid()) + const CXXScopeSpec &SS, + bool HasTrailingLParen) { + if (SS.isInvalid()) return ExprError(); QualType BaseType; - if (SS && isUnknownSpecialization(*SS)) - BaseType = Context.getTypenameType((NestedNameSpecifier *)SS->getScopeRep(), + if (isUnknownSpecialization(SS)) + BaseType = Context.getTypenameType((NestedNameSpecifier *)SS.getScopeRep(), ClassName); else { - TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, SS); + TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, &SS); if (!BaseTy) { Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type) << ClassName; @@ -1840,8 +1841,23 @@ Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, DeclarationName DtorName = Context.DeclarationNames.getCXXDestructorName(CanBaseType); - return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc, - DtorName, DeclPtrTy(), SS); + OwningExprResult Result + = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc, + DtorName, DeclPtrTy(), &SS); + if (Result.isInvalid() || HasTrailingLParen) + return move(Result); + + // The only way a reference to a destructor can be used is to + // immediately call them. Since the next token is not a '(', produce a + // diagnostic and build the call now. + Expr *E = (Expr *)Result.get(); + SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(E->getLocEnd()); + Diag(E->getLocStart(), diag::err_dtor_expr_without_call) + << isa<CXXPseudoDestructorExpr>(E) + << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()"); + + return ActOnCallExpr(0, move(Result), ExpectedLParenLoc, + MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc); } Sema::OwningExprResult |