Add support for the __has_trivial_constructor type trait.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69245 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index ffc35fe..78ed3fc 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -29,6 +29,7 @@
     UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
     UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
     Aggregate(true), PlainOldData(true), Polymorphic(false), Abstract(false),
+    HasTrivialConstructor(true),
     Bases(0), NumBases(0), Conversions(DC, DeclarationName()),
     TemplateOrInstantiation() { }
 
@@ -138,6 +139,11 @@
     //   A POD-struct is an aggregate class [...]
     PlainOldData = false;
 
+    // C++ [class.ctor]p5:
+    //   A constructor is trivial if it is an implicitly-declared default
+    //   constructor.
+    HasTrivialConstructor = false;
+    
     // Note when we have a user-declared copy constructor, which will
     // suppress the implicit declaration of a copy constructor.
     if (ConDecl->isCopyConstructor(Context))
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index c2fcc5f..3634c20 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -170,6 +170,10 @@
     if (const RecordType *RT = QueriedType->getAsRecordType())
       return cast<CXXRecordDecl>(RT->getDecl())->isAbstract();
     return false;
+  case UTT_HasTrivialConstructor:
+    if (const RecordType *RT = QueriedType->getAsRecordType())
+      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor();
+   return false;
   }
 }
 
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 20a8359..d41586c 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -481,7 +481,7 @@
 ///                   '__has_nothrow_constructor'             [TODO]
 ///                   '__has_trivial_assign'                  [TODO]
 ///                   '__has_trivial_copy'                    [TODO]
-///                   '__has_trivial_constructor'             [TODO]
+///                   '__has_trivial_constructor'
 ///                   '__has_trivial_destructor'              [TODO]
 ///                   '__has_virtual_destructor'              [TODO]
 ///                   '__is_abstract'                         [TODO]
@@ -771,6 +771,7 @@
   case tok::kw___is_union:
   case tok::kw___is_polymorphic:
   case tok::kw___is_abstract:
+  case tok::kw___has_trivial_constructor:
     return ParseUnaryTypeTrait();
 
   case tok::at: {
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 6233871..6c4580d 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2049,6 +2049,7 @@
       CurClass->setAggregate(false);
       CurClass->setPOD(false);
       CurClass->setPolymorphic(true);
+      CurClass->setHasTrivialConstructor(false);
     }
   }
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index cc70dc4..ec1ed46 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -369,6 +369,18 @@
   Class->setAggregate(false);
   Class->setPOD(false);
 
+  if (Virtual) {
+    // C++ [class.ctor]p5:
+    //   A constructor is trivial if its class has no virtual base classes.
+    Class->setHasTrivialConstructor(false);
+  } else {
+    // C++ [class.ctor]p5:
+    //   A constructor is trivial if all the direct base classes of its 
+    //   class have trivial constructors.
+    Class->setHasTrivialConstructor(cast<CXXRecordDecl>(BaseDecl)->
+                                    hasTrivialConstructor());
+  }
+  
   // Create the base specifier.
   // FIXME: Allocate via ASTContext?
   return new CXXBaseSpecifier(SpecifierRange, Virtual, 
@@ -940,6 +952,24 @@
   if (RD->isAbstract()) 
     AbstractClassUsageDiagnoser(*this, RD);
     
+  if (RD->hasTrivialConstructor()) {
+    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.
+      QualType FTy = i->getType();
+      while (const ArrayType *AT = Context.getAsArrayType(FTy))
+        FTy = AT->getElementType();
+      
+      if (const RecordType *RT = FTy->getAsRecordType()) {
+        CXXRecordDecl *FieldRD = cast<CXXRecordDecl>(RT->getDecl());
+        if (!FieldRD->hasTrivialConstructor()) {
+          RD->setHasTrivialConstructor(false);
+          break;
+        }
+      }
+    }
+  }
+      
   if (!Template)
     AddImplicitlyDeclaredMembersToClass(RD);
 }