]> granicus.if.org Git - clang/commitdiff
Teach CXXRecordDecl::hasIrrelevantDestructor to check the base classes and
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 25 Feb 2012 07:33:38 +0000 (07:33 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 25 Feb 2012 07:33:38 +0000 (07:33 +0000)
data members for deleted or user-provided destructors.

Now it's computed in advance, serialize it, and in passing fix all the other
record DefinitionData flags whose serialization was missing.

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

include/clang/AST/DeclCXX.h
lib/AST/ASTImporter.cpp
lib/AST/DeclCXX.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp
test/PCH/cxx0x-default-delete.cpp
test/PCH/cxx11-constexpr.cpp [new file with mode: 0644]
test/SemaCXX/defaulted-private-dtor.cpp

index afb53757459248a5a360fd65e1f91f2ddc5d0618..b2773027e00406bbd789c3700253ed9b6dcf71b9 100644 (file)
@@ -469,6 +469,10 @@ class CXXRecordDecl : public RecordDecl {
     ///   type (or array thereof), each such class has a trivial destructor.
     bool HasTrivialDestructor : 1;
 
+    /// HasIrrelevantDestructor - True when this class has a destructor with no
+    /// semantic effect.
+    bool HasIrrelevantDestructor : 1;
+
     /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least
     /// one non-static data member or base class of non-literal or volatile
     /// type.
@@ -1145,9 +1149,9 @@ public:
 
   // hasIrrelevantDestructor - Whether this class has a destructor which has no
   // semantic effect. Any such destructor will be trivial, public, defaulted
-  // and not deleted.
+  // and not deleted, and will call only irrelevant destructors.
   bool hasIrrelevantDestructor() const {
-    return hasTrivialDestructor() && !hasUserDeclaredDestructor();
+    return data().HasIrrelevantDestructor;
   }
 
   // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal or
index d7e979526d6046a1efd954d449fb636290095129..a7766255d0bdaea0b1202fb24b6c60b70794e8df 100644 (file)
@@ -1849,16 +1849,29 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
     ToData.HasProtectedFields = FromData.HasProtectedFields;
     ToData.HasPublicFields = FromData.HasPublicFields;
     ToData.HasMutableFields = FromData.HasMutableFields;
+    ToData.HasOnlyCMembers = FromData.HasOnlyCMembers;
     ToData.HasTrivialDefaultConstructor = FromData.HasTrivialDefaultConstructor;
     ToData.HasConstexprNonCopyMoveConstructor
       = FromData.HasConstexprNonCopyMoveConstructor;
+    ToData.DefaultedDefaultConstructorIsConstexpr
+      = FromData.DefaultedDefaultConstructorIsConstexpr;
+    ToData.DefaultedCopyConstructorIsConstexpr
+      = FromData.DefaultedCopyConstructorIsConstexpr;
+    ToData.DefaultedMoveConstructorIsConstexpr
+      = FromData.DefaultedMoveConstructorIsConstexpr;
+    ToData.HasConstexprDefaultConstructor
+      = FromData.HasConstexprDefaultConstructor;
+    ToData.HasConstexprCopyConstructor = FromData.HasConstexprCopyConstructor;
+    ToData.HasConstexprMoveConstructor = FromData.HasConstexprMoveConstructor;
     ToData.HasTrivialCopyConstructor = FromData.HasTrivialCopyConstructor;
     ToData.HasTrivialMoveConstructor = FromData.HasTrivialMoveConstructor;
     ToData.HasTrivialCopyAssignment = FromData.HasTrivialCopyAssignment;
     ToData.HasTrivialMoveAssignment = FromData.HasTrivialMoveAssignment;
     ToData.HasTrivialDestructor = FromData.HasTrivialDestructor;
+    ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor;
     ToData.HasNonLiteralTypeFieldsOrBases
       = FromData.HasNonLiteralTypeFieldsOrBases;
+    // ComputedVisibleConversions not imported.
     ToData.UserProvidedDefaultConstructor
       = FromData.UserProvidedDefaultConstructor;
     ToData.DeclaredDefaultConstructor = FromData.DeclaredDefaultConstructor;
@@ -1870,7 +1883,8 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
     ToData.FailedImplicitMoveConstructor
       = FromData.FailedImplicitMoveConstructor;
     ToData.FailedImplicitMoveAssignment = FromData.FailedImplicitMoveAssignment;
-    
+    ToData.IsLambda = FromData.IsLambda;
+
     SmallVector<CXXBaseSpecifier *, 4> Bases;
     for (CXXRecordDecl::base_class_iterator 
                   Base1 = FromCXX->bases_begin(),
index 4dd44cbf179c4fe73ef4a526773454be43813ec5..89a6661cbf6816349fbe7078d99634aba301c040 100644 (file)
@@ -52,6 +52,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
     HasConstexprMoveConstructor(false), HasTrivialCopyConstructor(true),
     HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
     HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
+    HasIrrelevantDestructor(true),
     HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
     UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false),
     DeclaredCopyConstructor(false), DeclaredMoveConstructor(false),
@@ -284,7 +285,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
     //   have trivial destructors.
     if (!BaseClassDecl->hasTrivialDestructor())
       data().HasTrivialDestructor = false;
-    
+
+    if (!BaseClassDecl->hasIrrelevantDestructor())
+      data().HasIrrelevantDestructor = false;
+
     // A class has an Objective-C object member if... or any of its bases
     // has an Objective-C object member.
     if (BaseClassDecl->hasObjectMember())
@@ -648,7 +652,8 @@ NotASpecialMember:;
   if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) {
     data().DeclaredDestructor = true;
     data().UserDeclaredDestructor = true;
-    
+    data().HasIrrelevantDestructor = false;
+
     // C++ [class]p4: 
     //   A POD-struct is an aggregate class that has [...] no user-defined 
     //   destructor.
@@ -865,6 +870,8 @@ NotASpecialMember:;
 
         if (!FieldRec->hasTrivialDestructor())
           data().HasTrivialDestructor = false;
+        if (!FieldRec->hasIrrelevantDestructor())
+          data().HasIrrelevantDestructor = false;
         if (FieldRec->hasObjectMember())
           setHasObjectMember(true);
 
@@ -1248,6 +1255,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
     Data.HasTrivialCopyConstructor = false;
     Data.HasTrivialCopyAssignment = false;
     Data.HasTrivialDestructor = false;
+    Data.HasIrrelevantDestructor = false;
   }
   
   // If the class may be abstract (but hasn't been marked as such), check for
index ce92e9cab49050178f50ce4544b5198b30e3f3bd..f79c2f51b7e8b2e4fbeb61df6501d4e334c51831 100644 (file)
@@ -1072,13 +1072,21 @@ void ASTDeclReader::ReadCXXDefinitionData(
   Data.HasProtectedFields = Record[Idx++];
   Data.HasPublicFields = Record[Idx++];
   Data.HasMutableFields = Record[Idx++];
+  Data.HasOnlyCMembers = Record[Idx++];
   Data.HasTrivialDefaultConstructor = Record[Idx++];
   Data.HasConstexprNonCopyMoveConstructor = Record[Idx++];
+  Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++];
+  Data.DefaultedCopyConstructorIsConstexpr = Record[Idx++];
+  Data.DefaultedMoveConstructorIsConstexpr = Record[Idx++];
+  Data.HasConstexprDefaultConstructor = Record[Idx++];
+  Data.HasConstexprCopyConstructor = Record[Idx++];
+  Data.HasConstexprMoveConstructor = Record[Idx++];
   Data.HasTrivialCopyConstructor = Record[Idx++];
   Data.HasTrivialMoveConstructor = Record[Idx++];
   Data.HasTrivialCopyAssignment = Record[Idx++];
   Data.HasTrivialMoveAssignment = Record[Idx++];
   Data.HasTrivialDestructor = Record[Idx++];
+  Data.HasIrrelevantDestructor = Record[Idx++];
   Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
   Data.ComputedVisibleConversions = Record[Idx++];
   Data.UserProvidedDefaultConstructor = Record[Idx++];
index f626f0b7e03cad8d799a3ce2983a6d1c5ef8e151..f497a038b37b76b7720b4b20f024bb1b74545b33 100644 (file)
@@ -4296,13 +4296,21 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
   Record.push_back(Data.HasProtectedFields);
   Record.push_back(Data.HasPublicFields);
   Record.push_back(Data.HasMutableFields);
+  Record.push_back(Data.HasOnlyCMembers);
   Record.push_back(Data.HasTrivialDefaultConstructor);
   Record.push_back(Data.HasConstexprNonCopyMoveConstructor);
+  Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr);
+  Record.push_back(Data.DefaultedCopyConstructorIsConstexpr);
+  Record.push_back(Data.DefaultedMoveConstructorIsConstexpr);
+  Record.push_back(Data.HasConstexprDefaultConstructor);
+  Record.push_back(Data.HasConstexprCopyConstructor);
+  Record.push_back(Data.HasConstexprMoveConstructor);
   Record.push_back(Data.HasTrivialCopyConstructor);
   Record.push_back(Data.HasTrivialMoveConstructor);
   Record.push_back(Data.HasTrivialCopyAssignment);
   Record.push_back(Data.HasTrivialMoveAssignment);
   Record.push_back(Data.HasTrivialDestructor);
