For PR11916: Add support for g++'s __int128 keyword. Unlike __int128_t, this is
a type specifier and can be combined with unsigned. This allows libstdc++4.7 to
be used with clang in c++98 mode.

Several other changes are still required for libstdc++4.7 to work with clang in
c++11 mode.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153999 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/INPUTS/all-std-headers.cpp b/INPUTS/all-std-headers.cpp
index 13e378d..5f13b9d 100644
--- a/INPUTS/all-std-headers.cpp
+++ b/INPUTS/all-std-headers.cpp
@@ -44,7 +44,9 @@
 #include <stdexcept>
 #include <streambuf>
 #include <string>
-#include <strstream> 
+#if __has_include(<strstream>)
+#include <strstream>
+#endif
 #include <typeinfo>
 #include <utility>
 #include <valarray>
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index ec0cd33..9e71827 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -40,6 +40,7 @@
     TST_char16,       // C++0x char16_t
     TST_char32,       // C++0x char32_t
     TST_int,
+    TST_int128,
     TST_half,         // OpenCL half, ARM NEON __fp16
     TST_float,
     TST_double,
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index d7e081f..2e4d34d 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -332,6 +332,7 @@
 KEYWORD(__builtin_va_arg            , KEYALL)
 KEYWORD(__extension__               , KEYALL)
 KEYWORD(__imag                      , KEYALL)
+KEYWORD(__int128                    , KEYALL)
 KEYWORD(__label__                   , KEYALL)
 KEYWORD(__real                      , KEYALL)
 KEYWORD(__thread                    , KEYALL)
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index f147950..67fd393 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -245,6 +245,7 @@
   static const TST TST_char16 = clang::TST_char16;
   static const TST TST_char32 = clang::TST_char32;
   static const TST TST_int = clang::TST_int;
+  static const TST TST_int128 = clang::TST_int128;
   static const TST TST_half = clang::TST_half;
   static const TST TST_float = clang::TST_float;
   static const TST TST_double = clang::TST_double;
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index c61f34f..c82aeaa 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1428,13 +1428,13 @@
   case Int:               return "int";
   case Long:              return "long";
   case LongLong:          return "long long";
-  case Int128:            return "__int128_t";
+  case Int128:            return "__int128";
   case UChar:             return "unsigned char";
   case UShort:            return "unsigned short";
   case UInt:              return "unsigned int";
   case ULong:             return "unsigned long";
   case ULongLong:         return "unsigned long long";
-  case UInt128:           return "__uint128_t";
+  case UInt128:           return "unsigned __int128";
   case Half:              return "half";
   case Float:             return "float";
   case Double:            return "double";
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 03f41a0..9216b23 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -207,6 +207,7 @@
   case tok::kw_int:
   case tok::kw_long:
   case tok::kw___int64:
+  case tok::kw___int128:
   case tok::kw_signed:
   case tok::kw_unsigned:
   case tok::kw_float:
@@ -2228,10 +2229,14 @@
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
                                      DiagID);
       break;
-     case tok::kw_half:
-       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
-                                      DiagID);
-       break;
+    case tok::kw___int128:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,
+                                     DiagID);
+      break;
+    case tok::kw_half:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
+                                     DiagID);
+      break;
     case tok::kw_float:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
                                      DiagID);
@@ -3039,6 +3044,7 @@
   case tok::kw_short:
   case tok::kw_long:
   case tok::kw___int64:
+  case tok::kw___int128:
   case tok::kw_signed:
   case tok::kw_unsigned:
   case tok::kw__Complex:
@@ -3109,6 +3115,7 @@
   case tok::kw_short:
   case tok::kw_long:
   case tok::kw___int64:
+  case tok::kw___int128:
   case tok::kw_signed:
   case tok::kw_unsigned:
   case tok::kw__Complex:
@@ -3244,6 +3251,7 @@
   case tok::kw_short:
   case tok::kw_long:
   case tok::kw___int64:
+  case tok::kw___int128:
   case tok::kw_signed:
   case tok::kw_unsigned:
   case tok::kw__Complex:
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 752e5c5..f68359b 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -987,6 +987,7 @@
   case tok::kw_int:
   case tok::kw_long:
   case tok::kw___int64:
+  case tok::kw___int128:
   case tok::kw_signed:
   case tok::kw_unsigned:
   case tok::kw_half:
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 9d1038e..0b7b2d9 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1389,6 +1389,7 @@
   case tok::kw_short:
   case tok::kw_long:
   case tok::kw___int64:
