[cfe-commits] r150866 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/defaulted-private-dtor.cpp test/SemaCXX/deleted-function.cpp

Richard Smith richard-llvm at metafoo.co.uk
Fri Feb 17 20:13:32 PST 2012


Author: rsmith
Date: Fri Feb 17 22:13:32 2012
New Revision: 150866

URL: http://llvm.org/viewvc/llvm-project?rev=150866&view=rev
Log:
Diagnose uses of deleted destructors and inaccessible defaulted destructors.

We had two separate issues here: firstly, varions functions were assuming that
they did not need to perform semantic checks on trivial destructors (this is
not true in C++11, where a trivial destructor can nonetheless be private or
deleted), and a bunch of DiagnoseUseOfDecl calls were missing for uses of
destructors.

Added:
    cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/deleted-function.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=150866&r1=150865&r2=150866&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Feb 17 22:13:32 2012
@@ -1122,6 +1122,13 @@
   // (C++ [class.dtor]p3)
   bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
 
+  // hasIrrelevantDestructor - Whether this class has a destructor which has no
+  // semantic effect. Any such destructor will be trivial, public, defaulted
+  // and not deleted.
+  bool hasIrrelevantDestructor() const {
+    return hasTrivialDestructor() && !hasUserDeclaredDestructor();
+  }
+
   // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal or
   // volatile type non-static data member or base class.
   bool hasNonLiteralTypeFieldsOrBases() const {

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=150866&r1=150865&r2=150866&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Feb 17 22:13:32 2012
@@ -3282,7 +3282,7 @@
     CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
     if (FieldClassDecl->isInvalidDecl())
       continue;
-    if (FieldClassDecl->hasTrivialDestructor())
+    if (FieldClassDecl->hasIrrelevantDestructor())
       continue;
 
     CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
@@ -3293,6 +3293,7 @@
                             << FieldType);
 
     MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+    DiagnoseUseOfDecl(Dtor, Location);
   }
 
   llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;
@@ -3311,8 +3312,7 @@
     // If our base class is invalid, we probably can't get its dtor anyway.
     if (BaseClassDecl->isInvalidDecl())
       continue;
-    // Ignore trivial destructors.
-    if (BaseClassDecl->hasTrivialDestructor())
+    if (BaseClassDecl->hasIrrelevantDestructor())
       continue;
 
     CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
@@ -3325,6 +3325,7 @@
                             << Base->getSourceRange());
     
     MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+    DiagnoseUseOfDecl(Dtor, Location);
   }
   
   // Virtual bases.
@@ -3342,8 +3343,7 @@
     // If our base class is invalid, we probably can't get its dtor anyway.
     if (BaseClassDecl->isInvalidDecl())
       continue;
-    // Ignore trivial destructors.
-    if (BaseClassDecl->hasTrivialDestructor())
+    if (BaseClassDecl->hasIrrelevantDestructor())
       continue;
 
     CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
@@ -3353,6 +3353,7 @@
                             << VBase->getType());
 
     MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+    DiagnoseUseOfDecl(Dtor, Location);
   }
 }
 
@@ -8918,7 +8919,7 @@
 
   CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
   if (ClassDecl->isInvalidDecl()) return;
-  if (ClassDecl->hasTrivialDestructor()) return;
+  if (ClassDecl->hasIrrelevantDestructor()) return;
   if (ClassDecl->isDependentContext()) return;
 
   CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
@@ -8927,6 +8928,7 @@
                         PDiag(diag::err_access_dtor_var)
                         << VD->getDeclName()
                         << VD->getType());
+  DiagnoseUseOfDecl(Destructor, VD->getLocation());
 
   if (!VD->hasGlobalStorage()) return;
 

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=150866&r1=150865&r2=150866&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Feb 17 22:13:32 2012
@@ -637,8 +637,8 @@
   if (isPointer)
     return Owned(E);
 
-  // If the class has a non-trivial destructor, we must be able to call it.
-  if (RD->hasTrivialDestructor())
+  // If the class has a destructor, we must be able to call it.
+  if (RD->hasIrrelevantDestructor())
     return Owned(E);
 
   CXXDestructorDecl *Destructor
@@ -649,6 +649,7 @@
   MarkFunctionReferenced(E->getExprLoc(), Destructor);
   CheckDestructorAccess(E->getExprLoc(), Destructor,
                         PDiag(diag::err_access_dtor_exception) << Ty);
+  DiagnoseUseOfDecl(Destructor, E->getExprLoc());
   return Owned(E);
 }
 
@@ -1318,6 +1319,7 @@
       CheckDestructorAccess(StartLoc, dtor, 
                             PDiag(diag::err_access_dtor)
                               << Context.getBaseElementType(AllocType));
