]> granicus.if.org Git - clang/commitdiff
If a destructor is referenced or a pseudo-destructor expression is
authorDouglas Gregor <dgregor@apple.com>
Fri, 4 Sep 2009 18:29:40 +0000 (18:29 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 4 Sep 2009 18:29:40 +0000 (18:29 +0000)
formed without a trailing '(', diagnose the error (these expressions
must be immediately called), emit a fix-it hint, and fix the code.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81015 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Parse/Action.h
lib/Parse/ParseExpr.cpp
lib/Sema/Sema.h
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/pseudo-destructors.cpp

index 35d91f7ad0c2ced3455f6398b4eaac747b3105aa..ddb82f4319bd95712ab9352df26cc990f44dff64 100644 (file)
@@ -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">;
index c7fde9c2cc634c36a01f2978d6bfef93924137f0..2a47e7b8aaa4f74dba3f658521254faf1be8300b 100644 (file)
@@ -1320,7 +1320,8 @@ public:
                                tok::TokenKind OpKind,
                                SourceLocation ClassNameLoc,
                                IdentifierInfo *ClassName,
-                               const CXXScopeSpec *SS = 0) {
+                               const CXXScopeSpec &SS,
+                               bool HasTrailingLParen) {
     return ExprEmpty();
   }
 
index 8fca14ff98989a6a4d928525d2b7b49470e05b89..da923c489d4c825a4a410791657a4519e24a020c 100644 (file)
@@ -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
index 78e71bcab8ef5137f3591ea772c5f052890ed3fe..d088387b05570e50c42ac4c0c172e9f7cd28da16 100644 (file)
@@ -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,
index 4d49f87a9a830c76c64bbd74138926e5248023e9..99d80944baa96091b1cbe206b652c989688ccbfe 100644 (file)
@@ -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
index f1fa331aa2434a98a79de79ecdde5e2ba3eb35b5..1f05e81df5306eb046dc109f45ee8d45f4d1bb45 100644 (file)
@@ -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