+  Record.push_back(Data.HasIrrelevantDestructor);
   Record.push_back(Data.HasNonLiteralTypeFieldsOrBases);
   Record.push_back(Data.ComputedVisibleConversions);
   Record.push_back(Data.UserProvidedDefaultConstructor);
@@ -4314,6 +4322,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
   Record.push_back(Data.DeclaredDestructor);
   Record.push_back(Data.FailedImplicitMoveConstructor);
   Record.push_back(Data.FailedImplicitMoveAssignment);
+  // IsLambda bit is already saved.
 
   Record.push_back(Data.NumBases);
   if (Data.NumBases > 0)
index 3ecb19c29572cd415bc6ff36082409eb3940806f..6eb65d61df42a73a2adf0214a6083f90adbd3dfe 100644 (file)
@@ -12,6 +12,14 @@ struct foo {
   void bar() = delete; // expected-note{{deleted here}}
 };
 
+struct baz {
+  ~baz() = delete; // expected-note{{deleted here}}
+};
+
+class quux {
+  ~quux() = default; // expected-note{{private here}}
+};
+
 #else
 
 foo::foo() { } // expected-error{{definition of explicitly defaulted default constructor}}
@@ -20,4 +28,7 @@ void fn() {
   f.bar(); // expected-error{{deleted function}}
 }
 
