diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-04 18:29:40 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-04 18:29:40 +0000 |
commit | bddb73fa1df420fd9e86d005e1782ed343a3154b (patch) | |
tree | 63e2cb58849c59c9f6e39197dfe25da1af5e323f /clang | |
parent | 5a522353c3bce98d39d91823ac7e1c8950100db7 (diff) | |
download | bcm5719-llvm-bddb73fa1df420fd9e86d005e1782ed343a3154b.tar.gz bcm5719-llvm-bddb73fa1df420fd9e86d005e1782ed343a3154b.zip |
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
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 | ||||
-rw-r--r-- | clang/include/clang/Parse/Action.h | 3 | ||||
-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 | ||||
-rw-r--r-- | clang/test/SemaCXX/pseudo-destructors.cpp | 6 |
6 files changed, 39 insertions, 11 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 35d91f7ad0c..ddb82f4319b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index c7fde9c2cc6..2a47e7b8aaa 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -1320,7 +1320,8 @@ public: tok::TokenKind OpKind, SourceLocation ClassNameLoc, IdentifierInfo *ClassName, - const CXXScopeSpec *SS = 0) { + const CXXScopeSpec &SS, + bool HasTrailingLParen) { return ExprEmpty(); } 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 diff --git a/clang/test/SemaCXX/pseudo-destructors.cpp b/clang/test/SemaCXX/pseudo-destructors.cpp index f1fa331aa24..1f05e81df53 100644 --- a/clang/test/SemaCXX/pseudo-destructors.cpp +++ b/clang/test/SemaCXX/pseudo-destructors.cpp @@ -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}} +}
\ No newline at end of file |