t/clang/type-traits

Patch authored by John Wiegley.

These type traits are used for parsing code that employs certain features of
the Embarcadero C++ compiler.  Several of these constructs are also desired by
libc++, according to its project pages (such as __is_standard_layout).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130342 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index f593028..c41798e 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -731,22 +731,19 @@
   // styles of attributes?
   MaybeParseCXX0XAttributes(attrs);
 
-  if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) {
-    // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but
-    // __is_pod is a keyword in GCC >= 4.3. Therefore, when we see the
-    // token sequence "struct __is_pod", make __is_pod into a normal
-    // identifier rather than a keyword, to allow libstdc++ 4.2 to work
-    // properly.
-    Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
-    Tok.setKind(tok::identifier);
-  }
-
-  if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_empty)) {
-    // GNU libstdc++ 4.2 uses __is_empty as the name of a struct template, but
-    // __is_empty is a keyword in GCC >= 4.3. Therefore, when we see the
-    // token sequence "struct __is_empty", make __is_empty into a normal
-    // identifier rather than a keyword, to allow libstdc++ 4.2 to work
-    // properly.
+  if (TagType == DeclSpec::TST_struct &&
+      (Tok.is(tok::kw___is_pod) ||
+       Tok.is(tok::kw___is_empty) ||
+       Tok.is(tok::kw___is_void) ||
+       Tok.is(tok::kw___is_pointer) ||
+       Tok.is(tok::kw___is_arithmetic) ||
+       Tok.is(tok::kw___is_fundamental) ||
+       Tok.is(tok::kw___is_scalar))) {
+    // GNU libstdc++ 4.2 uses certain intrinsic names as the name of
+    // struct templates, but these are keywords in GCC >= 4.3 and
+    // Clang. Therefore, when we see the token sequence "struct X", make
+    // X into a normal identifier rather than a keyword, to allow
+    // libstdc++ 4.2 to work properly.
     Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
     Tok.setKind(tok::identifier);
   }
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index c990c52..1c4a942 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -519,6 +519,34 @@
 ///                   '::'[opt] 'delete' cast-expression
 ///                   '::'[opt] 'delete' '[' ']' cast-expression
 ///
+/// [GNU/Embarcadero] unary-type-trait:
+///                   '__is_arithmetic'
+///                   '__is_floating_point'
+///                   '__is_integral'
+///                   '__is_lvalue_expr'
+///                   '__is_rvalue_expr'
+///                   '__is_complete_type'
+///                   '__is_void'
+///                   '__is_array'
+///                   '__is_function'
+///                   '__is_reference'
+///                   '__is_lvalue_reference'
+///                   '__is_rvalue_reference'
+///                   '__is_fundamental'
+///                   '__is_object'
+///                   '__is_scalar'
+///                   '__is_compound'
+///                   '__is_pointer'
+///                   '__is_member_object_pointer'
+///                   '__is_member_function_pointer'
+///                   '__is_member_pointer'
+///                   '__is_const'
+///                   '__is_volatile'
+///                   '__is_trivial'
+///                   '__is_standard_layout'
+///                   '__is_signed'
+///                   '__is_unsigned'
+///
 /// [GNU] unary-type-trait:
 ///                   '__has_nothrow_assign'
 ///                   '__has_nothrow_copy'
@@ -540,6 +568,8 @@
 ///       binary-type-trait:
 /// [GNU]             '__is_base_of'       
 /// [MS]              '__is_convertible_to'
+///                   '__is_convertible'
+///                   '__is_same'
 ///
 /// [Embarcadero] expression-trait:
 ///                   '__is_lvalue_expr'
@@ -997,6 +1027,29 @@
   case tok::kw___is_empty:
   case tok::kw___is_enum:
   case tok::kw___is_literal:
+  case tok::kw___is_arithmetic:
+  case tok::kw___is_integral:
+  case tok::kw___is_floating_point:
+  case tok::kw___is_complete_type:
+  case tok::kw___is_void:
+  case tok::kw___is_array:
+  case tok::kw___is_function:
+  case tok::kw___is_reference:
+  case tok::kw___is_lvalue_reference:
+  case tok::kw___is_rvalue_reference:
+  case tok::kw___is_fundamental:
+  case tok::kw___is_object:
+  case tok::kw___is_scalar:
+  case tok::kw___is_compound:
+  case tok::kw___is_pointer:
+  case tok::kw___is_member_object_pointer:
+  case tok::kw___is_member_function_pointer:
+  case tok::kw___is_member_pointer:
+  case tok::kw___is_const:
+  case tok::kw___is_volatile:
+  case tok::kw___is_standard_layout:
+  case tok::kw___is_signed:
+  case tok::kw___is_unsigned:
   case tok::kw___is_literal_type:
   case tok::kw___is_pod:
   case tok::kw___is_polymorphic:
@@ -1014,6 +1067,8 @@
 
   case tok::kw___builtin_types_compatible_p:
   case tok::kw___is_base_of:
+  case tok::kw___is_same:
+  case tok::kw___is_convertible:
   case tok::kw___is_convertible_to:
     return ParseBinaryTypeTrait();
 
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 7bf76a9..aade050 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1912,25 +1912,50 @@
 
 static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
   switch(kind) {
-  default: llvm_unreachable("Not a known unary type trait");
+  default: assert(false && "Not a known unary type trait.");
   case tok::kw___has_nothrow_assign:      return UTT_HasNothrowAssign;
-  case tok::kw___has_nothrow_copy:        return UTT_HasNothrowCopy;
   case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
+  case tok::kw___has_nothrow_copy:           return UTT_HasNothrowCopy;
   case tok::kw___has_trivial_assign:      return UTT_HasTrivialAssign;
-  case tok::kw___has_trivial_copy:        return UTT_HasTrivialCopy;
   case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
+  case tok::kw___has_trivial_copy:           return UTT_HasTrivialCopy;
   case tok::kw___has_trivial_destructor:  return UTT_HasTrivialDestructor;
   case tok::kw___has_virtual_destructor:  return UTT_HasVirtualDestructor;
   case tok::kw___is_abstract:             return UTT_IsAbstract;
+  case tok::kw___is_arithmetic:              return UTT_IsArithmetic;
+  case tok::kw___is_array:                   return UTT_IsArray;
   case tok::kw___is_class:                return UTT_IsClass;
+  case tok::kw___is_complete_type:           return UTT_IsCompleteType;
+  case tok::kw___is_compound:                return UTT_IsCompound;
+  case tok::kw___is_const:                   return UTT_IsConst;
   case tok::kw___is_empty:                return UTT_IsEmpty;
   case tok::kw___is_enum:                 return UTT_IsEnum;
+  case tok::kw___is_floating_point:          return UTT_IsFloatingPoint;
+  case tok::kw___is_function:                return UTT_IsFunction;
+  case tok::kw___is_fundamental:             return UTT_IsFundamental;
+  case tok::kw___is_integral:                return UTT_IsIntegral;
+  case tok::kw___is_lvalue_expr:             return UTT_IsLvalueExpr;
+  case tok::kw___is_lvalue_reference:        return UTT_IsLvalueReference;
+  case tok::kw___is_member_function_pointer: return UTT_IsMemberFunctionPointer;
+  case tok::kw___is_member_object_pointer:   return UTT_IsMemberObjectPointer;
+  case tok::kw___is_member_pointer:          return UTT_IsMemberPointer;
+  case tok::kw___is_object:                  return UTT_IsObject;
   case tok::kw___is_literal:              return UTT_IsLiteral;
   case tok::kw___is_literal_type:         return UTT_IsLiteral;
   case tok::kw___is_pod:                  return UTT_IsPOD;
+  case tok::kw___is_pointer:                 return UTT_IsPointer;
   case tok::kw___is_polymorphic:          return UTT_IsPolymorphic;
-  case tok::kw___is_trivial:              return UTT_IsTrivial;
+  case tok::kw___is_reference:               return UTT_IsReference;
+  case tok::kw___is_rvalue_expr:             return UTT_IsRvalueExpr;
+  case tok::kw___is_rvalue_reference:        return UTT_IsRvalueReference;
+  case tok::kw___is_scalar:                  return UTT_IsScalar;
+  case tok::kw___is_signed:                  return UTT_IsSigned;
+  case tok::kw___is_standard_layout:         return UTT_IsStandardLayout;
+  case tok::kw___is_trivial:                 return UTT_IsTrivial;
   case tok::kw___is_union:                return UTT_IsUnion;
+  case tok::kw___is_unsigned:                return UTT_IsUnsigned;
+  case tok::kw___is_void:                    return UTT_IsVoid;
+  case tok::kw___is_volatile:                return UTT_IsVolatile;
   }
 }
 
@@ -1938,6 +1963,8 @@
   switch(kind) {
   default: llvm_unreachable("Not a known binary type trait");
   case tok::kw___is_base_of:                 return BTT_IsBaseOf;
+  case tok::kw___is_convertible:             return BTT_IsConvertible;
+  case tok::kw___is_same:                    return BTT_IsSame;
   case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible;
   case tok::kw___is_convertible_to:          return BTT_IsConvertibleTo;
   }