+      DiagnoseUseOfDecl(dtor, StartLoc);
     }
   }
 
@@ -2064,7 +2066,7 @@
           UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2);
       }
 
-      if (!PointeeRD->hasTrivialDestructor())
+      if (!PointeeRD->hasIrrelevantDestructor())
         if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
           MarkFunctionReferenced(StartLoc,
                                     const_cast<CXXDestructorDecl*>(Dtor));
@@ -4309,23 +4311,28 @@
   }
 
   // That should be enough to guarantee that this type is complete.
-  // If it has a trivial destructor, we can avoid the extra copy.
   CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-  if (RD->isInvalidDecl() || RD->hasTrivialDestructor())
+  if (RD->isInvalidDecl() || RD->isDependentContext())
     return Owned(E);
-
   CXXDestructorDecl *Destructor = LookupDestructor(RD);
 
-  CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor);
   if (Destructor) {
     MarkFunctionReferenced(E->getExprLoc(), Destructor);
     CheckDestructorAccess(E->getExprLoc(), Destructor,
                           PDiag(diag::err_access_dtor_temp)
                             << E->getType());
+    DiagnoseUseOfDecl(Destructor, E->getExprLoc());
+  }
+
+  // If destructor is trivial, we can avoid the extra copy.
+  if (Destructor->isTrivial())
+    return Owned(E);
 
+  if (Destructor)
     // We need a cleanup, but we don't need to remember the temporary.
     ExprNeedsCleanups = true;
-  }
+
+  CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor);
   return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E));
 }
 

Added: cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp?rev=150866&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp (added)
+++ cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp Fri Feb 17 22:13:32 2012
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s -fcxx-exceptions
+
+class BadDtor {
+  // A private, but nonetheless trivial, destructor.
+  ~BadDtor() = default; // expected-note 9{{here}}
+  friend class K;
+};
+void f() {
+  BadDtor *p = new BadDtor[3]; // expected-error {{private destructor}}
+  delete [] p; // expected-error {{private destructor}}
+  const BadDtor &dd2 = BadDtor(); // expected-error {{private destructor}}
+  BadDtor dd; // expected-error {{private destructor}}
+  throw dd; // expected-error {{private destructor}}
+}
+struct X : BadDtor { // expected-error {{private destructor}}
+  ~X() {}
+};
+struct Y {
+  BadDtor dd; // expected-error {{private destructor}}
+  ~Y() {}
+};
+struct Z : virtual BadDtor { // expected-error {{private destructor}}
+  ~Z() {}
+};
+BadDtor dd; // expected-error {{private destructor}}
+
+class K : BadDtor {
+  void f() {
+    BadDtor *p = new BadDtor[3];
+    delete [] p;
+    const BadDtor &dd2 = BadDtor();
+    BadDtor dd;
+    throw dd;
+
+    {
+      BadDtor x;
+      goto dont_call_dtor;
+    }
+dont_call_dtor:
+    ;
+  }
+  struct Z : virtual BadDtor {
+    ~Z() {}
+  };
+  BadDtor dd;
+  ~K();
+};

Modified: cfe/trunk/test/SemaCXX/deleted-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/deleted-function.cpp?rev=150866&r1=150865&r2=150866&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/deleted-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/deleted-function.cpp Fri Feb 17 22:13:32 2012
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s
 
 int i = delete; // expected-error {{only functions can have deleted definitions}}
 
@@ -33,3 +33,25 @@
   d->fn(); // expected-error {{attempt to use a deleted function}}
   int i = *d; // expected-error {{invokes a deleted function}}
 }
+
+struct DelDtor {
+  ~DelDtor() = delete; // expected-note 9{{here}}
+};
+void f() {
+  DelDtor *p = new DelDtor[3]; // expected-error {{attempt to use a deleted function}}
+  delete [] p; // expected-error {{attempt to use a deleted function}}
+  const DelDtor &dd2 = DelDtor(); // expected-error {{attempt to use a deleted function}}
+  DelDtor dd; // expected-error {{attempt to use a deleted function}}
+  throw dd; // expected-error {{attempt to use a deleted function}}
+}
+struct X : DelDtor {
+  ~X() {} // expected-error {{attempt to use a deleted function}}
+};
+struct Y {
+  DelDtor dd;
+  ~Y() {} // expected-error {{attempt to use a deleted function}}
+};
+struct Z : virtual DelDtor {
+  ~Z() {} // expected-error {{attempt to use a deleted function}}
+};
+DelDtor dd; // expected-error {{attempt to use a deleted function}}





More information about the cfe-commits mailing list