Add support for the __has_trivial_destructor type trait.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69345 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 78ed3fc..a5d133c 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -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() { }
 
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 3634c20..d73ea37 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -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;
   }
 }
 
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 3280730..47e364e 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -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: {
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index a2b565b..3b6ce6b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e3195a9..9fd6226 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
-        }
       }
     }
   }