+baz bz; // expected-error{{deleted function}}
+quux qx; // expected-error{{private destructor}}
+
 #endif
diff --git a/test/PCH/cxx11-constexpr.cpp b/test/PCH/cxx11-constexpr.cpp
new file mode 100644 (file)
index 0000000..338543e
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t
+// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s
+
+#ifndef HEADER_INCLUDED
+
+#define HEADER_INCLUDED
+
+struct B {
+  B(); // expected-note {{here}}
+  constexpr B(char) {}
+};
+
+struct C { // expected-note {{not an aggregate and has no constexpr constructors}}
+  B b;
+  double d = 0.0;
+};
+
+struct D : B {
+  constexpr D(int n) : B('x'), k(2*n+1) {}
+  int k;
+};
+
+#else
+
+static_assert(D(4).k == 9, "");
+constexpr int f(C c) { return 0; } // expected-error {{not a literal type}}
+constexpr B b; // expected-error {{constant expression}} expected-note {{non-constexpr}}
+
+#endif
index a15bdde60c92ec8da536ab0b7a68ca34f6acc89d..a4b868c0ad5a7f5414a73dd0cbbc5dab6fb7bc8e 100644 (file)
@@ -2,7 +2,7 @@
 
 class BadDtor {
   // A private, but nonetheless trivial, destructor.
-  ~BadDtor() = default; // expected-note 9{{here}}
+  ~BadDtor() = default; // expected-note 11{{here}}
   friend class K;
 };
 void f() {
@@ -12,6 +12,15 @@ void f() {
   BadDtor dd; // expected-error {{private destructor}}
   throw dd; // expected-error {{private destructor}}
 }
+struct V { // expected-note {{here}}
+  V();
+  BadDtor bd; // expected-error {{private destructor}}
+};
+V v; // expected-error {{deleted function}} expected-note {{required here}}
+struct W : BadDtor { // expected-note {{here}} expected-error {{private destructor}}
+  W();
+};
+W w; // expected-error {{deleted function}} expected-note {{required here}}
 struct X : BadDtor { // expected-error {{private destructor}}
   ~X() {}
 };