+  case tok::kw___int128:
   case tok::kw_signed:
   case tok::kw_unsigned:
   case tok::kw_void:
@@ -1499,6 +1500,9 @@
   case tok::kw_int:
     DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
     break;
+  case tok::kw___int128:
+    DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID);
+    break;
   case tok::kw_half:
     DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID);
     break;
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index e3b9225..73501e5 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -707,6 +707,7 @@
   case tok::kw_int:
   case tok::kw_long:
   case tok::kw___int64:
+  case tok::kw___int128:
   case tok::kw_restrict:
   case tok::kw_short:
   case tok::kw_signed:
@@ -1038,6 +1039,7 @@
   case tok::kw_int:
   case tok::kw_long:
   case tok::kw___int64:
+  case tok::kw___int128:
   case tok::kw_signed:
   case tok::kw_unsigned:
   case tok::kw_half:
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 97e00f0..b531acc 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -264,6 +264,7 @@
     case TST_float:
     case TST_half:
     case TST_int:
+    case TST_int128:
     case TST_struct:
     case TST_union:
     case TST_unknown_anytype:
@@ -379,6 +380,7 @@
   case DeclSpec::TST_char16:      return "char16_t";
   case DeclSpec::TST_char32:      return "char32_t";
   case DeclSpec::TST_int:         return "int";
+  case DeclSpec::TST_int128:      return "__int128";
   case DeclSpec::TST_half:        return "half";
   case DeclSpec::TST_float:       return "float";
   case DeclSpec::TST_double:      return "double";
@@ -818,7 +820,7 @@
   if (TypeSpecSign != TSS_unspecified) {
     if (TypeSpecType == TST_unspecified)
       TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
-    else if (TypeSpecType != TST_int  &&
+    else if (TypeSpecType != TST_int  && TypeSpecType != TST_int128 &&
              TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
       Diag(D, TSSLoc, diag::err_invalid_sign_spec)
         << getSpecifierName((TST)TypeSpecType);
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 87c8b4d..a40100c 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -667,6 +667,7 @@
   case TST_char16:
   case TST_char32:
   case TST_int:
+  case TST_int128:
   case TST_half:
   case TST_float:
   case TST_double:
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index e83e9ef..711ff08 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -720,6 +720,12 @@
     }
     break;
   }
+  case DeclSpec::TST_int128:
+    if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+      Result = Context.UnsignedInt128Ty;
+    else
+      Result = Context.Int128Ty;
+    break;
   case DeclSpec::TST_half: Result = Context.HalfTy; break;
   case DeclSpec::TST_float: Result = Context.FloatTy; break;
   case DeclSpec::TST_double:
diff --git a/test/Sema/128bitint.c b/test/Sema/128bitint.c
index fe83d97..89d3ee2 100644
--- a/test/Sema/128bitint.c
+++ b/test/Sema/128bitint.c
@@ -7,3 +7,7 @@
 
 // PR5435
 __uint128_t b = (__uint128_t)-1;
+
+// PR11916: Support for libstdc++ 4.7
+__int128 i = (__int128)0;
+unsigned __int128 u = (unsigned __int128)-1;
diff --git a/test/Sema/types.c b/test/Sema/types.c
index 332b525..3bec83e 100644
--- a/test/Sema/types.c
+++ b/test/Sema/types.c
@@ -19,7 +19,21 @@
   int __int128_t;
   int __uint128_t;
 }
+// __int128 is a keyword
+int c() {
+  __int128 i;
+  unsigned __int128 j;
+  long unsigned __int128 k; // expected-error {{'long __int128' is invalid}}
+  int __int128; // expected-error {{cannot combine with previous}} expected-warning {{does not declare anything}}
+}
+// __int128_t is __int128; __uint128_t is unsigned __int128.
+typedef __int128 check_int_128; // expected-note {{here}}
+typedef __int128_t check_int_128; // expected-note {{here}} expected-warning {{redefinition}}
+typedef int check_int_128; // expected-error {{different types ('int' vs '__int128_t' (aka '__int128'))}}
 
+typedef unsigned __int128 check_uint_128; // expected-note {{here}}
+typedef __uint128_t check_uint_128; // expected-note {{here}} expected-warning {{redefinition}}
+typedef int check_uint_128; // expected-error {{different types ('int' vs '__uint128_t' (aka 'unsigned __int128'))}}
 
 // Array type merging should convert array size to whatever matches the target
 // pointer size.