[cfe-commits] r69345 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/AST/ExprCXX.cpp lib/Parse/ParseExpr.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/trivial-constructor.cpp test/SemaCXX/trivial-destructor.cpp

Anders Carlsson andersca at mac.com
Thu Apr 16 19:34:55 PDT 2009


Author: andersca
Date: Thu Apr 16 21:34:54 2009
New Revision: 69345

URL: http://llvm.org/viewvc/llvm-project?rev=69345&view=rev
Log:
Add support for the __has_trivial_destructor type trait.

Added:
    cfe/trunk/test/SemaCXX/trivial-destructor.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/trivial-constructor.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=69345&r1=69344&r2=69345&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Apr 16 21:34:54 2009
@@ -228,6 +228,9 @@
   /// HasTrivialConstructor - True when this class has a trivial constructor
   bool HasTrivialConstructor : 1;
   
+  /// HasTrivialDestructor - True when this class has a trivial destructor
+  bool HasTrivialDestructor : 1;
+  
   /// Bases - Base classes of this class.
   /// FIXME: This is wasted space for a union.
   CXXBaseSpecifier *Bases;
@@ -327,7 +330,7 @@
   /// setUserDeclaredDestructor - Set whether this class has a
   /// user-declared destructor. If not set by the time the class is
   /// fully defined, a destructor will be implicitly declared.
-  void setUserDeclaredDestructor(bool UCD = true) { 
+  void setUserDeclaredDestructor(bool UCD) { 
     UserDeclaredDestructor = UCD; 
   }
 
@@ -386,6 +389,14 @@
   // (C++ [class.ctor]p5)
   void setHasTrivialConstructor(bool TC) { HasTrivialConstructor = TC; }
   
+  // hasTrivialDestructor - Whether this class has a trivial destructor
+  // (C++ [class.dtor]p3)
+  bool hasTrivialDestructor() const { return HasTrivialDestructor; }
+  
+  // setHasTrivialDestructor - Set whether this class has a trivial destructor
+  // (C++ [class.dtor]p3)
+  void setHasTrivialDestructor(bool TC) { HasTrivialDestructor = TC; }
+  
   /// \brief If this record is an instantiation of a member class,
   /// retrieves the member class from which it was instantiated.
   ///

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=69345&r1=69344&r2=69345&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Apr 16 21:34:54 2009
@@ -29,7 +29,7 @@
     UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
     UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
     Aggregate(true), PlainOldData(true), Polymorphic(false), Abstract(false),
-    HasTrivialConstructor(true),
+    HasTrivialConstructor(true), HasTrivialDestructor(true),
     Bases(0), NumBases(0), Conversions(DC, DeclarationName()),
     TemplateOrInstantiation() { }
 

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=69345&r1=69344&r2=69345&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Thu Apr 16 21:34:54 2009
@@ -173,7 +173,11 @@
   case UTT_HasTrivialConstructor:
     if (const RecordType *RT = QueriedType->getAsRecordType())
       return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor();
-   return false;
+    return false;
+  case UTT_HasTrivialDestructor:
+    if (const RecordType *RT = QueriedType->getAsRecordType())
+      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
+    return false;
   }
 }
 

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=69345&r1=69344&r2=69345&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Apr 16 21:34:54 2009
@@ -493,7 +493,7 @@
 ///                   '__has_trivial_assign'                  [TODO]
 ///                   '__has_trivial_copy'                    [TODO]
 ///                   '__has_trivial_constructor'
-///                   '__has_trivial_destructor'              [TODO]
+///                   '__has_trivial_destructor'
 ///                   '__has_virtual_destructor'              [TODO]
 ///                   '__is_abstract'                         [TODO]
 ///                   '__is_class'
@@ -783,6 +783,7 @@
   case tok::kw___is_polymorphic:
   case tok::kw___is_abstract:
   case tok::kw___has_trivial_constructor:
