Introduce the notion of literal types, as specified in C++0x.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90361 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 349487f..16b6dd7 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -791,6 +791,10 @@
   /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10).
   bool isPODType() const;
 
+  /// isLiteralType - Return true if this is a literal type
+  /// (C++0x [basic.types]p10)
+  bool isLiteralType() const;
+
   /// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
   /// types that have a non-constant expression. This does not include "[]".
   bool isVariablyModifiedType() const;
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 9942233..bb022f1 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -324,6 +324,8 @@
 KEYWORD(__is_pod                    , KEYCXX)
 KEYWORD(__is_polymorphic            , KEYCXX)
 KEYWORD(__is_union                  , KEYCXX)
+// Tentative name - there's no implementation of std::is_literal_type yet.
+KEYWORD(__is_literal                , KEYCXX)
 // FIXME: Add MS's traits, too.
 
 // Apple Extension.
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index 2a2eacc..36b8300 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -32,7 +32,8 @@
     UTT_IsEnum,
     UTT_IsPOD,
     UTT_IsPolymorphic,
-    UTT_IsUnion
+    UTT_IsUnion,
+    UTT_IsLiteral
   };
 
 }
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 7a6fbdc..a9f96ad 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -199,6 +199,7 @@
   switch(UTT) {
   default: assert(false && "Unknown type trait or not implemented");
   case UTT_IsPOD: return QueriedType->isPODType();
+  case UTT_IsLiteral: return QueriedType->isLiteralType();
   case UTT_IsClass: // Fallthrough
   case UTT_IsUnion:
     if (const RecordType *Record = QueriedType->getAs<RecordType>()) {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 5a2434d..70387c7 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -639,6 +639,40 @@
   }
 }
 
+bool Type::isLiteralType() const {
+  if (isIncompleteType())
+    return false;
+
+  // 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
+    return false;
+
+    //   -- 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();
+  }
+}
+
 bool Type::isPromotableIntegerType() const {
   if (const BuiltinType *BT = getAs<BuiltinType>())
     switch (BT->getKind()) {
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index f780cf1..7b8bc3e 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -826,6 +826,7 @@
   case tok::kw___is_empty:
   case tok::kw___is_polymorphic:
   case tok::kw___is_abstract:
+  case tok::kw___is_literal:
   case tok::kw___has_trivial_constructor:
   case tok::kw___has_trivial_copy:
   case tok::kw___has_trivial_assign:
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 52003e6..4eb6cd5 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1459,6 +1459,7 @@
   case tok::kw___is_pod:                  return UTT_IsPOD;
   case tok::kw___is_polymorphic:          return UTT_IsPolymorphic;
   case tok::kw___is_union:                return UTT_IsUnion;
+  case tok::kw___is_literal:              return UTT_IsLiteral;
   }
 }
 
diff --git a/test/SemaCXX/literal-type.cpp b/test/SemaCXX/literal-type.cpp
new file mode 100644
index 0000000..0dca9c9
--- /dev/null
+++ b/test/SemaCXX/literal-type.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
+
+static_assert(__is_literal(int), "fail");
+static_assert(__is_literal(void*), "fail");
+enum E { E1 };
+static_assert(__is_literal(E), "fail");
+static_assert(__is_literal(decltype(E1)), "fail");
+typedef int IAR[10];
+static_assert(__is_literal(IAR), "fail");
+// FIXME: Records