If a destructor is referenced or a pseudo-destructor expression is
formed without a trailing '(', diagnose the error (these expressions must be immediately called), emit a fix-it hint, and fix the code. llvm-svn: 81015
This commit is contained in:
parent
5a522353c3
commit
bddb73fa1d
|
@ -1596,7 +1596,10 @@ def err_pseudo_dtor_type_mismatch : Error<
|
|||
"(%1) in pseudo-destructor expression">;
|
||||
def err_pseudo_dtor_call_with_args : Error<
|
||||
"call to pseudo-destructor cannot have any arguments">;
|
||||
|
||||
def err_dtor_expr_without_call : Error<
|
||||
"%select{destructor reference|pseudo-destructor expression}0 must be "
|
||||
"called immediately with '()'">;
|
||||
|
||||
def err_invalid_use_of_function_type : Error<
|
||||
"a function type is not allowed here">;
|
||||
def err_invalid_use_of_array_type : Error<"an array type is not allowed here">;
|
||||
|
|
|
@ -1320,7 +1320,8 @@ public:
|
|||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
IdentifierInfo *ClassName,
|
||||
const CXXScopeSpec *SS = 0) {
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,3 +32,9 @@ void f(A* a, Foo *f, int *i) {
|
|||
|
||||
f->::~Bar(17, 42); // expected-error{{cannot have any arguments}}
|
||||
}
|
||||
|
||||
typedef int Integer;
|
||||
|
||||
void destroy_without_call(int *ip) {
|
||||
ip->~Integer; // expected-error{{called immediately}}
|
||||
}
|
Loading…
Reference in New Issue