+  case tok::kw___has_trivial_destructor:
     return ParseUnaryTypeTrait();
 
   case tok::at: {

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=69345&r1=69344&r2=69345&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Apr 16 21:34:54 2009
@@ -2251,6 +2251,10 @@
       // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
       // user-defined destructor.
       Record->setPOD(false);
+      
+      // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly-
+      // declared destructor.
+      Record->setHasTrivialDestructor(false);
     } else if (CXXConversionDecl *Conversion 
                = dyn_cast<CXXConversionDecl>(NewFD))
       ActOnConversionDeclarator(Conversion);

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=69345&r1=69344&r2=69345&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Apr 16 21:34:54 2009
@@ -380,6 +380,12 @@
     Class->setHasTrivialConstructor(cast<CXXRecordDecl>(BaseDecl)->
                                     hasTrivialConstructor());
   }
+
+  // C++ [class.ctor]p3:
+  //   A destructor is trivial if all the direct base classes of its class
+  //   have trivial destructors.
+  Class->setHasTrivialDestructor(cast<CXXRecordDecl>(BaseDecl)->
+                                 hasTrivialDestructor());
   
   // Create the base specifier.
   // FIXME: Allocate via ASTContext?
@@ -952,7 +958,7 @@
   if (RD->isAbstract()) 
     AbstractClassUsageDiagnoser(*this, RD);
     
-  if (RD->hasTrivialConstructor()) {
+  if (RD->hasTrivialConstructor() || RD->hasTrivialDestructor()) {
     for (RecordDecl::field_iterator i = RD->field_begin(Context), 
          e = RD->field_end(Context); i != e; ++i) {
       // All the nonstatic data members must have trivial constructors.
@@ -962,10 +968,16 @@
       
       if (const RecordType *RT = FTy->getAsRecordType()) {
         CXXRecordDecl *FieldRD = cast<CXXRecordDecl>(RT->getDecl());
-        if (!FieldRD->hasTrivialConstructor()) {
+        
+        if (!FieldRD->hasTrivialConstructor())
           RD->setHasTrivialConstructor(false);
+        if (!FieldRD->hasTrivialDestructor())
+          RD->setHasTrivialDestructor(false);
+        
+        // If RD has neither a trivial constructor nor a trivial destructor
+        // we don't need to continue checking.
+        if (!RD->hasTrivialConstructor() && !RD->hasTrivialDestructor())
           break;
-        }
       }
     }
   }

Modified: cfe/trunk/test/SemaCXX/trivial-constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/trivial-constructor.cpp?rev=69345&r1=69344&r2=69345&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/trivial-constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/trivial-constructor.cpp Thu Apr 16 21:34:54 2009
@@ -32,3 +32,7 @@
   T4 t4;
 };
 static_assert(!__has_trivial_constructor(T7), "t4 does not have a trivial constructor!");
+
+struct T8 : T2 {
+};
+static_assert(!__has_trivial_constructor(T8), "The base class T2 does not have a trivial constructor!");

Added: cfe/trunk/test/SemaCXX/trivial-destructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/trivial-destructor.cpp?rev=69345&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/trivial-destructor.cpp (added)
+++ cfe/trunk/test/SemaCXX/trivial-destructor.cpp Thu Apr 16 21:34:54 2009
@@ -0,0 +1,38 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+struct T1 {
+};
+static_assert(__has_trivial_destructor(T1), "T1 has trivial destructor!");
+
+struct T2 {
+  ~T2();
+};
+static_assert(!__has_trivial_destructor(T2), "T2 has a user-declared destructor!");
+
+struct T3 {
+  virtual void f();
+};
+static_assert(__has_trivial_destructor(T3), "T3 has a virtual function (but still a trivial destructor)!");
+
+struct T4 : virtual T3 {
+};
+static_assert(__has_trivial_destructor(T4), "T4 has a virtual base class! (but still a trivial destructor)!");
+
+struct T5 : T1 {
+};
+static_assert(__has_trivial_destructor(T5), "All the direct base classes of T5 have trivial destructors!");
+
+struct T6 {
+  T5 t5;
+  T1 t1[2][2];
+  static T2 t2;
+};
+static_assert(__has_trivial_destructor(T6), "All nonstatic data members of T6 have trivial destructors!");
+
+struct T7 {
+  T2 t2;
+};
+static_assert(!__has_trivial_destructor(T7), "t2 does not have a trivial destructor!");
+
+struct T8 : T2 {
+};
+static_assert(!__has_trivial_destructor(T8), "The base class T2 does not have a trivial destructor!");





More information about the cfe-commits mailing list