Implement most of the remaining logic in __is_literal type trait. This
should now support all of the C++98 types, and all of the C++0x types
Clang supports.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130079 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index af796d5..a71750b 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -32,9 +32,11 @@
     UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
     Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
     Abstract(false), HasTrivialConstructor(true),
+    HasConstExprNonCopyMoveConstructor(false),
     HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true),
     HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true),
-    HasTrivialDestructor(true), ComputedVisibleConversions(false),
+    HasTrivialDestructor(true), HasNonLiteralTypeFieldsOrBases(false),
+    ComputedVisibleConversions(false),
     DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), 
     DeclaredCopyAssignment(false), DeclaredDestructor(false),
     NumBases(0), NumVBases(0), Bases(), VBases(),
@@ -117,6 +119,10 @@
     //   polymorphic class.
     if (BaseClassDecl->isPolymorphic())
       data().Polymorphic = true;
+
+    // Record if this base is the first non-literal field or base.
+    if (!hasNonLiteralTypeFieldsOrBases() && !BaseType->isLiteralType())
+      data().HasNonLiteralTypeFieldsOrBases = true;
     
     // Now go through all virtual bases of this base and add them.
     for (CXXRecordDecl::base_class_iterator VBase =
@@ -486,6 +492,12 @@
         data().HasTrivialMoveConstructor = false;
       }
     }
+    if (Constructor->isConstExpr() &&
+        !Constructor->isCopyOrMoveConstructor()) {
+      // Record if we see any constexpr constructors which are niether copy
+      // nor move constructors.
+      data().HasConstExprNonCopyMoveConstructor = true;
+    }
 
     return;
   }
@@ -620,7 +632,11 @@
       data().PlainOldData = false;
     if (T->isReferenceType())
       data().HasTrivialConstructor = false;
-    
+
+    // Record if this field is the first non-literal field or base.
+    if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType())
+      data().HasNonLiteralTypeFieldsOrBases = true;
+
     if (const RecordType *RecordTy = T->getAs<RecordType>()) {
       CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
       if (FieldRec->getDefinition()) {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index a25f033..124bf13 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -874,32 +874,43 @@
 
   // C++0x [basic.types]p10:
   //   A type is a literal type if it is:
-  switch (CanonicalType->getTypeClass()) {
-    // We're whitelisting
-  default: return false;
-
-    //   -- a scalar type
-  case Builtin:
-  case Complex:
-  case Pointer:
-  case MemberPointer:
-  case Vector:
-  case ExtVector:
-  case ObjCObjectPointer:
-  case Enum:
-    return true;
-
-    //   -- a class type with ...
-  case Record:
-    // FIXME: Do the tests
+  //   [...]
+  //   -- an array of literal type
+  // Extension: variable arrays cannot be literal types, since they're
+  // runtime-sized.
+  if (isArrayType() && !isConstantArrayType())
     return false;
+  const Type *BaseTy = getBaseElementTypeUnsafe();
+  assert(BaseTy && "NULL element type");
 
-    //   -- an array of literal type
-    // Extension: variable arrays cannot be literal types, since they're
-    // runtime-sized.
-  case ConstantArray:
-    return cast<ArrayType>(CanonicalType)->getElementType()->isLiteralType();
+  // C++0x [basic.types]p10:
+  //   A type is a literal type if it is:
+  //    -- a scalar type; or
+  if (BaseTy->isScalarType()) return true;
+  //    -- a reference type; or
+  if (BaseTy->isReferenceType()) return true;
+  //    -- a class type that has all of the following properties:
+  if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
+    const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    //      -- a trivial destructor,
+    if (!ClassDecl->hasTrivialDestructor()) return false;
+    //      -- every constructor call and full-expression in the
+    //         brace-or-equal-initializers for non-static data members (if any)
+    //         is a constant expression,
+    // FIXME: C++0x: Clang doesn't yet support non-static data member
+    // declarations with initializers, or constexprs.
+    //      -- it is an aggregate type or has at least one constexpr
+    //         constructor or constructor template that is not a copy or move
+    //         constructor, and
+    if (!ClassDecl->isAggregate() &&
+        !ClassDecl->hasConstExprNonCopyMoveConstructor())
+      return false;
+    //      -- all non-static data members and base classes of literal types
+    if (ClassDecl->hasNonLiteralTypeFieldsOrBases()) return false;
+
+    return true;
   }
+  return false;
 }
 
 bool Type::isTrivialType() const {
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index a85099d..8190eab 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -842,11 +842,13 @@
   Data.Polymorphic = Record[Idx++];
   Data.Abstract = Record[Idx++];
   Data.HasTrivialConstructor = Record[Idx++];
+  Data.HasConstExprNonCopyMoveConstructor = Record[Idx++];
   Data.HasTrivialCopyConstructor = Record[Idx++];
   Data.HasTrivialMoveConstructor = Record[Idx++];
   Data.HasTrivialCopyAssignment = Record[Idx++];
   Data.HasTrivialMoveAssignment = Record[Idx++];
   Data.HasTrivialDestructor = Record[Idx++];
+  Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
   Data.ComputedVisibleConversions = Record[Idx++];
   Data.DeclaredDefaultConstructor = Record[Idx++];
   Data.DeclaredCopyConstructor = Record[Idx++];
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 24a9c66..7196a72 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -3794,11 +3794,13 @@
   Record.push_back(Data.Polymorphic);
   Record.push_back(Data.Abstract);
   Record.push_back(Data.HasTrivialConstructor);
+  Record.push_back(Data.HasConstExprNonCopyMoveConstructor);
   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.HasNonLiteralTypeFieldsOrBases);
   Record.push_back(Data.ComputedVisibleConversions);
   Record.push_back(Data.DeclaredDefaultConstructor);
   Record.push_back(Data.DeclaredCopyConstructor);