[clang] 5f0903e - Reland Implement _ExtInt as an extended int type specifier.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 17 10:45:59 PDT 2020


Author: Erich Keane
Date: 2020-04-17T10:45:48-07:00
New Revision: 5f0903e9bec97e67bf34d887bcbe9d05790de934

URL: https://github.com/llvm/llvm-project/commit/5f0903e9bec97e67bf34d887bcbe9d05790de934
DIFF: https://github.com/llvm/llvm-project/commit/5f0903e9bec97e67bf34d887bcbe9d05790de934.diff

LOG: Reland Implement _ExtInt as an extended int type specifier.

I fixed the LLDB issue, so re-applying the patch.

This reverts commit a4b88c044980337bb14390be654fe76864aa60ec.

Added: 
    clang/test/CodeGen/ext-int-sanitizer.cpp
    clang/test/CodeGen/ext-int.c
    clang/test/CodeGenCXX/ext-int.cpp
    clang/test/CodeGenOpenCL/ext-int-shift.cl
    clang/test/Parser/ext-int.cpp
    clang/test/SemaCXX/ext-int.cpp

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/docs/ReleaseNotes.rst
    clang/include/clang/AST/ASTContext.h
    clang/include/clang/AST/RecursiveASTVisitor.h
    clang/include/clang/AST/Type.h
    clang/include/clang/AST/TypeLoc.h
    clang/include/clang/AST/TypeProperties.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Basic/Specifiers.h
    clang/include/clang/Basic/TokenKinds.def
    clang/include/clang/Basic/TypeNodes.td
    clang/include/clang/Parse/Parser.h
    clang/include/clang/Sema/DeclSpec.h
    clang/include/clang/Sema/Sema.h
    clang/include/clang/Serialization/TypeBitCodes.def
    clang/lib/AST/ASTContext.cpp
    clang/lib/AST/ASTStructuralEquivalence.cpp
    clang/lib/AST/ExprConstant.cpp
    clang/lib/AST/ItaniumMangle.cpp
    clang/lib/AST/MicrosoftMangle.cpp
    clang/lib/AST/Type.cpp
    clang/lib/AST/TypePrinter.cpp
    clang/lib/CodeGen/CGDebugInfo.cpp
    clang/lib/CodeGen/CGDebugInfo.h
    clang/lib/CodeGen/CGExprScalar.cpp
    clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
    clang/lib/CodeGen/CodeGenFunction.cpp
    clang/lib/CodeGen/CodeGenTBAA.cpp
    clang/lib/CodeGen/CodeGenTypes.cpp
    clang/lib/CodeGen/CodeGenTypes.h
    clang/lib/CodeGen/ItaniumCXXABI.cpp
    clang/lib/Parse/ParseDecl.cpp
    clang/lib/Parse/ParseExpr.cpp
    clang/lib/Parse/ParseExprCXX.cpp
    clang/lib/Parse/ParseTentative.cpp
    clang/lib/Sema/DeclSpec.cpp
    clang/lib/Sema/SemaChecking.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaDeclAttr.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaLookup.cpp
    clang/lib/Sema/SemaTemplate.cpp
    clang/lib/Sema/SemaTemplateDeduction.cpp
    clang/lib/Sema/SemaTemplateVariadic.cpp
    clang/lib/Sema/SemaType.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/tools/libclang/CIndex.cpp
    lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 929cd1c67e73..07062a191ce8 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -3461,3 +3461,56 @@ Since the size of ``buffer`` can't be known at compile time, Clang will fold
 ``__builtin_object_size(buffer, 0)`` into ``-1``. However, if this was written
 as ``__builtin_dynamic_object_size(buffer, 0)``, Clang will fold it into
 ``size``, providing some extra runtime safety.
+
+Extended Integer Types
+======================
+
+Clang supports a set of extended integer types under the syntax ``_ExtInt(N)``
+where ``N`` is an integer that specifies the number of bits that are used to represent
+the type, including the sign bit. The keyword ``_ExtInt`` is a type specifier, thus
+it can be used in any place a type can, including as a non-type-template-parameter,
+as the type of a bitfield, and as the underlying type of an enumeration.
+
+An extended integer can be declared either signed, or unsigned by using the
+``signed``/``unsigned`` keywords. If no sign specifier is used or if the ``signed``
+keyword is used, the extended integer type is a signed integer and can represent
+negative values.
+
+The ``N`` expression is an integer constant expression, which specifies the number
+of bits used to represent the type, following normal integer representations for
+both signed and unsigned types. Both a signed and unsigned extended integer of the
+same ``N`` value will have the same number of bits in its representation. Many
+architectures don't have a way of representing non power-of-2 integers, so these
+architectures emulate these types using larger integers. In these cases, they are
+expected to follow the 'as-if' rule and do math 'as-if' they were done at the
+specified number of bits.
+
+In order to be consistent with the C language specification, and make the extended
+integer types useful for their intended purpose, extended integers follow the C
+standard integer conversion ranks. An extended integer type has a greater rank than
+any integer type with less precision.  However, they have lower rank than any
+of the built in or other integer types (such as __int128). Usual arithmetic conversions
+also work the same, where the smaller ranked integer is converted to the larger.
+
+The one exception to the C rules for integers for these types is Integer Promotion.
+Unary +, -, and ~ operators typically will promote operands to ``int``. Doing these
+promotions would inflate the size of required hardware on some platforms, so extended
+integer types aren't subject to the integer promotion rules in these cases.
+
+In languages (such as OpenCL) that define shift by-out-of-range behavior as a mask,
+non-power-of-two versions of these types use an unsigned remainder operation to constrain
+the value to the proper range, preventing undefined behavior.
+
+Extended integer types are aligned to the next greatest power-of-2 up to 64 bits.
+The size of these types for the purposes of layout and ``sizeof`` are the number of
+bits aligned to this calculated alignment. This permits the use of these types in
+allocated arrays using common ``sizeof(Array)/sizeof(ElementType)`` pattern.
+
+Extended integer types work with the C _Atomic type modifier, however only precisions
+that are powers-of-2 greater than 8 bit are accepted.
+
+Extended integer types align with existing calling conventions. They have the same size
+and alignment as the smallest basic type that can contain them. Types that are larger
+than 64 bits are handled in the same way as _int128 is handled; they are conceptually
+treated as struct of register size chunks. They number of chunks are the smallest
+number that can contain the types which does not necessarily mean a power-of-2 size.

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a8163cad9fde..54deba7bbd0e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -62,6 +62,14 @@ Non-comprehensive list of changes in this release
   in the Arm C Language Extensions.
 
 
+* clang adds support for a set of  extended integer types (``_ExtInt(N)``) that
+  permit non-power of 2 integers, exposing the LLVM integer types. Since a major
+  motivating use case for these types is to limit 'bit' usage, these types don't
+  automatically promote to 'int' when operations are done between two ``ExtInt(N)``
+  types, instead math occurs at the size of the largest ``ExtInt(N)`` type.
+
+
+
 New Compiler Flags
 ------------------
 

diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index ac742fefc109..dedbd857819d 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -224,6 +224,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   mutable llvm::FoldingSet<AtomicType> AtomicTypes;
   llvm::FoldingSet<AttributedType> AttributedTypes;
   mutable llvm::FoldingSet<PipeType> PipeTypes;
+  mutable llvm::FoldingSet<ExtIntType> ExtIntTypes;
+  mutable llvm::FoldingSet<DependentExtIntType> DependentExtIntTypes;
 
   mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
   mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@@ -1203,6 +1205,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
   /// Return a write_only pipe type for the specified type.
   QualType getWritePipeType(QualType T) const;
 
+  /// Return an extended integer type with the specified signedness and bit
+  /// count.
+  QualType getExtIntType(bool Unsigned, unsigned NumBits) const;
+
+  /// Return a dependent extended integer type with the specified signedness and
+  /// bit count.
+  QualType getDependentExtIntType(bool Unsigned, Expr *BitsExpr) const;
+
   /// Gets the struct used to keep track of the extended descriptor for
   /// pointer to blocks.
   QualType getBlockDescriptorExtendedType() const;

diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 85eb6259a419..b71f7994e2fa 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1115,6 +1115,10 @@ DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
 
 DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); })
 
+DEF_TRAVERSE_TYPE(ExtIntType, {})
+DEF_TRAVERSE_TYPE(DependentExtIntType,
+                  { TRY_TO(TraverseStmt(T->getNumBitsExpr())); })
+
 #undef DEF_TRAVERSE_TYPE
 
 // ----------------- TypeLoc traversal -----------------
@@ -1385,6 +1389,11 @@ DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
 
 DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
 
+DEF_TRAVERSE_TYPELOC(ExtIntType, {})
+DEF_TRAVERSE_TYPELOC(DependentExtIntType, {
+  TRY_TO(TraverseStmt(TL.getTypePtr()->getNumBitsExpr()));
+})
+
 #undef DEF_TRAVERSE_TYPELOC
 
 // ----------------- Decl traversal -----------------

diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index f78d9d7670a7..322b14ce641a 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2101,6 +2101,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
   bool isOCLExtOpaqueType() const;              // Any OpenCL extension type
 
   bool isPipeType() const;                      // OpenCL pipe type
+  bool isExtIntType() const;                    // Extended Int Type
   bool isOpenCLSpecificType() const;            // Any OpenCL specific type
 
   /// Determines if this type, which must satisfy
@@ -6127,6 +6128,64 @@ class PipeType : public Type, public llvm::FoldingSetNode {
   bool isReadOnly() const { return isRead; }
 };
 
+/// A fixed int type of a specified bitwidth.
+class ExtIntType final : public Type, public llvm::FoldingSetNode {
+  friend class ASTContext;
+  unsigned IsUnsigned : 1;
+  unsigned NumBits : 24;
+
+protected:
+  ExtIntType(bool isUnsigned, unsigned NumBits);
+
+public:
+  bool isUnsigned() const { return IsUnsigned; }
+  bool isSigned() const { return !IsUnsigned; }
+  unsigned getNumBits() const { return NumBits; }
+
+  bool isSugared() const { return false; }
+  QualType desugar() const { return QualType(this, 0); }
+
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, isUnsigned(), getNumBits());
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &ID, bool IsUnsigned,
+                      unsigned NumBits) {
+    ID.AddBoolean(IsUnsigned);
+    ID.AddInteger(NumBits);
+  }
+
+  static bool classof(const Type *T) { return T->getTypeClass() == ExtInt; }
+};
+
+class DependentExtIntType final : public Type, public llvm::FoldingSetNode {
+  friend class ASTContext;
+  const ASTContext &Context;
+  llvm::PointerIntPair<Expr*, 1, bool> ExprAndUnsigned;
+
+protected:
+  DependentExtIntType(const ASTContext &Context, bool IsUnsigned,
+                      Expr *NumBits);
+
+public:
+  bool isUnsigned() const;
+  bool isSigned() const { return !isUnsigned(); }
+  Expr *getNumBitsExpr() const;
+
+  bool isSugared() const { return false; }
+  QualType desugar() const { return QualType(this, 0); }
+
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, Context, isUnsigned(), getNumBitsExpr());
+  }
+  static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+                      bool IsUnsigned, Expr *NumBitsExpr);
+
+  static bool classof(const Type *T) {
+    return T->getTypeClass() == DependentExtInt;
+  }
+};
+
 /// A qualifier set is used to build a set of qualifiers.
 class QualifierCollector : public Qualifiers {
 public:
@@ -6646,6 +6705,10 @@ inline bool Type::isPipeType() const {
   return isa<PipeType>(CanonicalType);
 }
 
+inline bool Type::isExtIntType() const {
+  return isa<ExtIntType>(CanonicalType);
+}
+
 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
   inline bool Type::is##Id##Type() const { \
     return isSpecificBuiltinType(BuiltinType::Id); \
@@ -6741,7 +6804,7 @@ inline bool Type::isIntegerType() const {
     return IsEnumDeclComplete(ET->getDecl()) &&
       !IsEnumDeclScoped(ET->getDecl());
   }
-  return false;
+  return isExtIntType();
 }
 
 inline bool Type::isFixedPointType() const {
@@ -6798,7 +6861,8 @@ inline bool Type::isScalarType() const {
          isa<BlockPointerType>(CanonicalType) ||
          isa<MemberPointerType>(CanonicalType) ||
          isa<ComplexType>(CanonicalType) ||
-         isa<ObjCObjectPointerType>(CanonicalType);
+         isa<ObjCObjectPointerType>(CanonicalType) ||
+         isExtIntType();
 }
 
 inline bool Type::isIntegralOrEnumerationType() const {
@@ -6811,7 +6875,7 @@ inline bool Type::isIntegralOrEnumerationType() const {
   if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
     return IsEnumDeclComplete(ET->getDecl());
 
-  return false;
+  return isExtIntType();
 }
 
 inline bool Type::isBooleanType() const {

diff  --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 3fc53d823c37..2221485983b2 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -2450,6 +2450,12 @@ inline T TypeLoc::getAsAdjusted() const {
   }
   return Cur.getAs<T>();
 }
+class ExtIntTypeLoc final
+    : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, ExtIntTypeLoc,
+                                        ExtIntType> {};
+class DependentExtIntTypeLoc final
+    : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentExtIntTypeLoc,
+                                        DependentExtIntType> {};
 
 } // namespace clang
 

diff  --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 994f932170ae..12bc5a4ee8a3 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -833,3 +833,28 @@ let Class = PipeType in {
     return ctx.getPipeType(elementType, isReadOnly);
   }]>;
 }
+
+let Class = ExtIntType in {
+  def : Property<"isUnsigned", Bool> {
+    let Read = [{ node->isUnsigned() }];
+  }
+  def : Property <"numBits", UInt32> {
+    let Read = [{ node->getNumBits() }];
+  }
+
+  def : Creator<[{
+    return ctx.getExtIntType(isUnsigned, numBits);
+  }]>;
+}
+
+let Class = DependentExtIntType in {
+  def : Property<"isUnsigned", Bool> {
+    let Read = [{ node->isUnsigned() }];
+  }
+  def : Property <"numBitsExpr", ExprRef> {
+    let Read = [{ node->getNumBitsExpr() }];
+  }
+  def : Creator<[{
+    return ctx.getDependentExtIntType(isUnsigned, numBitsExpr);
+  }]>;
+}

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 35a7a05667fc..97ad1a6c7920 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5947,10 +5947,12 @@ def err_block_return_missing_expr : Error<
   "non-void block should return a value">;
 def err_func_def_incomplete_result : Error<
   "incomplete result type %0 in function definition">;
-def err_atomic_specifier_bad_type : Error<
-  "_Atomic cannot be applied to "
-  "%select{incomplete |array |function |reference |atomic |qualified |sizeless |}0type "
-  "%1 %select{|||||||which is not trivially copyable}0">;
+def err_atomic_specifier_bad_type
+    : Error<"_Atomic cannot be applied to "
+            "%select{incomplete |array |function |reference |atomic |qualified "
+            "|sizeless ||integer |integer }0type "
+            "%1 %select{|||||||which is not trivially copyable|with less than "
+            "1 byte of precision|with a non power of 2 precision}0">;
 
 // Expressions.
 def select_unary_expr_or_type_trait_kind : TextSubstitution<
@@ -10711,4 +10713,8 @@ def warn_sycl_kernel_return_type : Warning<
   "function template with 'sycl_kernel' attribute must have a 'void' return type">,
   InGroup<IgnoredAttributes>;
 
+def err_ext_int_bad_size : Error<"%select{signed|unsigned}0 _ExtInt must "
+                                 "have a bit size of at least %select{2|1}0">;
+def err_ext_int_max_size : Error<"%select{signed|unsigned}0 _ExtInt of bit "
+                                 "sizes greater than %1 not supported">;
 } // end of sema component.

diff  --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 73823dc01ec7..e6c2cb39566c 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -67,6 +67,7 @@ namespace clang {
     TST_char32,       // C++11 char32_t
     TST_int,
     TST_int128,
+    TST_extint,       // Extended Int types.
     TST_half,         // OpenCL half, ARM NEON __fp16
     TST_Float16,      // C11 extension ISO/IEC TS 18661-3
     TST_Accum,        // ISO/IEC JTC1 SC22 WG14 N1169 Extension

diff  --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 3b1062e48767..1da24a8fd38b 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -285,6 +285,7 @@ KEYWORD(goto                        , KEYALL)
 KEYWORD(if                          , KEYALL)
 KEYWORD(inline                      , KEYC99|KEYCXX|KEYGNU)
 KEYWORD(int                         , KEYALL)
+KEYWORD(_ExtInt                     , KEYALL)
 KEYWORD(long                        , KEYALL)
 KEYWORD(register                    , KEYALL)
 KEYWORD(restrict                    , KEYC99)

diff  --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td
index 96d9472a488a..cd15a498642f 100644
--- a/clang/include/clang/Basic/TypeNodes.td
+++ b/clang/include/clang/Basic/TypeNodes.td
@@ -104,3 +104,5 @@ def ObjCInterfaceType : TypeNode<ObjCObjectType>, LeafType;
 def ObjCObjectPointerType : TypeNode<Type>;
 def PipeType : TypeNode<Type>;
 def AtomicType : TypeNode<Type>;
+def ExtIntType : TypeNode<Type>;
+def DependentExtIntType : TypeNode<Type>, AlwaysDependent;

diff  --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 3f73a1b90268..b4e96a5b85de 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2721,6 +2721,7 @@ class Parser : public CodeCompletionHandler {
                                 SourceLocation &EllipsisLoc);
   void ParseAlignmentSpecifier(ParsedAttributes &Attrs,
                                SourceLocation *endLoc = nullptr);
+  ExprResult ParseExtIntegerArgument();
 
   VirtSpecifiers::Specifier isCXX11VirtSpecifier(const Token &Tok) const;
   VirtSpecifiers::Specifier isCXX11VirtSpecifier() const {

diff  --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 0e95e237e974..5bc13fe343f4 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -278,6 +278,7 @@ class DeclSpec {
   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_extint = clang::TST_extint;
   static const TST TST_half = clang::TST_half;
   static const TST TST_float = clang::TST_float;
   static const TST TST_double = clang::TST_double;
@@ -413,7 +414,7 @@ class DeclSpec {
             T == TST_underlyingType || T == TST_atomic);
   }
   static bool isExprRep(TST T) {
-    return (T == TST_typeofExpr || T == TST_decltype);
+    return (T == TST_typeofExpr || T == TST_decltype || T == TST_extint);
   }
   static bool isTemplateIdRep(TST T) {
     return (T == TST_auto || T == TST_decltype_auto);
@@ -704,6 +705,9 @@ class DeclSpec {
   bool SetTypePipe(bool isPipe, SourceLocation Loc,
                        const char *&PrevSpec, unsigned &DiagID,
                        const PrintingPolicy &Policy);
+  bool SetExtIntType(SourceLocation KWLoc, Expr *BitWidth,
+                     const char *&PrevSpec, unsigned &DiagID,
+                     const PrintingPolicy &Policy);
   bool SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec,
                       unsigned &DiagID);
   bool SetTypeSpecError();

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index a1a0b854a85b..af58b0ec4e82 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1678,6 +1678,7 @@ class Sema final {
                          SourceLocation Loc);
   QualType BuildWritePipeType(QualType T,
                          SourceLocation Loc);
+  QualType BuildExtIntType(bool IsUnsigned, Expr *BitWidth, SourceLocation Loc);
 
   TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
   TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);

diff  --git a/clang/include/clang/Serialization/TypeBitCodes.def b/clang/include/clang/Serialization/TypeBitCodes.def
index 38c73ccb7daf..561c8869ead6 100644
--- a/clang/include/clang/Serialization/TypeBitCodes.def
+++ b/clang/include/clang/Serialization/TypeBitCodes.def
@@ -58,5 +58,7 @@ TYPE_BIT_CODE(DependentSizedExtVector, DEPENDENT_SIZED_EXT_VECTOR, 46)
 TYPE_BIT_CODE(DependentAddressSpace, DEPENDENT_ADDRESS_SPACE, 47)
 TYPE_BIT_CODE(DependentVector, DEPENDENT_SIZED_VECTOR, 48)
 TYPE_BIT_CODE(MacroQualified, MACRO_QUALIFIED, 49)
+TYPE_BIT_CODE(ExtInt, EXT_INT, 50)
+TYPE_BIT_CODE(DependentExtInt, DEPENDENT_EXT_INT, 51)
 
 #undef TYPE_BIT_CODE

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 34bb07cd3f78..8734dd390247 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -2180,6 +2180,15 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
     Align = toBits(Layout.getAlignment());
     break;
   }
+  case Type::ExtInt: {
+    const auto *EIT = cast<ExtIntType>(T);
+    Align =
+        std::min(static_cast<unsigned>(std::max(
+                     getCharWidth(), llvm::PowerOf2Ceil(EIT->getNumBits()))),
+                 Target->getLongLongAlign());
+    Width = llvm::alignTo(EIT->getNumBits(), Align);
+    break;
+  }
   case Type::Record:
   case Type::Enum: {
     const auto *TT = cast<TagType>(T);
@@ -3376,6 +3385,8 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
   case Type::Auto:
   case Type::DeducedTemplateSpecialization:
   case Type::PackExpansion:
+  case Type::ExtInt:
+  case Type::DependentExtInt:
     llvm_unreachable("type should never be variably-modified");
 
   // These types can be variably-modified but should never need to
@@ -4070,6 +4081,39 @@ QualType ASTContext::getWritePipeType(QualType T) const {
   return getPipeType(T, false);
 }
 
+QualType ASTContext::getExtIntType(bool IsUnsigned, unsigned NumBits) const {
+  llvm::FoldingSetNodeID ID;
+  ExtIntType::Profile(ID, IsUnsigned, NumBits);
+
+  void *InsertPos = nullptr;
+  if (ExtIntType *EIT = ExtIntTypes.FindNodeOrInsertPos(ID, InsertPos))
+    return QualType(EIT, 0);
+
+  auto *New = new (*this, TypeAlignment) ExtIntType(IsUnsigned, NumBits);
+  ExtIntTypes.InsertNode(New, InsertPos);
+  Types.push_back(New);
+  return QualType(New, 0);
+}
+
+QualType ASTContext::getDependentExtIntType(bool IsUnsigned,
+                                            Expr *NumBitsExpr) const {
+  assert(NumBitsExpr->isInstantiationDependent() && "Only good for dependent");
+  llvm::FoldingSetNodeID ID;
+  DependentExtIntType::Profile(ID, *this, IsUnsigned, NumBitsExpr);
+
+  void *InsertPos = nullptr;
+  if (DependentExtIntType *Existing =
+          DependentExtIntTypes.FindNodeOrInsertPos(ID, InsertPos))
+    return QualType(Existing, 0);
+
+  auto *New = new (*this, TypeAlignment)
+      DependentExtIntType(*this, IsUnsigned, NumBitsExpr);
+  DependentExtIntTypes.InsertNode(New, InsertPos);
+
+  Types.push_back(New);
+  return QualType(New, 0);
+}
+
 #ifndef NDEBUG
 static bool NeedsInjectedClassNameType(const RecordDecl *D) {
   if (!isa<CXXRecordDecl>(D)) return false;
@@ -5905,6 +5949,11 @@ int ASTContext::getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const {
 unsigned ASTContext::getIntegerRank(const Type *T) const {
   assert(T->isCanonicalUnqualified() && "T should be canonicalized");
 
+  // Results in this 'losing' to any type of the same size, but winning if
+  // larger.
+  if (const auto *EIT = dyn_cast<ExtIntType>(T))
+    return 0 + (EIT->getNumBits() << 3);
+
   switch (cast<BuiltinType>(T)->getKind()) {
   default: llvm_unreachable("getIntegerRank(): not a built-in integer");
   case BuiltinType::Bool:
@@ -7288,6 +7337,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S,
     return;
 
   case Type::Pipe:
+  case Type::ExtInt:
 #define ABSTRACT_TYPE(KIND, BASE)
 #define TYPE(KIND, BASE)
 #define DEPENDENT_TYPE(KIND, BASE) \
@@ -9381,6 +9431,21 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
     assert(LHS != RHS &&
            "Equivalent pipe types should have already been handled!");
     return {};
+  case Type::ExtInt: {
+    // Merge two ext-int types, while trying to preserve typedef info.
+    bool LHSUnsigned  = LHS->castAs<ExtIntType>()->isUnsigned();
+    bool RHSUnsigned = RHS->castAs<ExtIntType>()->isUnsigned();
+    unsigned LHSBits = LHS->castAs<ExtIntType>()->getNumBits();
+    unsigned RHSBits = RHS->castAs<ExtIntType>()->getNumBits();
+
+    // Like unsigned/int, shouldn't have a type if they dont match.
+    if (LHSUnsigned != RHSUnsigned)
+      return {};
+
+    if (LHSBits != RHSBits)
+      return {};
+    return LHS;
+  }
   }
 
   llvm_unreachable("Invalid Type::Class!");
@@ -9521,6 +9586,8 @@ unsigned ASTContext::getIntWidth(QualType T) const {
     T = ET->getDecl()->getIntegerType();
   if (T->isBooleanType())
     return 1;
+  if(const auto *EIT = T->getAs<ExtIntType>())
+    return EIT->getNumBits();
   // For builtin types, just use the standard type sizing method
   return (unsigned)getTypeSize(T);
 }

diff  --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index c29b7b2f5907..c562830c41e1 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -949,6 +949,24 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
                                   cast<PipeType>(T2)->getElementType()))
       return false;
     break;
+  case Type::ExtInt: {
+    const auto *Int1 = cast<ExtIntType>(T1);
+    const auto *Int2 = cast<ExtIntType>(T2);
+
+    if (Int1->isUnsigned() != Int2->isUnsigned() ||
+        Int1->getNumBits() != Int2->getNumBits())
+      return false;
+    break;
+  }
+  case Type::DependentExtInt: {
+    const auto *Int1 = cast<DependentExtIntType>(T1);
+    const auto *Int2 = cast<DependentExtIntType>(T2);
+
+    if (Int1->isUnsigned() != Int2->isUnsigned() ||
+        !IsStructurallyEquivalent(Context, Int1->getNumBitsExpr(),
+                                  Int2->getNumBitsExpr()))
+      return false;
+  }
   } // end switch
 
   return true;

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 5b3866d0a471..8bc7a1128e7a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10354,6 +10354,7 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) {
   case Type::ObjCInterface:
   case Type::ObjCObjectPointer:
   case Type::Pipe:
+  case Type::ExtInt:
     // GCC classifies vectors as None. We follow its lead and classify all
     // other types that don't fit into the regular classification the same way.
     return GCCTypeClass::None;

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 535bb86f0d5b..d60cacf07534 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2093,6 +2093,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
   case Type::Atomic:
   case Type::Pipe:
   case Type::MacroQualified:
+  case Type::ExtInt:
+  case Type::DependentExtInt:
     llvm_unreachable("type is illegal as a nested name specifier");
 
   case Type::SubstTemplateTypeParmPack:
@@ -3551,6 +3553,28 @@ void CXXNameMangler::mangleType(const PipeType *T) {
   Out << "8ocl_pipe";
 }
 
+void CXXNameMangler::mangleType(const ExtIntType *T) {
+  Out << "U7_ExtInt";
+  llvm::APSInt BW(32, true);
+  BW = T->getNumBits();
+  TemplateArgument TA(Context.getASTContext(), BW, getASTContext().IntTy);
+  mangleTemplateArgs(&TA, 1);
+  if (T->isUnsigned())
+    Out << "j";
+  else
+    Out << "i";
+}
+
+void CXXNameMangler::mangleType(const DependentExtIntType *T) {
+  Out << "U7_ExtInt";
+  TemplateArgument TA(T->getNumBitsExpr());
+  mangleTemplateArgs(&TA, 1);
+  if (T->isUnsigned())
+    Out << "j";
+  else
+    Out << "i";
+}
+
 void CXXNameMangler::mangleIntegerLiteral(QualType T,
                                           const llvm::APSInt &Value) {
   //  <expr-primary> ::= L <type> <value number> E # integer literal

diff  --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index af51ae07bc57..dc5c15fbef68 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -2953,6 +2953,30 @@ void MicrosoftMangleContextImpl::mangleCXXName(GlobalDecl GD,
   return Mangler.mangle(D);
 }
 
+void MicrosoftCXXNameMangler::mangleType(const ExtIntType *T, Qualifiers,
+                                         SourceRange Range) {
+  llvm::SmallString<64> TemplateMangling;
+  llvm::raw_svector_ostream Stream(TemplateMangling);
+  MicrosoftCXXNameMangler Extra(Context, Stream);
+  Stream << "?$";
+  if (T->isUnsigned())
+    Extra.mangleSourceName("_UExtInt");
+  else
+    Extra.mangleSourceName("_ExtInt");
+  Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumBits()),
+                             /*IsBoolean=*/false);
+
+  mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
+}
+
+void MicrosoftCXXNameMangler::mangleType(const DependentExtIntType *T,
+                                         Qualifiers, SourceRange Range) {
+  DiagnosticsEngine &Diags = Context.getDiags();
+  unsigned DiagID = Diags.getCustomDiagID(
+      DiagnosticsEngine::Error, "cannot mangle this DependentExtInt type yet");
+  Diags.Report(Range.getBegin(), DiagID) << Range;
+}
+
 // <this-adjustment> ::= <no-adjustment> | <static-adjustment> |
 //                       <virtual-adjustment>
 // <no-adjustment>      ::= A # private near

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 3428437c3146..982aa8962f03 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -293,6 +293,39 @@ VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
   VectorTypeBits.NumElements = nElements;
 }
 
+ExtIntType::ExtIntType(bool IsUnsigned, unsigned NumBits)
+    : Type(ExtInt, QualType{}, TypeDependence::None), IsUnsigned(IsUnsigned),
+      NumBits(NumBits) {}
+
+DependentExtIntType::DependentExtIntType(const ASTContext &Context,
+                                         bool IsUnsigned, Expr *NumBitsExpr)
+    : Type(DependentExtInt, QualType{},
+           ((NumBitsExpr->isValueDependent() || NumBitsExpr->isTypeDependent())
+                ? TypeDependence::Dependent
+                : TypeDependence::None) |
+               (NumBitsExpr->isInstantiationDependent()
+                    ? TypeDependence::Instantiation
+                    : TypeDependence::None) |
+               (NumBitsExpr->containsUnexpandedParameterPack()
+                    ? TypeDependence::VariablyModified
+                    : TypeDependence::None)),
+      Context(Context), ExprAndUnsigned(NumBitsExpr, IsUnsigned) {}
+
+bool DependentExtIntType::isUnsigned() const {
+  return ExprAndUnsigned.getInt();
+}
+
+clang::Expr *DependentExtIntType::getNumBitsExpr() const {
+  return ExprAndUnsigned.getPointer();
+}
+
+void DependentExtIntType::Profile(llvm::FoldingSetNodeID &ID,
+                                  const ASTContext &Context, bool IsUnsigned,
+                                  Expr *NumBitsExpr) {
+  ID.AddBoolean(IsUnsigned);
+  NumBitsExpr->Profile(ID, Context, true);
+}
+
 /// getArrayElementTypeNoTypeQual - If this is an array type, return the
 /// element type of the array, potentially with type qualifiers missing.
 /// This method should never be used when type qualifiers are meaningful.
@@ -1836,13 +1869,17 @@ bool Type::isIntegralType(const ASTContext &Ctx) const {
     if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
       return ET->getDecl()->isComplete();
 
-  return false;
+  return isExtIntType();
 }
 
 bool Type::isIntegralOrUnscopedEnumerationType() const {
   if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Bool &&
            BT->getKind() <= BuiltinType::Int128;
+
+  if (isExtIntType())
+    return true;
+
   return isUnscopedEnumerationType();
 }
 
@@ -1923,6 +1960,9 @@ bool Type::isSignedIntegerType() const {
       return ET->getDecl()->getIntegerType()->isSignedIntegerType();
   }
 
+  if (const ExtIntType *IT = dyn_cast<ExtIntType>(CanonicalType))
+    return IT->isSigned();
+
   return false;
 }
 
@@ -1937,6 +1977,10 @@ bool Type::isSignedIntegerOrEnumerationType() const {
       return ET->getDecl()->getIntegerType()->isSignedIntegerType();
   }
 
+  if (const ExtIntType *IT = dyn_cast<ExtIntType>(CanonicalType))
+    return IT->isSigned();
+
+
   return false;
 }
 
@@ -1963,6 +2007,9 @@ bool Type::isUnsignedIntegerType() const {
       return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
   }
 
+  if (const ExtIntType *IT = dyn_cast<ExtIntType>(CanonicalType))
+    return IT->isUnsigned();
+
   return false;
 }
 
@@ -1977,6 +2024,9 @@ bool Type::isUnsignedIntegerOrEnumerationType() const {
       return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
   }
 
+  if (const ExtIntType *IT = dyn_cast<ExtIntType>(CanonicalType))
+    return IT->isUnsigned();
+
   return false;
 }
 
@@ -2015,7 +2065,7 @@ bool Type::isRealType() const {
            BT->getKind() <= BuiltinType::Float128;
   if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
       return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
-  return false;
+  return isExtIntType();
 }
 
 bool Type::isArithmeticType() const {
@@ -2030,7 +2080,7 @@ bool Type::isArithmeticType() const {
     // false for scoped enumerations since that will disable any
     // unwanted implicit conversions.
     return !ET->getDecl()->isScoped() && ET->getDecl()->isComplete();
-  return isa<ComplexType>(CanonicalType);
+  return isa<ComplexType>(CanonicalType) || isExtIntType();
 }
 
 Type::ScalarTypeKind Type::getScalarTypeKind() const {
@@ -2059,6 +2109,8 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
     if (CT->getElementType()->isRealFloatingType())
       return STK_FloatingComplex;
     return STK_IntegralComplex;
+  } else if (isExtIntType()) {
+    return STK_Integral;
   }
 
   llvm_unreachable("unknown scalar type");
@@ -2224,6 +2276,7 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const {
   case Type::MemberPointer:
   case Type::Vector:
   case Type::ExtVector:
+  case Type::ExtInt:
     return true;
 
   case Type::Enum:
@@ -3643,6 +3696,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
     // here in error recovery.
     return CachedProperties(ExternalLinkage, false);
 
+  case Type::ExtInt:
   case Type::Builtin:
     // C++ [basic.link]p8:
     //   A type is said to have linkage if and only if:
@@ -3740,6 +3794,7 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) {
     assert(T->isInstantiationDependentType());
     return LinkageInfo::external();
 
+  case Type::ExtInt:
   case Type::Builtin:
     return LinkageInfo::external();
 
@@ -3948,6 +4003,8 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
   case Type::ObjCInterface:
   case Type::Atomic:
   case Type::Pipe:
+  case Type::ExtInt:
+  case Type::DependentExtInt:
     return false;
   }
   llvm_unreachable("bad type kind!");

diff  --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 4cc0d735ed6a..f000e1f6c932 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -227,6 +227,8 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
     case Type::ObjCInterface:
     case Type::Atomic:
     case Type::Pipe:
+    case Type::ExtInt:
+    case Type::DependentExtInt:
       CanPrefixQualifiers = true;
       break;
 
@@ -1114,6 +1116,28 @@ void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
 
 void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {}
 
+void TypePrinter::printExtIntBefore(const ExtIntType *T, raw_ostream &OS) {
+  if (T->isUnsigned())
+    OS << "unsigned ";
+  OS << "_ExtInt(" << T->getNumBits() << ")";
+  spaceBeforePlaceHolder(OS);
+}
+
+void TypePrinter::printExtIntAfter(const ExtIntType *T, raw_ostream &OS) {}
+
+void TypePrinter::printDependentExtIntBefore(const DependentExtIntType *T,
+                                             raw_ostream &OS) {
+  if (T->isUnsigned())
+    OS << "unsigned ";
+  OS << "_ExtInt(";
+  T->getNumBitsExpr()->printPretty(OS, nullptr, Policy);
+  OS << ")";
+  spaceBeforePlaceHolder(OS);
+}
+
+void TypePrinter::printDependentExtIntAfter(const DependentExtIntType *T,
+                                            raw_ostream &OS) {}
+
 /// Appends the given scope to the end of a string.
 void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
   if (DC->isTranslationUnit()) return;

diff  --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 4ea3fbca2144..e6422a7ff1c3 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -826,6 +826,17 @@ llvm::DIType *CGDebugInfo::CreateType(const AutoType *Ty) {
   return DBuilder.createUnspecifiedType("auto");
 }
 
+llvm::DIType *CGDebugInfo::CreateType(const ExtIntType *Ty) {
+
+  StringRef Name = Ty->isUnsigned() ? "unsigned _ExtInt" : "_ExtInt";
+  llvm::dwarf::TypeKind Encoding = Ty->isUnsigned()
+                                       ? llvm::dwarf::DW_ATE_unsigned
+                                       : llvm::dwarf::DW_ATE_signed;
+
+  return DBuilder.createBasicType(Name, CGM.getContext().getTypeSize(Ty),
+                                  Encoding);
+}
+
 llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
   // Bit size and offset of the type.
   llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float;
@@ -3159,6 +3170,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
   case Type::Atomic:
     return CreateType(cast<AtomicType>(Ty), Unit);
 
+  case Type::ExtInt:
+    return CreateType(cast<ExtIntType>(Ty));
   case Type::Pipe:
     return CreateType(cast<PipeType>(Ty), Unit);
 

diff  --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 4915e19753c6..34164fbec90e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -168,6 +168,7 @@ class CGDebugInfo {
   llvm::DIType *CreateType(const BuiltinType *Ty);
   llvm::DIType *CreateType(const ComplexType *Ty);
   llvm::DIType *CreateType(const AutoType *Ty);
+  llvm::DIType *CreateType(const ExtIntType *Ty);
   llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg);
   llvm::DIType *CreateType(const TypedefType *Ty, llvm::DIFile *Fg);
   llvm::DIType *CreateType(const TemplateSpecializationType *Ty,

diff  --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index ce0904234333..62a0f6c0efe6 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -760,6 +760,11 @@ class ScalarExprEmitter
                                                   llvm::Value *Zero,bool isDiv);
   // Common helper for getting how wide LHS of shift is.
   static Value *GetWidthMinusOneValue(Value* LHS,Value* RHS);
+
+  // Used for shifting constraints for OpenCL, do mask for powers of 2, URem for
+  // non powers of two.
+  Value *ConstrainShiftValue(Value *LHS, Value *RHS, const Twine &Name);
+
   Value *EmitDiv(const BinOpInfo &Ops);
   Value *EmitRem(const BinOpInfo &Ops);
   Value *EmitAdd(const BinOpInfo &Ops);
@@ -3762,6 +3767,21 @@ Value *ScalarExprEmitter::GetWidthMinusOneValue(Value* LHS,Value* RHS) {
   return llvm::ConstantInt::get(RHS->getType(), Ty->getBitWidth() - 1);
 }
 
+Value *ScalarExprEmitter::ConstrainShiftValue(Value *LHS, Value *RHS,
+                                              const Twine &Name) {
+  llvm::IntegerType *Ty;
+  if (auto *VT = dyn_cast<llvm::VectorType>(LHS->getType()))
+    Ty = cast<llvm::IntegerType>(VT->getElementType());
+  else
+    Ty = cast<llvm::IntegerType>(LHS->getType());
+
+  if (llvm::isPowerOf2_64(Ty->getBitWidth()))
+        return Builder.CreateAnd(RHS, GetWidthMinusOneValue(LHS, RHS), Name);
+
+  return Builder.CreateURem(
+      RHS, llvm::ConstantInt::get(RHS->getType(), Ty->getBitWidth()), Name);
+}
+
 Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
   // LLVM requires the LHS and RHS to be the same type: promote or truncate the
   // RHS to the same size as the LHS.
@@ -3776,8 +3796,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
   bool SanitizeExponent = CGF.SanOpts.has(SanitizerKind::ShiftExponent);
   // OpenCL 6.3j: shift values are effectively % word size of LHS.
   if (CGF.getLangOpts().OpenCL)
-    RHS =
-        Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shl.mask");
+    RHS = ConstrainShiftValue(Ops.LHS, RHS, "shl.mask");
   else if ((SanitizeBase || SanitizeExponent) &&
            isa<llvm::IntegerType>(Ops.LHS->getType())) {
     CodeGenFunction::SanitizerScope SanScope(&CGF);
@@ -3839,8 +3858,7 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
 
   // OpenCL 6.3j: shift values are effectively % word size of LHS.
   if (CGF.getLangOpts().OpenCL)
-    RHS =
-        Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shr.mask");
+    RHS = ConstrainShiftValue(Ops.LHS, RHS, "shr.mask");
   else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) &&
            isa<llvm::IntegerType>(Ops.LHS->getType())) {
     CodeGenFunction::SanitizerScope SanScope(&CGF);

diff  --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 4de64a32f2ac..75af05623b03 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -385,7 +385,8 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
         Run = FieldEnd;
         continue;
       }
-      llvm::Type *Type = Types.ConvertTypeForMem(Field->getType());
+      llvm::Type *Type =
+          Types.ConvertTypeForMem(Field->getType(), /*ForBitFields=*/true);
       // If we don't have a run yet, or don't live within the previous run's
       // allocated storage then we allocate some storage and start a new run.
       if (Run == FieldEnd || BitOffset >= Tail) {

diff  --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 05bf70e5cb22..9929c154e37b 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -257,6 +257,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
     case Type::Enum:
     case Type::ObjCObjectPointer:
     case Type::Pipe:
+    case Type::ExtInt:
       return TEK_Scalar;
 
     // Complexes.
@@ -2010,6 +2011,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
     case Type::ObjCObject:
     case Type::ObjCInterface:
     case Type::ObjCObjectPointer:
+    case Type::ExtInt:
       llvm_unreachable("type class is never variably-modified!");
 
     case Type::Adjusted:

diff  --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index 8cc8c162dfbe..f4ebe6885675 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -209,6 +209,15 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
     return createScalarTypeNode(OutName, getChar(), Size);
   }
 
+  if (const auto *EIT = dyn_cast<ExtIntType>(Ty)) {
+    SmallString<256> OutName;
+    llvm::raw_svector_ostream Out(OutName);
+    // Don't specify signed/unsigned since integer types can alias despite sign
+    // 
diff erences.
+    Out << "_ExtInt(" << EIT->getNumBits() << ')';
+    return createScalarTypeNode(OutName, getChar(), Size);
+  }
+
   // For now, handle any other kind of type conservatively.
   return getChar();
 }

diff  --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 29adc2c7adb3..d6d84a3ff051 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -83,19 +83,19 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
 /// ConvertType in that it is used to convert to the memory representation for
 /// a type.  For example, the scalar representation for _Bool is i1, but the
 /// memory representation is usually i8 or i32, depending on the target.
-llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) {
+llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T, bool ForBitField) {
   llvm::Type *R = ConvertType(T);
 
-  // If this is a non-bool type, don't map it.
-  if (!R->isIntegerTy(1))
-    return R;
+  // If this is a bool type, or an ExtIntType in a bitfield representation,
+  // map this integer to the target-specified size.
+  if ((ForBitField && T->isExtIntType()) || R->isIntegerTy(1))
+    return llvm::IntegerType::get(getLLVMContext(),
+                                  (unsigned)Context.getTypeSize(T));
 
-  // Otherwise, return an integer of the target-specified size.
-  return llvm::IntegerType::get(getLLVMContext(),
-                                (unsigned)Context.getTypeSize(T));
+  // Else, don't map it.
+  return R;
 }
 
-
 /// isRecordLayoutComplete - Return true if the specified type is already
 /// completely laid out.
 bool CodeGenTypes::isRecordLayoutComplete(const Type *Ty) const {
@@ -731,6 +731,11 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
     ResultType = CGM.getOpenCLRuntime().getPipeType(cast<PipeType>(Ty));
     break;
   }
+  case Type::ExtInt: {
+    const auto &EIT = cast<ExtIntType>(Ty);
+    ResultType = llvm::Type::getIntNTy(getLLVMContext(), EIT->getNumBits());
+    break;
+  }
   }
 
   assert(ResultType && "Didn't convert a type?");

diff  --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 03102329507e..394e2fdf8d65 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -134,7 +134,7 @@ class CodeGenTypes {
   /// ConvertType in that it is used to convert to the memory representation for
   /// a type.  For example, the scalar representation for _Bool is i1, but the
   /// memory representation is usually i8 or i32, depending on the target.
-  llvm::Type *ConvertTypeForMem(QualType T);
+  llvm::Type *ConvertTypeForMem(QualType T, bool ForBitField = false);
 
   /// GetFunctionType - Get the LLVM function type for \arg Info.
   llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info);

diff  --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index c8a73c2757ab..4a591cf7aac5 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3219,6 +3219,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
     llvm_unreachable("Pipe types shouldn't get here");
 
   case Type::Builtin:
+  case Type::ExtInt:
   // GCC treats vector and complex types as fundamental types.
   case Type::Vector:
   case Type::ExtVector:
@@ -3472,7 +3473,10 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
     llvm_unreachable("Undeduced type shouldn't get here");
 
   case Type::Pipe:
-    llvm_unreachable("Pipe type shouldn't get here");
+    break;
+
+  case Type::ExtInt:
+    break;
 
   case Type::ConstantArray:
   case Type::IncompleteArray:

diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 8bd7571f1242..fe00199c1f8f 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2880,6 +2880,25 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
                ParsedAttr::AS_Keyword, EllipsisLoc);
 }
 
+ExprResult Parser::ParseExtIntegerArgument() {
+  assert(Tok.is(tok::kw__ExtInt) && "Not an extended int type");
+  ConsumeToken();
+
+  BalancedDelimiterTracker T(*this, tok::l_paren);
+  if (T.expectAndConsume())
+    return ExprError();
+
+  ExprResult ER = ParseConstantExpression();
+  if (ER.isInvalid()) {
+    T.skipToEnd();
+    return ExprError();
+  }
+
+  if(T.consumeClose())
+    return ExprError();
+  return ER;
+}
+
 /// Determine whether we're looking at something that might be a declarator
 /// in a simple-declaration. If it can't possibly be a declarator, maybe
 /// diagnose a missing semicolon after a prior tag definition in the decl
@@ -3807,6 +3826,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
                                      DiagID, Policy);
       break;
+    case tok::kw__ExtInt: {
+      ExprResult ER = ParseExtIntegerArgument();
+      if (ER.isInvalid())
+        continue;
+      isInvalid = DS.SetExtIntType(Loc, ER.get(), PrevSpec, DiagID, Policy);
+      ConsumedEnd = PrevTokLocation;
+      break;
+    }
     case tok::kw___int128:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,
                                      DiagID, Policy);
@@ -4890,6 +4917,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
   case tok::kw_char16_t:
   case tok::kw_char32_t:
   case tok::kw_int:
+  case tok::kw__ExtInt:
   case tok::kw_half:
   case tok::kw_float:
   case tok::kw_double:
@@ -4969,6 +4997,7 @@ bool Parser::isTypeSpecifierQualifier() {
   case tok::kw_char16_t:
   case tok::kw_char32_t:
   case tok::kw_int:
+  case tok::kw__ExtInt:
   case tok::kw_half:
   case tok::kw_float:
   case tok::kw_double:
@@ -5135,6 +5164,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
   case tok::kw_char32_t:
 
   case tok::kw_int:
+  case tok::kw__ExtInt:
   case tok::kw_half:
   case tok::kw_float:
   case tok::kw_double:

diff  --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 0c6939b04319..29e583fcb84e 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1492,6 +1492,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
   case tok::kw_long:
   case tok::kw___int64:
   case tok::kw___int128:
+  case tok::kw__ExtInt:
   case tok::kw_signed:
   case tok::kw_unsigned:
   case tok::kw_half:

diff  --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index c5e895d090a5..32e9370b0e00 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -2156,6 +2156,19 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
     return;
   }
 
+  case tok::kw__ExtInt: {
+    ExprResult ER = ParseExtIntegerArgument();
+    if (ER.isInvalid())
+      DS.SetTypeSpecError();
+    else
+      DS.SetExtIntType(Loc, ER.get(), PrevSpec, DiagID, Policy);
+
+    // Do this here because we have already consumed the close paren.
+    DS.SetRangeEnd(PrevTokLocation);
+    DS.Finish(Actions, Policy);
+    return;
+  }
+
   // builtin types
   case tok::kw_short:
     DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID, Policy);

diff  --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 529e3f321054..61a82664bf71 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1141,6 +1141,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
   case tok::kw_half:
   case tok::kw_float:
   case tok::kw_int:
+  case tok::kw__ExtInt:
   case tok::kw_long:
   case tok::kw___int64:
   case tok::kw___int128:
@@ -1778,6 +1779,24 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
   case tok::kw__Atomic:
     return TPResult::True;
 
+  case tok::kw__ExtInt: {
+    if (NextToken().isNot(tok::l_paren))
+      return TPResult::Error;
+    RevertingTentativeParsingAction PA(*this);
+    ConsumeToken();
+    ConsumeParen();
+
+    if (!SkipUntil(tok::r_paren, StopAtSemi))
+      return TPResult::Error;
+
+    if (Tok.is(tok::l_paren))
+      return TPResult::Ambiguous;
+
+    if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))
+      return BracedCastResult;
+
+    return TPResult::True;
+  }
   default:
     return TPResult::False;
   }
@@ -1810,6 +1829,7 @@ bool Parser::isCXXDeclarationSpecifierAType() {
   case tok::kw_bool:
   case tok::kw_short:
   case tok::kw_int:
+  case tok::kw__ExtInt:
   case tok::kw_long:
   case tok::kw___int64:
   case tok::kw___int128:

diff  --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index ae4a78a4556d..276e35a3497e 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -360,6 +360,7 @@ bool Declarator::isDeclarationOfFunction() const {
     case TST_half:
     case TST_int:
     case TST_int128:
+    case TST_extint:
     case TST_struct:
     case TST_interface:
     case TST_union:
@@ -538,6 +539,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
   case DeclSpec::TST_char32:      return "char32_t";
   case DeclSpec::TST_int:         return "int";
   case DeclSpec::TST_int128:      return "__int128";
+  case DeclSpec::TST_extint:      return "_ExtInt";
   case DeclSpec::TST_half:        return "half";
   case DeclSpec::TST_float:       return "float";
   case DeclSpec::TST_double:      return "double";
@@ -913,6 +915,27 @@ bool DeclSpec::SetTypeSpecError() {
   return false;
 }
 
+bool DeclSpec::SetExtIntType(SourceLocation KWLoc, Expr *BitsExpr,
+                             const char *&PrevSpec, unsigned &DiagID,
+                             const PrintingPolicy &Policy) {
+  assert(BitsExpr && "no expression provided!");
+  if (TypeSpecType == TST_error)
+    return false;
+
+  if (TypeSpecType != TST_unspecified) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
+    DiagID = diag::err_invalid_decl_spec_combination;
+    return true;
+  }
+
+  TypeSpecType = TST_extint;
+  ExprRep = BitsExpr;
+  TSTLoc = KWLoc;
+  TSTNameLoc = KWLoc;
+  TypeSpecOwned = false;
+  return false;
+}
+
 bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
                            unsigned &DiagID, const LangOptions &Lang) {
   // Duplicates are permitted in C99 onwards, but are not permitted in C89 or
@@ -1194,7 +1217,7 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
       TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
     else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
              TypeSpecType != TST_char && TypeSpecType != TST_wchar &&
-             !IsFixedPointType) {
+             !IsFixedPointType && TypeSpecType != TST_extint) {
       S.Diag(TSSLoc, diag::err_invalid_sign_spec)
         << getSpecifierName((TST)TypeSpecType, Policy);
       // signed double -> double.
@@ -1241,7 +1264,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
                               S.getLocForEndOfToken(getTypeSpecComplexLoc()),
                                                  " double");
       TypeSpecType = TST_double;   // _Complex -> _Complex double.
-    } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
+    } else if (TypeSpecType == TST_int || TypeSpecType == TST_char ||
+               TypeSpecType == TST_extint) {
       // Note that this intentionally doesn't include _Complex _Bool.
       if (!S.getLangOpts().CPlusPlus)
         S.Diag(TSTLoc, diag::ext_integer_complex);

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e7bc4994e540..037e9c332412 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -9793,6 +9793,9 @@ struct IntRange {
                         false/*NonNegative*/);
     }
 
+    if (const auto *EIT = dyn_cast<ExtIntType>(T))
+      return IntRange(EIT->getNumBits(), EIT->isUnsigned());
+
     const BuiltinType *BT = cast<BuiltinType>(T);
     assert(BT->isInteger());
 
@@ -9816,6 +9819,9 @@ struct IntRange {
     if (const EnumType *ET = dyn_cast<EnumType>(T))
       T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr();
 
+    if (const auto *EIT = dyn_cast<ExtIntType>(T))
+      return IntRange(EIT->getNumBits(), EIT->isUnsigned());
+
     const BuiltinType *BT = cast<BuiltinType>(T);
     assert(BT->isInteger());
 

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ed082dbaf986..27c8365ab8be 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14811,12 +14811,16 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
   if (T->isDependentType())
     return false;
 
+  // This doesn't use 'isIntegralType' despite the error message mentioning
+  // integral type because isIntegralType would also allow enum types in C.
   if (const BuiltinType *BT = T->getAs<BuiltinType>())
     if (BT->isInteger())
       return false;
 
-  Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T;
-  return true;
+  if (T->isExtIntType())
+    return false;
+
+  return Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T;
 }
 
 /// Check whether this is a valid redeclaration of a previous enumeration.

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 3205b4472db2..869ae5cbc40b 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4087,8 +4087,9 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
     Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << CI.getRange();
     return;
   }
-  bool IntegralOrAnyEnumType =
-      OldElemTy->isIntegralOrEnumerationType() || OldElemTy->getAs<EnumType>();
+  bool IntegralOrAnyEnumType = (OldElemTy->isIntegralOrEnumerationType() &&
+                                !OldElemTy->isExtIntType()) ||
+                               OldElemTy->getAs<EnumType>();
 
   if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() &&
       !IntegralOrAnyEnumType)

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 31d694857e9c..fbb5d4b05bbf 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1482,6 +1482,11 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
   if (LHSType == RHSType)
     return LHSType;
 
+  // ExtInt types aren't subject to conversions between them or normal integers,
+  // so this fails. 
+  if(LHSType->isExtIntType() || RHSType->isExtIntType())
+    return QualType();
+
   // At this point, we have two 
diff erent arithmetic types.
 
   // Diagnose attempts to convert between __float128 and long double where
@@ -4261,6 +4266,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
     case Type::ObjCObjectPointer:
     case Type::ObjCTypeParam:
     case Type::Pipe:
+    case Type::ExtInt:
       llvm_unreachable("type class is never variably-modified!");
     case Type::Adjusted:
       T = cast<AdjustedType>(Ty)->getOriginalType();
@@ -10431,14 +10437,19 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
                             << RHS.get()->getSourceRange());
     return;
   }
-  llvm::APInt LeftBits(Right.getBitWidth(),
-                       S.Context.getTypeSize(LHS.get()->getType()));
+
+  QualType LHSExprType = LHS.get()->getType();
+  uint64_t LeftSize = LHSExprType->isExtIntType()
+                          ? S.Context.getIntWidth(LHSExprType)
+                          : S.Context.getTypeSize(LHSExprType);
+  llvm::APInt LeftBits(Right.getBitWidth(), LeftSize);
   if (Right.uge(LeftBits)) {
     S.DiagRuntimeBehavior(Loc, RHS.get(),
                           S.PDiag(diag::warn_shift_gt_typewidth)
                             << RHS.get()->getSourceRange());
     return;
   }
+
   if (Opc != BO_Shl)
     return;
 

diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 82a197196576..08d29fa51e6e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2967,6 +2967,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
     case Type::Vector:
     case Type::ExtVector:
     case Type::Complex:
+    case Type::ExtInt:
       break;
 
     // Non-deduced auto types only get here for error cases.

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index f425ec742b7b..7bd12913aec4 100755
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5998,6 +5998,15 @@ bool UnnamedLocalNoLinkageFinder::VisitPipeType(const PipeType* T) {
   return false;
 }
 
+bool UnnamedLocalNoLinkageFinder::VisitExtIntType(const ExtIntType *T) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDependentExtIntType(
+    const DependentExtIntType *T) {
+  return false;
+}
+
 bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
   if (Tag->getDeclContext()->isFunctionOrMethod()) {
     S.Diag(SR.getBegin(),
@@ -6891,7 +6900,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
       QualType IntegerType = ParamType;
       if (const EnumType *Enum = IntegerType->getAs<EnumType>())
         IntegerType = Enum->getDecl()->getIntegerType();
-      Value = Value.extOrTrunc(Context.getTypeSize(IntegerType));
+      Value = Value.extOrTrunc(IntegerType->isExtIntType()
+                                   ? Context.getIntWidth(IntegerType)
+                                   : Context.getTypeSize(IntegerType));
 
       Converted = TemplateArgument(Context, Value,
                                    Context.getCanonicalType(ParamType));
@@ -6985,7 +6996,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
 
       // Coerce the template argument's value to the value it will have
       // based on the template parameter's type.
-      unsigned AllowedBits = Context.getTypeSize(IntegerType);
+      unsigned AllowedBits = IntegerType->isExtIntType()
+                                 ? Context.getIntWidth(IntegerType)
+                                 : Context.getTypeSize(IntegerType);
       if (Value.getBitWidth() != AllowedBits)
         Value = Value.extOrTrunc(AllowedBits);
       Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());

diff  --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 8e3c61819571..e1d438fcb724 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1515,6 +1515,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
     case Type::ObjCObject:
     case Type::ObjCInterface:
     case Type::ObjCObjectPointer:
+    case Type::ExtInt:
       if (TDF & TDF_SkipNonDependent)
         return Sema::TDK_Success;
 
@@ -2106,6 +2107,33 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
 
       return Sema::TDK_NonDeducedMismatch;
     }
+    case Type::DependentExtInt: {
+      const auto *IntParam = cast<DependentExtIntType>(Param);
+
+      if (const auto *IntArg = dyn_cast<ExtIntType>(Arg)){
+        if (IntParam->isUnsigned() != IntArg->isUnsigned())
+          return Sema::TDK_NonDeducedMismatch;
+
+        NonTypeTemplateParmDecl *NTTP =
+            getDeducedParameterFromExpr(Info, IntParam->getNumBitsExpr());
+        if (!NTTP)
+          return Sema::TDK_Success;
+
+        llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
+        ArgSize = IntArg->getNumBits();
+
+        return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize,
+                                             S.Context.IntTy, true, Info,
+                                             Deduced);
+      }
+
+      if (const auto *IntArg = dyn_cast<DependentExtIntType>(Arg)) {
+        if (IntParam->isUnsigned() != IntArg->isUnsigned())
+          return Sema::TDK_NonDeducedMismatch;
+        return Sema::TDK_Success;
+      }
+      return Sema::TDK_NonDeducedMismatch;
+    }
 
     case Type::TypeOfExpr:
     case Type::TypeOf:
@@ -5850,6 +5878,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
                                cast<DeducedType>(T)->getDeducedType(),
                                OnlyDeduced, Depth, Used);
     break;
+  case Type::DependentExtInt:
+    MarkUsedTemplateParameters(Ctx,
+                               cast<DependentExtIntType>(T)->getNumBitsExpr(),
+                               OnlyDeduced, Depth, Used);
+    break;
 
   // None of these types have any template parameters in them.
   case Type::Builtin:
@@ -5862,6 +5895,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
   case Type::ObjCObjectPointer:
   case Type::UnresolvedUsing:
   case Type::Pipe:
+  case Type::ExtInt:
 #define TYPE(Class, Base)
 #define ABSTRACT_TYPE(Class, Base)
 #define DEPENDENT_TYPE(Class, Base)

diff  --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 825b062c0054..466cb084e7c3 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -847,6 +847,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
 
   case TST_typeofExpr:
   case TST_decltype:
+  case TST_extint:
     if (DS.getRepAsExpr() &&
         DS.getRepAsExpr()->containsUnexpandedParameterPack())
       return true;

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 53e4366f673b..4ecd36209e5b 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -35,6 +35,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/IR/DerivedTypes.h"
 #include "llvm/Support/ErrorHandling.h"
 
 using namespace clang;
@@ -1441,6 +1442,15 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
     }
     break;
   }
+  case DeclSpec::TST_extint: {
+    Result = S.BuildExtIntType(DS.getTypeSpecSign() == TSS_unsigned,
+                               DS.getRepAsExpr(), DS.getBeginLoc());
+    if (Result.isNull()) {
+      Result = Context.IntTy;
+      declarator.setInvalidType(true);
+    }
+    break;
+  }
   case DeclSpec::TST_accum: {
     switch (DS.getTypeSpecWidth()) {
       case DeclSpec::TSW_short:
@@ -2160,6 +2170,45 @@ QualType Sema::BuildWritePipeType(QualType T, SourceLocation Loc) {
   return Context.getWritePipeType(T);
 }
 
+/// Build a extended int type.
+///
+/// \param IsUnsigned Boolean representing the signedness of the type.
+///
+/// \param BitWidth Size of this int type in bits, or an expression representing
+/// that.
+///
+/// \param Loc Location of the keyword.
+QualType Sema::BuildExtIntType(bool IsUnsigned, Expr *BitWidth,
+                               SourceLocation Loc) {
+  if (BitWidth->isInstantiationDependent())
+    return Context.getDependentExtIntType(IsUnsigned, BitWidth);
+
+  llvm::APSInt Bits(32);
+  ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Bits);
+
+  if (ICE.isInvalid())
+    return QualType();
+
+  int64_t NumBits = Bits.getSExtValue();
+  if (!IsUnsigned && NumBits < 2) {
+    Diag(Loc, diag::err_ext_int_bad_size) << 0;
+    return QualType();
+  }
+
+  if (IsUnsigned && NumBits < 1) {
+    Diag(Loc, diag::err_ext_int_bad_size) << 1;
+    return QualType();
+  }
+
+  if (NumBits > llvm::IntegerType::MAX_INT_BITS) {
+    Diag(Loc, diag::err_ext_int_max_size) << IsUnsigned
+                                          << llvm::IntegerType::MAX_INT_BITS;
+    return QualType();
+  }
+
+  return Context.getExtIntType(IsUnsigned, NumBits);
+}
+
 /// Check whether the specified array size makes the array type a VLA.  If so,
 /// return true, if not, return the size of the array in SizeVal.
 static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
@@ -5774,6 +5823,14 @@ namespace {
       TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
     }
 
+    void VisitExtIntTypeLoc(ExtIntTypeLoc TL) {
+      TL.setNameLoc(DS.getTypeSpecTypeLoc());
+    }
+
+    void VisitDependentExtIntTypeLoc(DependentExtIntTypeLoc TL) {
+      TL.setNameLoc(DS.getTypeSpecTypeLoc());
+    }
+
     void VisitTypeLoc(TypeLoc TL) {
       // FIXME: add other typespec types and change this to an assert.
       TL.initialize(Context, DS.getTypeSpecTypeLoc());
@@ -5900,6 +5957,9 @@ namespace {
       assert(Chunk.Kind == DeclaratorChunk::Pipe);
       TL.setKWLoc(Chunk.Loc);
     }
+    void VisitExtIntTypeLoc(ExtIntTypeLoc TL) {
+      TL.setNameLoc(Chunk.Loc);
+    }
     void VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {
       TL.setExpansionLoc(Chunk.Loc);
     }
@@ -8631,6 +8691,12 @@ QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
     else if (!T.isTriviallyCopyableType(Context))
       // Some other non-trivially-copyable type (probably a C++ class)
       DisallowedKind = 7;
+    else if (auto *ExtTy = T->getAs<ExtIntType>()) {
+      if (ExtTy->getNumBits() < 8)
+        DisallowedKind = 8;
+      else if (!llvm::isPowerOf2_32(ExtTy->getNumBits()))
+        DisallowedKind = 9;
+    }
 
     if (DisallowedKind != -1) {
       Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 87b07897ec28..abde968bed8c 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1183,6 +1183,14 @@ class TreeTransform {
   QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc,
                            bool isReadPipe);
 
+   /// Build an extended int given its value type.
+  QualType RebuildExtIntType(bool IsUnsigned, unsigned NumBits,
+                             SourceLocation Loc);
+
+  /// Build a dependent extended int given its value type.
+  QualType RebuildDependentExtIntType(bool IsUnsigned, Expr *NumBitsExpr,
+                                      SourceLocation Loc);
+
   /// Build a new template name given a nested name specifier, a flag
   /// indicating whether the "template" keyword was provided, and the template
   /// that the template name refers to.
@@ -6120,6 +6128,57 @@ QualType TreeTransform<Derived>::TransformPipeType(TypeLocBuilder &TLB,
   return Result;
 }
 
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformExtIntType(TypeLocBuilder &TLB,
+                                                     ExtIntTypeLoc TL) {
+  const ExtIntType *EIT = TL.getTypePtr();
+  QualType Result = TL.getType();
+
+  if (getDerived().AlwaysRebuild()) {
+    Result = getDerived().RebuildExtIntType(EIT->isUnsigned(),
+                                            EIT->getNumBits(), TL.getNameLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  ExtIntTypeLoc NewTL = TLB.push<ExtIntTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+  return Result;
+}
+
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformDependentExtIntType(
+    TypeLocBuilder &TLB, DependentExtIntTypeLoc TL) {
+  const DependentExtIntType *EIT = TL.getTypePtr();
+
+  EnterExpressionEvaluationContext Unevaluated(
+      SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+  ExprResult BitsExpr = getDerived().TransformExpr(EIT->getNumBitsExpr());
+  BitsExpr = SemaRef.ActOnConstantExpression(BitsExpr);
+
+  if (BitsExpr.isInvalid())
+    return QualType();
+
+  QualType Result = TL.getType();
+
+  if (getDerived().AlwaysRebuild() || BitsExpr.get() != EIT->getNumBitsExpr()) {
+    Result = getDerived().RebuildDependentExtIntType(
+        EIT->isUnsigned(), BitsExpr.get(), TL.getNameLoc());
+
+    if (Result.isNull())
+      return QualType();
+  }
+
+  if (isa<DependentExtIntType>(Result)) {
+    DependentExtIntTypeLoc NewTL = TLB.push<DependentExtIntTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+  } else {
+    ExtIntTypeLoc NewTL = TLB.push<ExtIntTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+  }
+  return Result;
+}
+
   /// Simple iterator that traverses the template arguments in a
   /// container that provides a \c getArgLoc() member function.
   ///
@@ -13782,6 +13841,23 @@ QualType TreeTransform<Derived>::RebuildPipeType(QualType ValueType,
                     : SemaRef.BuildWritePipeType(ValueType, KWLoc);
 }
 
+template <typename Derived>
+QualType TreeTransform<Derived>::RebuildExtIntType(bool IsUnsigned,
+                                                   unsigned NumBits,
+                                                   SourceLocation Loc) {
+  llvm::APInt NumBitsAP(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy),
+                        NumBits, true);
+  IntegerLiteral *Bits = IntegerLiteral::Create(SemaRef.Context, NumBitsAP,
+                                                SemaRef.Context.IntTy, Loc);
+  return SemaRef.BuildExtIntType(IsUnsigned, Bits, Loc);
+}
+
+template <typename Derived>
+QualType TreeTransform<Derived>::RebuildDependentExtIntType(
+    bool IsUnsigned, Expr *NumBitsExpr, SourceLocation Loc) {
+  return SemaRef.BuildExtIntType(IsUnsigned, NumBitsExpr, Loc);
+}
+
 template<typename Derived>
 TemplateName
 TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,

diff  --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f0e9bbd4dcea..62dd233aab3f 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6719,6 +6719,15 @@ void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) {
   TL.setKWLoc(readSourceLocation());
 }
 
+void TypeLocReader::VisitExtIntTypeLoc(clang::ExtIntTypeLoc TL) {
+  TL.setNameLoc(readSourceLocation());
+}
+void TypeLocReader::VisitDependentExtIntTypeLoc(
+    clang::DependentExtIntTypeLoc TL) {
+  TL.setNameLoc(readSourceLocation());
+}
+
+
 void ASTRecordReader::readTypeLoc(TypeLoc TL) {
   TypeLocReader TLR(*this);
   for (; !TL.isNull(); TL = TL.getNextTypeLoc())

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index c8ce3edda60b..18a92aaadd52 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -476,6 +476,14 @@ void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) {
   Record.AddSourceLocation(TL.getKWLoc());
 }
 
+void TypeLocWriter::VisitExtIntTypeLoc(clang::ExtIntTypeLoc TL) {
+  Record.AddSourceLocation(TL.getNameLoc());
+}
+void TypeLocWriter::VisitDependentExtIntTypeLoc(
+    clang::DependentExtIntTypeLoc TL) {
+  Record.AddSourceLocation(TL.getNameLoc());
+}
+
 void ASTWriter::WriteTypeAbbrevs() {
   using namespace llvm;
 

diff  --git a/clang/test/CodeGen/ext-int-sanitizer.cpp b/clang/test/CodeGen/ext-int-sanitizer.cpp
new file mode 100644
index 000000000000..ddf3180e1a1b
--- /dev/null
+++ b/clang/test/CodeGen/ext-int-sanitizer.cpp
@@ -0,0 +1,265 @@
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s 
+
+
+// CHECK: define void @_Z6BoundsRA10_KiU7_ExtIntILi15EEi
+void Bounds(const int (&Array)[10], _ExtInt(15) Index) {
+  int I1 = Array[Index];
+  // CHECK: %[[SEXT:.+]] = sext i15 %{{.+}} to i64
+  // CHECK: %[[CMP:.+]] = icmp ult i64 %[[SEXT]], 10
+  // CHECK: br i1 %[[CMP]]
+  // CHECK: call void @__ubsan_handle_out_of_bounds
+}
+
+// CHECK: define void @_Z4Enumv
+void Enum() {
+  enum E1 { e1a = 0, e1b = 127 }
+  e1;
+  enum E2 { e2a = -1, e2b = 64 }
+  e2;
+  enum E3 { e3a = (1u << 31) - 1 }
+  e3;
+
+  _ExtInt(34) a = e1;
+  // CHECK: %[[E1:.+]] = icmp ule i32 %{{.*}}, 127
+  // CHECK: br i1 %[[E1]]
+  // CHECK: call void @__ubsan_handle_load_invalid_value_abort
+  _ExtInt(34) b = e2;
+  // CHECK: %[[E2HI:.*]] = icmp sle i32 {{.*}}, 127
+  // CHECK: %[[E2LO:.*]] = icmp sge i32 {{.*}}, -128
+  // CHECK: %[[E2:.*]] = and i1 %[[E2HI]], %[[E2LO]]
+  // CHECK: br i1 %[[E2]]
+  // CHECK: call void @__ubsan_handle_load_invalid_value_abort
+  _ExtInt(34) c = e3;
+  // CHECK: %[[E3:.*]] = icmp ule i32 {{.*}}, 2147483647
+  // CHECK: br i1 %[[E3]]
+  // CHECK: call void @__ubsan_handle_load_invalid_value_abort
+}
+
+// CHECK: define void @_Z13FloatOverflowfd
+void FloatOverflow(float f, double d) {
+  _ExtInt(10) E = f;
+  // CHECK: fcmp ogt float %{{.+}}, -5.130000e+02
+  // CHECK: fcmp olt float %{{.+}}, 5.120000e+02
+  _ExtInt(10) E2 = d;
+  // CHECK: fcmp ogt double %{{.+}}, -5.130000e+02
+  // CHECK: fcmp olt double %{{.+}}, 5.120000e+02
+  _ExtInt(7) E3 = f;
+  // CHECK: fcmp ogt float %{{.+}}, -6.500000e+01
+  // CHECK: fcmp olt float %{{.+}}, 6.400000e+01
+  _ExtInt(7) E4 = d;
+  // CHECK: fcmp ogt double %{{.+}}, -6.500000e+01
+  // CHECK: fcmp olt double %{{.+}}, 6.400000e+01
+}
+
+// CHECK: define void @_Z14UIntTruncationU7_ExtIntILi35EEjjy
+void UIntTruncation(unsigned _ExtInt(35) E, unsigned int i, unsigned long long ll) {
+
+  i = E;
+  // CHECK: %[[LOADE:.+]] = load i35
+  // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADE]] to i32
+  // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i35
+  // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADE]]
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_implicit_conversion_abort
+
+  E = ll;
+  // CHECK: %[[LOADLL:.+]] = load i64
+  // CHECK: %[[CONV:.+]] = trunc i64 %[[LOADLL]] to i35
+  // CHECK: %[[EXT:.+]] = zext i35 %[[CONV]] to i64
+  // CHECK: %[[CHECK:.+]] = icmp eq i64 %[[EXT]], %[[LOADLL]]
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_implicit_conversion_abort
+}
+
+// CHECK: define void @_Z13IntTruncationU7_ExtIntILi35EEiU7_ExtIntILi42EEjij
+void IntTruncation(_ExtInt(35) E, unsigned _ExtInt(42) UE, int i, unsigned j) {
+
+  j = E;
+  // CHECK: %[[LOADE:.+]] = load i35
+  // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADE]] to i32
+  // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i35
+  // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADE]]
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_implicit_conversion_abort
+
+  j = UE;
+  // CHECK: %[[LOADUE:.+]] = load i42
+  // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADUE]] to i32
+  // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i42
+  // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADUE]]
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_implicit_conversion_abort
+
+  // Note: also triggers sign change check.
+  i = UE;
+  // CHECK: %[[LOADUE:.+]] = load i42
+  // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADUE]] to i32
+  // CHECK: %[[NEG:.+]] = icmp slt i32 %[[CONV]], 0
+  // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
+  // CHECK: %[[EXT:.+]] = sext i32 %[[CONV]] to i42
+  // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADUE]]
+  // CHECK: %[[CHECKBOTH:.+]] = and i1 %[[SIGNCHECK]], %[[CHECK]]
+  // CHECK: br i1 %[[CHECKBOTH]]
+  // CHECK: call void @__ubsan_handle_implicit_conversion_abort
+
+  // Note: also triggers sign change check.
+  E = UE;
+  // CHECK: %[[LOADUE:.+]] = load i42
+  // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADUE]] to i35
+  // CHECK: %[[NEG:.+]] = icmp slt i35 %[[CONV]], 0
+  // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
+  // CHECK: %[[EXT:.+]] = sext i35 %[[CONV]] to i42
+  // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADUE]]
+  // CHECK: %[[CHECKBOTH:.+]] = and i1 %[[SIGNCHECK]], %[[CHECK]]
+  // CHECK: br i1 %[[CHECKBOTH]]
+  // CHECK: call void @__ubsan_handle_implicit_conversion_abort
+}
+
+// CHECK: define void @_Z15SignChangeCheckU7_ExtIntILi39EEjU7_ExtIntILi39EEi
+void SignChangeCheck(unsigned _ExtInt(39) UE, _ExtInt(39) E) {
+  UE = E;
+  // CHECK: %[[LOADE:.+]] = load i39
+  // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADE]], 0
+  // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 %[[NEG]], false
+  // CHECK: br i1 %[[SIGNCHECK]]
+  // CHECK: call void @__ubsan_handle_implicit_conversion_abort
+
+
+  E = UE;
+  // CHECK: %[[LOADUE:.+]] = load i39
+  // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADUE]], 0
+  // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
+  // CHECK: br i1 %[[SIGNCHECK]]
+  // CHECK: call void @__ubsan_handle_implicit_conversion_abort
+}
+
+// CHECK: define void @_Z9DivByZeroU7_ExtIntILi11EEii
+void DivByZero(_ExtInt(11) E, int i) {
+
+  // Also triggers signed integer overflow.
+  E / E;
+  // CHECK: %[[E:.+]] = load i11, i11*
+  // CHECK: %[[E2:.+]] = load i11, i11*
+  // CHECK: %[[NEZERO:.+]] = icmp ne i11 %[[E2]], 0
+  // CHECK: %[[NEMIN:.+]] = icmp ne i11 %[[E]], -1024
+  // CHECK: %[[NENEG1:.+]] = icmp ne i11 %[[E2]], -1
+  // CHECK: %[[OR:.+]] = or i1 %[[NEMIN]], %[[NENEG1]]
+  // CHECK: %[[AND:.+]] = and i1 %[[NEZERO]], %[[OR]]
+  // CHECK: br i1 %[[AND]]
+  // CHECK: call void @__ubsan_handle_divrem_overflow_abort
+}
+
+// TODO:
+//-fsanitize=shift: (shift-base, shift-exponent) Shift operators where the amount shifted is greater or equal to the promoted bit-width of the left hand side or less than zero, or where the left hand side is negative. For a signed left shift, also checks for signed overflow in C, and for unsigned overflow in C++. You can use -fsanitize=shift-base or -fsanitize=shift-exponent to check only left-hand side or right-hand side of shift operation, respectively.
+// CHECK: define void @_Z6ShiftsU7_ExtIntILi9EEi
+void Shifts(_ExtInt(9) E) {
+  E >> E;
+  // CHECK: %[[LHSE:.+]] = load i9, i9*
+  // CHECK: %[[RHSE:.+]] = load i9, i9*
+  // CHECK: %[[CMP:.+]] = icmp ule i9 %[[RHSE]], 8
+  // CHECK: br i1 %[[CMP]]
+  // CHECK: call void @__ubsan_handle_shift_out_of_bounds_abort
+
+  E << E;
+  // CHECK: %[[LHSE:.+]] = load i9, i9*
+  // CHECK: %[[RHSE:.+]] = load i9, i9*
+  // CHECK: %[[CMP:.+]] = icmp ule i9 %[[RHSE]], 8
+  // CHECK: br i1 %[[CMP]]
+  // CHECK: %[[ZEROS:.+]] = sub nuw nsw i9 8, %[[RHSE]]
+  // CHECK: %[[CHECK:.+]] = lshr i9 %[[LHSE]], %[[ZEROS]]
+  // CHECK: %[[SKIPSIGN:.+]] = lshr i9 %[[CHECK]], 1
+  // CHECK: %[[CHECK:.+]] = icmp eq i9 %[[SKIPSIGN]]
+  // CHECK: %[[PHI:.+]] = phi i1 [ true, %{{.+}} ], [ %[[CHECK]], %{{.+}} ]
+  // CHECK: and i1 %[[CMP]], %[[PHI]]
+  // CHECK: call void @__ubsan_handle_shift_out_of_bounds_abort
+}
+
+// CHECK: define void @_Z21SignedIntegerOverflowU7_ExtIntILi93EEiU7_ExtIntILi4EEiU7_ExtIntILi31EEi
+void SignedIntegerOverflow(_ExtInt(93) BiggestE,
+                           _ExtInt(4) SmallestE,
+                           _ExtInt(31) JustRightE) {
+  BiggestE + BiggestE;
+  // CHECK: %[[LOAD1:.+]] = load i93, i93*
+  // CHECK: %[[LOAD2:.+]] = load i93, i93*
+  // CHECK: %[[OFCALL:.+]] = call { i93, i1 } @llvm.sadd.with.overflow.i93(i93 %[[LOAD1]], i93 %[[LOAD2]])
+  // CHECK: %[[EXRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 0
+  // CHECK: %[[OFRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 1
+  // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_add_overflow_abort
+
+  SmallestE - SmallestE;
+  // CHECK: %[[LOAD1:.+]] = load i4, i4*
+  // CHECK: %[[LOAD2:.+]] = load i4, i4*
+  // CHECK: %[[OFCALL:.+]] = call { i4, i1 } @llvm.ssub.with.overflow.i4(i4 %[[LOAD1]], i4 %[[LOAD2]])
+  // CHECK: %[[EXRESULT:.+]] = extractvalue { i4, i1 } %[[OFCALL]], 0
+  // CHECK: %[[OFRESULT:.+]] = extractvalue { i4, i1 } %[[OFCALL]], 1
+  // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_sub_overflow_abort
+
+  JustRightE * JustRightE;
+  // CHECK: %[[LOAD1:.+]] = load i31, i31*
+  // CHECK: %[[LOAD2:.+]] = load i31, i31*
+  // CHECK: %[[OFCALL:.+]] = call { i31, i1 } @llvm.smul.with.overflow.i31(i31 %[[LOAD1]], i31 %[[LOAD2]])
+  // CHECK: %[[EXRESULT:.+]] = extractvalue { i31, i1 } %[[OFCALL]], 0
+  // CHECK: %[[OFRESULT:.+]] = extractvalue { i31, i1 } %[[OFCALL]], 1
+  // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_mul_overflow_abort
+}
+
+// CHECK: define void @_Z23UnsignedIntegerOverflowjU7_ExtIntILi23EEjU7_ExtIntILi35EEj
+void UnsignedIntegerOverflow(unsigned u,
+                             unsigned _ExtInt(23) SmallE,
+                             unsigned _ExtInt(35) BigE) {
+  u = SmallE + SmallE;
+  // CHECK: %[[LOADE1:.+]] = load i23, i23*
+  // CHECK: %[[LOADE2:.+]] = load i23, i23*
+  // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADE1]], i23 %[[LOADE2]])
+  // CHECK: %[[EXRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 0
+  // CHECK: %[[OFRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 1
+  // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_add_overflow_abort
+
+  SmallE = u + u;
+  // CHECK: %[[LOADU1:.+]] = load i32, i32*
+  // CHECK: %[[LOADU2:.+]] = load i32, i32*
+  // CHECK: %[[OFCALL:.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %[[LOADU1]], i32 %[[LOADU2]])
+  // CHECK: %[[EXRESULT:.+]] = extractvalue { i32, i1 } %[[OFCALL]], 0
+  // CHECK: %[[OFRESULT:.+]] = extractvalue { i32, i1 } %[[OFCALL]], 1
+  // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_add_overflow_abort
+
+  SmallE = SmallE + SmallE;
+  // CHECK: %[[LOADE1:.+]] = load i23, i23*
+  // CHECK: %[[LOADE2:.+]] = load i23, i23*
+  // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADE1]], i23 %[[LOADE2]])
+  // CHECK: %[[EXRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 0
+  // CHECK: %[[OFRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 1
+  // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_add_overflow_abort
+
+  SmallE = BigE + BigE;
+  // CHECK: %[[LOADE1:.+]] = load i35, i35*
+  // CHECK: %[[LOADE2:.+]] = load i35, i35*
+  // CHECK: %[[OFCALL:.+]] = call { i35, i1 } @llvm.uadd.with.overflow.i35(i35 %[[LOADE1]], i35 %[[LOADE2]])
+  // CHECK: %[[EXRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 0
+  // CHECK: %[[OFRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 1
+  // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_add_overflow_abort
+
+  BigE = BigE + BigE;
+  // CHECK: %[[LOADE1:.+]] = load i35, i35*
+  // CHECK: %[[LOADE2:.+]] = load i35, i35*
+  // CHECK: %[[OFCALL:.+]] = call { i35, i1 } @llvm.uadd.with.overflow.i35(i35 %[[LOADE1]], i35 %[[LOADE2]])
+  // CHECK: %[[EXRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 0
+  // CHECK: %[[OFRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 1
+  // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
+  // CHECK: br i1 %[[CHECK]]
+  // CHECK: call void @__ubsan_handle_add_overflow_abort
+}

diff  --git a/clang/test/CodeGen/ext-int.c b/clang/test/CodeGen/ext-int.c
new file mode 100644
index 000000000000..ef48dd331652
--- /dev/null
+++ b/clang/test/CodeGen/ext-int.c
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -triple x86_64-windows-pc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK
+
+
+void GenericTest(_ExtInt(3) a, unsigned _ExtInt(3) b, _ExtInt(4) c) {
+  // CHECK: define {{.*}}void @GenericTest
+  int which = _Generic(a, _ExtInt(3): 1, unsigned _ExtInt(3) : 2, _ExtInt(4) : 3);
+  // CHECK: store i32 1
+  int which2 = _Generic(b, _ExtInt(3): 1, unsigned _ExtInt(3) : 2, _ExtInt(4) : 3);
+  // CHECK: store i32 2
+  int which3 = _Generic(c, _ExtInt(3): 1, unsigned _ExtInt(3) : 2, _ExtInt(4) : 3);
+  // CHECK: store i32 3
+}
+
+void VLATest(_ExtInt(3) A, _ExtInt(99) B, _ExtInt(123456) C) {
+  // CHECK: define {{.*}}void @VLATest
+  int AR1[A];
+  // CHECK: %[[A:.+]] = zext i3 %{{.+}} to i64
+  // CHECK: %[[VLA1:.+]] = alloca i32, i64 %[[A]]
+  int AR2[B];
+  // CHECK: %[[B:.+]] = trunc i99 %{{.+}} to i64
+  // CHECK: %[[VLA2:.+]] = alloca i32, i64 %[[B]]
+  int AR3[C];
+  // CHECK: %[[C:.+]] = trunc i123456 %{{.+}} to i64
+  // CHECK: %[[VLA3:.+]] = alloca i32, i64 %[[C]]
+}
+
+struct S {
+  _ExtInt(17) A;
+  _ExtInt(16777200) B;
+  _ExtInt(17) C;
+};
+
+void OffsetOfTest() {
+  // CHECK: define {{.*}}void @OffsetOfTest 
+  int A = __builtin_offsetof(struct S,A);
+  // CHECK: store i32 0, i32* %{{.+}}
+  int B = __builtin_offsetof(struct S,B);
+  // CHECK: store i32 8, i32* %{{.+}}
+  int C = __builtin_offsetof(struct S,C);
+  // CHECK: store i32 2097160, i32* %{{.+}}
+}
+
+

diff  --git a/clang/test/CodeGenCXX/ext-int.cpp b/clang/test/CodeGenCXX/ext-int.cpp
new file mode 100644
index 000000000000..4e0c58fe1e40
--- /dev/null
+++ b/clang/test/CodeGenCXX/ext-int.cpp
@@ -0,0 +1,432 @@
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -O3 -disable-llvm-passes -I%S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LIN,NoNewStructPathTBAA
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -O3 -disable-llvm-passes -I%S -new-struct-path-tbaa -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LIN,NewStructPathTBAA
+
+// RUN: %clang_cc1 -triple x86_64-windows-pc -O3 -disable-llvm-passes -I%S -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WIN,NoNewStructPathTBAA
+// RUN: %clang_cc1 -triple x86_64-windows-pc -O3 -disable-llvm-passes -I%S -new-struct-path-tbaa -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WIN,NewStructPathTBAA
+
+#include <typeinfo>
+
+// Ensure that the layout for these structs is the same as the normal bitfield
+// layouts.
+struct BitFieldsByte {
+  _ExtInt(7) A : 3;
+  _ExtInt(7) B : 3;
+  _ExtInt(7) C : 2;
+};
+// CHECK: %struct.BitFieldsByte = type { i8 }
+
+struct BitFieldsShort {
+  _ExtInt(15) A : 3;
+  _ExtInt(15) B : 3;
+  _ExtInt(15) C : 2;
+};
+// LIN: %struct.BitFieldsShort = type { i8, i8 }
+// WIN: %struct.BitFieldsShort = type { i16 }
+
+struct BitFieldsInt {
+  _ExtInt(31) A : 3;
+  _ExtInt(31) B : 3;
+  _ExtInt(31) C : 2;
+};
+// LIN: %struct.BitFieldsInt = type { i8, [3 x i8] }
+// WIN: %struct.BitFieldsInt = type { i32 }
+
+struct BitFieldsLong {
+  _ExtInt(63) A : 3;
+  _ExtInt(63) B : 3;
+  _ExtInt(63) C : 2;
+};
+// LIN: %struct.BitFieldsLong = type { i8, [7 x i8] }
+// WIN: %struct.BitFieldsLong = type { i64 }
+
+struct HasExtIntFirst {
+  _ExtInt(35) A;
+  int B;
+};
+// CHECK: %struct.HasExtIntFirst = type { i35, i32 }
+
+struct HasExtIntLast {
+  int A;
+  _ExtInt(35) B;
+};
+// CHECK: %struct.HasExtIntLast = type { i32, i35 }
+
+struct HasExtIntMiddle {
+  int A;
+  _ExtInt(35) B;
+  int C;
+};
+// CHECK: %struct.HasExtIntMiddle = type { i32, i35, i32 }
+
+// Force emitting of the above structs.
+void StructEmit() {
+  BitFieldsByte A;
+  BitFieldsShort B;
+  BitFieldsInt C;
+  BitFieldsLong D;
+
+  HasExtIntFirst E;
+  HasExtIntLast F;
+  HasExtIntMiddle G;
+}
+
+void BitfieldAssignment() {
+  // LIN: define void @_Z18BitfieldAssignmentv
+  // WIN: define dso_local void  @"?BitfieldAssignment@@YAXXZ"
+  BitFieldsByte B;
+  B.A = 3;
+  B.B = 2;
+  B.C = 1;
+  // First one is used for the lifetime start, skip that.
+  // CHECK: bitcast %struct.BitFieldsByte*
+  // CHECK: %[[BFType:.+]] = bitcast %struct.BitFieldsByte*
+  // CHECK: %[[LOADA:.+]] = load i8, i8* %[[BFType]]
+  // CHECK: %[[CLEARA:.+]] = and i8 %[[LOADA]], -8
+  // CHECK: %[[SETA:.+]] = or i8 %[[CLEARA]], 3
+  // CHECK: %[[BFType:.+]] = bitcast %struct.BitFieldsByte*
+  // CHECK: %[[LOADB:.+]] = load i8, i8* %[[BFType]]
+  // CHECK: %[[CLEARB:.+]] = and i8 %[[LOADB]], -57
+  // CHECK: %[[SETB:.+]] = or i8 %[[CLEARB]], 16
+  // CHECK: %[[BFType:.+]] = bitcast %struct.BitFieldsByte*
+  // CHECK: %[[LOADC:.+]] = load i8, i8* %[[BFType]]
+  // CHECK: %[[CLEARC:.+]] = and i8 %[[LOADC]], 63
+  // CHECK: %[[SETC:.+]] = or i8 %[[CLEARC]], 64
+}
+
+enum AsEnumUnderlyingType : _ExtInt(9) {
+  A,B,C
+};
+
+void UnderlyingTypeUsage(AsEnumUnderlyingType Param) {
+  // LIN: define void @_Z19UnderlyingTypeUsage20AsEnumUnderlyingType(i9 %
+  // WIN: define dso_local void @"?UnderlyingTypeUsage@@YAXW4AsEnumUnderlyingType@@@Z"(i9 %
+  AsEnumUnderlyingType Var;
+  // CHECK: alloca i9, align 2
+  // CHECK: store i9 %{{.*}}, align 2
+}
+
+unsigned _ExtInt(33) ManglingTestRetParam(unsigned _ExtInt(33) Param) {
+// LIN: define i33 @_Z20ManglingTestRetParamU7_ExtIntILi33EEj(i33 %
+// WIN: define dso_local i33 @"?ManglingTestRetParam@@YAU?$_UExtInt@$0CB@@__clang@@U12@@Z"(i33
+  return 0;
+}
+
+_ExtInt(33) ManglingTestRetParam(_ExtInt(33) Param) {
+// LIN: define i33 @_Z20ManglingTestRetParamU7_ExtIntILi33EEi(i33 %
+// WIN: define dso_local i33 @"?ManglingTestRetParam@@YAU?$_ExtInt@$0CB@@__clang@@U12@@Z"(i33
+  return 0;
+}
+
+template<typename T>
+void ManglingTestTemplateParam(T&);
+template<_ExtInt(99) T>
+void ManglingTestNTTP();
+
+void ManglingInstantiator() {
+  // LIN: define void @_Z20ManglingInstantiatorv()
+  // WIN: define dso_local void @"?ManglingInstantiator@@YAXXZ"()
+  _ExtInt(93) A;
+  ManglingTestTemplateParam(A);
+// LIN: call void @_Z25ManglingTestTemplateParamIU7_ExtIntILi93EEiEvRT_(i93*
+// WIN: call void @"??$ManglingTestTemplateParam at U?$_ExtInt@$0FN@@__clang@@@@YAXAEAU?$_ExtInt@$0FN@@__clang@@@Z"(i93*
+  constexpr _ExtInt(93) B = 993;
+  ManglingTestNTTP<38>();
+// LIN: call void @_Z16ManglingTestNTTPILU7_ExtIntILi99EEi38EEvv()
+// WIN: call void @"??$ManglingTestNTTP@$0CG@@@YAXXZ"()
+  ManglingTestNTTP<B>();
+// LIN: call void @_Z16ManglingTestNTTPILU7_ExtIntILi99EEi993EEvv()
+// WIN: call void @"??$ManglingTestNTTP@$0DOB@@@YAXXZ"()
+}
+
+void TakesVarargs(int i, ...) {
+  // LIN: define void @_Z12TakesVarargsiz(i32 %i, ...)
+  // WIN: define dso_local void @"?TakesVarargs@@YAXHZZ"(i32 %i, ...)
+
+  __builtin_va_list args;
+  // LIN: %[[ARGS:.+]] = alloca [1 x %struct.__va_list_tag]
+  // WIN: %[[ARGS:.+]] = alloca i8*
+  __builtin_va_start(args, i);
+  // LIN: %[[STARTAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
+  // LIN: %[[STARTAD1:.+]] = bitcast %struct.__va_list_tag* %[[STARTAD]] to i8*
+  // LIN: call void @llvm.va_start(i8* %[[STARTAD1]])
+  // WIN: %[[ARGSLLIFETIMESTART:.+]] = bitcast i8** %[[ARGS]] to i8*
+  // WIN: %[[ARGSSTART:.+]] = bitcast i8** %[[ARGS]] to i8*
+  // WIN: call void @llvm.va_start(i8* %[[ARGSSTART]])
+
+  _ExtInt(92) A = __builtin_va_arg(args, _ExtInt(92));
+  // LIN: %[[AD1:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
+  // LIN: %[[OFA_P1:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD1]], i32 0, i32 2
+  // LIN: %[[OFA1:.+]] = load i8*, i8** %[[OFA_P1]]
+  // LIN: %[[BC1:.+]] = bitcast i8* %[[OFA1]] to i92*
+  // LIN: %[[OFANEXT1:.+]] = getelementptr i8, i8* %[[OFA1]], i32 16
+  // LIN: store i8* %[[OFANEXT1]], i8** %[[OFA_P1]]
+  // LIN: %[[LOAD1:.+]] = load i92, i92* %[[BC1]]
+  // LIN: store i92 %[[LOAD1]], i92*
+  // WIN: %[[CUR1:.+]] = load i8*, i8** %[[ARGS]]
+  // WIN: %[[NEXT1:.+]] = getelementptr inbounds i8, i8* %[[CUR1]], i64 16
+  // WIN: store i8* %[[NEXT1]], i8** %[[ARGS]]
+  // WIN: %[[BC1:.+]] = bitcast i8* %[[CUR1]] to i92*
+  // WIN: %[[LOADV1:.+]] = load i92, i92* %[[BC1]]
+  // WIN: store i92 %[[LOADV1]], i92*
+
+  _ExtInt(31) B = __builtin_va_arg(args, _ExtInt(31));
+  // LIN: %[[AD2:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
+  // LIN: %[[OFA_P2:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD2]], i32 0, i32 2
+  // LIN: %[[OFA2:.+]] = load i8*, i8** %[[OFA_P2]]
+  // LIN: %[[BC2:.+]] = bitcast i8* %[[OFA2]] to i31*
+  // LIN: %[[OFANEXT2:.+]] = getelementptr i8, i8* %[[OFA2]], i32 8
+  // LIN: store i8* %[[OFANEXT2]], i8** %[[OFA_P2]]
+  // LIN: %[[LOAD2:.+]] = load i31, i31* %[[BC2]]
+  // LIN: store i31 %[[LOAD2]], i31*
+  // WIN: %[[CUR2:.+]] = load i8*, i8** %[[ARGS]]
+  // WIN: %[[NEXT2:.+]] = getelementptr inbounds i8, i8* %[[CUR2]], i64 8 
+  // WIN: store i8* %[[NEXT2]], i8** %[[ARGS]]
+  // WIN: %[[BC2:.+]] = bitcast i8* %[[CUR2]] to i31*
+  // WIN: %[[LOADV2:.+]] = load i31, i31* %[[BC2]]
+  // WIN: store i31 %[[LOADV2]], i31*
+
+  _ExtInt(16) C = __builtin_va_arg(args, _ExtInt(16));
+  // LIN: %[[AD3:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
+  // LIN: %[[OFA_P3:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD3]], i32 0, i32 2
+  // LIN: %[[OFA3:.+]] = load i8*, i8** %[[OFA_P3]]
+  // LIN: %[[BC3:.+]] = bitcast i8* %[[OFA3]] to i16*
+  // LIN: %[[OFANEXT3:.+]] = getelementptr i8, i8* %[[OFA3]], i32 8
+  // LIN: store i8* %[[OFANEXT3]], i8** %[[OFA_P3]]
+  // LIN: %[[LOAD3:.+]] = load i16, i16* %[[BC3]]
+  // LIN: store i16 %[[LOAD3]], i16*
+  // WIN: %[[CUR3:.+]] = load i8*, i8** %[[ARGS]]
+  // WIN: %[[NEXT3:.+]] = getelementptr inbounds i8, i8* %[[CUR3]], i64 8
+  // WIN: store i8* %[[NEXT3]], i8** %[[ARGS]]
+  // WIN: %[[BC3:.+]] = bitcast i8* %[[CUR3]] to i16*
+  // WIN: %[[LOADV3:.+]] = load i16, i16* %[[BC3]]
+  // WIN: store i16 %[[LOADV3]], i16*
+
+  _ExtInt(129) D = __builtin_va_arg(args, _ExtInt(129));
+  // LIN: %[[AD4:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
+  // LIN: %[[OFA_P4:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD4]], i32 0, i32 2
+  // LIN: %[[OFA4:.+]] = load i8*, i8** %[[OFA_P4]]
+  // LIN: %[[BC4:.+]] = bitcast i8* %[[OFA4]] to i129*
+  // LIN: %[[OFANEXT4:.+]] = getelementptr i8, i8* %[[OFA4]], i32 24
+  // LIN: store i8* %[[OFANEXT4]], i8** %[[OFA_P4]]
+  // LIN: %[[LOAD4:.+]] = load i129, i129* %[[BC4]]
+  // LIN: store i129 %[[LOAD4]], i129*
+  // WIN: %[[CUR4:.+]] = load i8*, i8** %[[ARGS]]
+  // WIN: %[[NEXT4:.+]] = getelementptr inbounds i8, i8* %[[CUR4]], i64 24 
+  // WIN: store i8* %[[NEXT4]], i8** %[[ARGS]]
+  // WIN: %[[BC4:.+]] = bitcast i8* %[[CUR4]] to i129*
+  // WIN: %[[LOADV4:.+]] = load i129, i129* %[[BC4]]
+  // WIN: store i129 %[[LOADV4]], i129*
+
+  _ExtInt(16777200) E = __builtin_va_arg(args, _ExtInt(16777200));
+  // LIN: %[[AD5:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
+  // LIN: %[[OFA_P5:.+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %[[AD5]], i32 0, i32 2
+  // LIN: %[[OFA5:.+]] = load i8*, i8** %[[OFA_P5]]
+  // LIN: %[[BC5:.+]] = bitcast i8* %[[OFA5]] to i16777200*
+  // LIN: %[[OFANEXT5:.+]] = getelementptr i8, i8* %[[OFA5]], i32 2097152
+  // LIN: store i8* %[[OFANEXT5]], i8** %[[OFA_P5]]
+  // LIN: %[[LOAD5:.+]] = load i16777200, i16777200* %[[BC5]]
+  // LIN: store i16777200 %[[LOAD5]], i16777200*
+  // WIN: %[[CUR5:.+]] = load i8*, i8** %[[ARGS]]
+  // WIN: %[[NEXT5:.+]] = getelementptr inbounds i8, i8* %[[CUR5]], i64 2097152
+  // WIN: store i8* %[[NEXT5]], i8** %[[ARGS]]
+  // WIN: %[[BC5:.+]] = bitcast i8* %[[CUR5]] to i16777200*
+  // WIN: %[[LOADV5:.+]] = load i16777200, i16777200* %[[BC5]]
+  // WIN: store i16777200 %[[LOADV5]], i16777200*
+
+  __builtin_va_end(args);
+  // LIN: %[[ENDAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %[[ARGS]]
+  // LIN: %[[ENDAD1:.+]] = bitcast %struct.__va_list_tag* %[[ENDAD]] to i8*
+  // LIN: call void @llvm.va_end(i8* %[[ENDAD1]])
+  // WIN: %[[ARGSEND:.+]] = bitcast i8** %[[ARGS]] to i8*
+  // WIN: call void @llvm.va_end(i8* %[[ARGSEND]])
+}
+void typeid_tests() {
+  // LIN: define void @_Z12typeid_testsv()
+  // WIN: define dso_local void @"?typeid_tests@@YAXXZ"()
+  unsigned _ExtInt(33) U33_1, U33_2;
+  _ExtInt(33) S33_1, S33_2;
+  _ExtInt(32) S32_1, S32_2;
+
+ auto A = typeid(U33_1);
+ // LIN: call void @_ZNSt9type_infoC1ERKS_(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast ({ i8*, i8* }* @_ZTIU7_ExtIntILi33EEj to %"class.std::type_info"*))
+ // WIN: call %"class.std::type_info"* @"??0type_info at std@@QEAA at AEBV01@@Z"(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast (%rtti.TypeDescriptor28* @"??_R0U?$_UExtInt@$0CB@@__clang@@@8" to %"class.std::type_info"*))
+ auto B = typeid(U33_2);
+ // LIN: call void @_ZNSt9type_infoC1ERKS_(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast ({ i8*, i8* }* @_ZTIU7_ExtIntILi33EEj to %"class.std::type_info"*))
+ // WIN:  call %"class.std::type_info"* @"??0type_info at std@@QEAA at AEBV01@@Z"(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast (%rtti.TypeDescriptor28* @"??_R0U?$_UExtInt@$0CB@@__clang@@@8" to %"class.std::type_info"*))
+ auto C = typeid(S33_1);
+ // LIN: call void @_ZNSt9type_infoC1ERKS_(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast ({ i8*, i8* }* @_ZTIU7_ExtIntILi33EEi to %"class.std::type_info"*))
+ // WIN:  call %"class.std::type_info"* @"??0type_info at std@@QEAA at AEBV01@@Z"(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast (%rtti.TypeDescriptor27* @"??_R0U?$_ExtInt@$0CB@@__clang@@@8" to %"class.std::type_info"*))
+ auto D = typeid(S33_2);
+ // LIN: call void @_ZNSt9type_infoC1ERKS_(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast ({ i8*, i8* }* @_ZTIU7_ExtIntILi33EEi to %"class.std::type_info"*))
+ // WIN:  call %"class.std::type_info"* @"??0type_info at std@@QEAA at AEBV01@@Z"(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast (%rtti.TypeDescriptor27* @"??_R0U?$_ExtInt@$0CB@@__clang@@@8" to %"class.std::type_info"*))
+ auto E = typeid(S32_1);
+ // LIN: call void @_ZNSt9type_infoC1ERKS_(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast ({ i8*, i8* }* @_ZTIU7_ExtIntILi32EEi to %"class.std::type_info"*))
+ // WIN:  call %"class.std::type_info"* @"??0type_info at std@@QEAA at AEBV01@@Z"(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast (%rtti.TypeDescriptor27* @"??_R0U?$_ExtInt@$0CA@@__clang@@@8" to %"class.std::type_info"*))
+ auto F = typeid(S32_2);
+ // LIN: call void @_ZNSt9type_infoC1ERKS_(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast ({ i8*, i8* }* @_ZTIU7_ExtIntILi32EEi to %"class.std::type_info"*))
+ // WIN:  call %"class.std::type_info"* @"??0type_info at std@@QEAA at AEBV01@@Z"(%"class.std::type_info"* %{{.+}}, %"class.std::type_info"* dereferenceable(16) bitcast (%rtti.TypeDescriptor27* @"??_R0U?$_ExtInt@$0CA@@__clang@@@8" to %"class.std::type_info"*))
+}
+
+void ExplicitCasts() {
+  // LIN: define void @_Z13ExplicitCastsv() 
+  // WIN: define dso_local void @"?ExplicitCasts@@YAXXZ"()
+
+  _ExtInt(33) a;
+  _ExtInt(31) b;
+  int i;
+
+  a = i;
+  // CHECK: %[[CONV:.+]] = sext i32 %{{.+}} to i33
+  b = i;
+  // CHECK: %[[CONV:.+]] = trunc i32 %{{.+}} to i31
+  i = a;
+  // CHECK: %[[CONV:.+]] = trunc i33 %{{.+}} to i32
+  i = b;
+  // CHECK: %[[CONV:.+]] = sext i31 %{{.+}} to i32
+}
+
+struct S {
+  _ExtInt(17) A;
+  _ExtInt(16777200) B;
+  _ExtInt(17) C;
+};
+
+void OffsetOfTest() {
+  // LIN: define void @_Z12OffsetOfTestv() 
+  // WIN: define dso_local void @"?OffsetOfTest@@YAXXZ"()
+
+  auto A = __builtin_offsetof(S,A);
+  // CHECK: store i64 0, i64* %{{.+}}
+  auto B = __builtin_offsetof(S,B);
+  // CHECK: store i64 8, i64* %{{.+}}
+  auto C = __builtin_offsetof(S,C);
+  // CHECK: store i64 2097160, i64* %{{.+}}
+}
+
+
+void ShiftExtIntByConstant(_ExtInt(28) Ext) {
+// LIN: define void @_Z21ShiftExtIntByConstantU7_ExtIntILi28EEi
+// WIN: define dso_local void @"?ShiftExtIntByConstant@@YAXU?$_ExtInt@$0BM@@__clang@@@Z"
+  Ext << 7;
+  // CHECK: shl i28 %{{.+}}, 7
+  Ext >> 7;
+  // CHECK: ashr i28 %{{.+}}, 7
+  Ext << -7;
+  // CHECK: shl i28 %{{.+}}, -7
+  Ext >> -7;
+  // CHECK: ashr i28 %{{.+}}, -7
+
+  // UB in C/C++, Defined in OpenCL.
+  Ext << 29;
+  // CHECK: shl i28 %{{.+}}, 29 
+  Ext >> 29;
+  // CHECK: ashr i28 %{{.+}}, 29
+}
+
+void ConstantShiftByExtInt(_ExtInt(28) Ext, _ExtInt(65) LargeExt) {
+  // LIN: define void @_Z21ConstantShiftByExtIntU7_ExtIntILi28EEiU7_ExtIntILi65EEi
+  // WIN: define dso_local void @"?ConstantShiftByExtInt@@YAXU?$_ExtInt@$0BM@@__clang@@U?$_ExtInt@$0EB@@2@@Z"
+  10 << Ext;
+  // CHECK: %[[PROMO:.+]] = zext i28 %{{.+}} to i32
+  // CHECK: shl i32 10, %[[PROMO]]
+  10 >> Ext;
+  // CHECK: %[[PROMO:.+]] = zext i28 %{{.+}} to i32
+  // CHECK: ashr i32 10, %[[PROMO]]
+  10 << LargeExt;
+  // CHECK: %[[PROMO:.+]] = trunc i65 %{{.+}} to i32
+  // CHECK: shl i32 10, %[[PROMO]]
+  10 >> LargeExt;
+  // CHECK: %[[PROMO:.+]] = trunc i65 %{{.+}} to i32
+  // CHECK: ashr i32 10, %[[PROMO]]
+}
+
+void Shift(_ExtInt(28) Ext, _ExtInt(65) LargeExt, int i) {
+  // LIN: define void @_Z5ShiftU7_ExtIntILi28EEiU7_ExtIntILi65EEii
+  // WIN: define dso_local void @"?Shift@@YAXU?$_ExtInt@$0BM@@__clang@@U?$_ExtInt@$0EB@@2 at H@Z"
+  i << Ext;
+  // CHECK: %[[PROMO:.+]] = zext i28 %{{.+}} to i32
+  // CHECK: shl i32 {{.+}}, %[[PROMO]]
+  i >> Ext;
+  // CHECK: %[[PROMO:.+]] = zext i28 %{{.+}} to i32
+  // CHECK: ashr i32 {{.+}}, %[[PROMO]]
+
+  i << LargeExt;
+  // CHECK: %[[PROMO:.+]] = trunc i65 %{{.+}} to i32
+  // CHECK: shl i32 {{.+}}, %[[PROMO]]
+  i >> LargeExt;
+  // CHECK: %[[PROMO:.+]] = trunc i65 %{{.+}} to i32
+  // CHECK: ashr i32 {{.+}}, %[[PROMO]]
+
+  Ext << i;
+  // CHECK: %[[PROMO:.+]] = trunc i32 %{{.+}} to i28
+  // CHECK: shl i28 {{.+}}, %[[PROMO]]
+  Ext >> i;
+  // CHECK: %[[PROMO:.+]] = trunc i32 %{{.+}} to i28
+  // CHECK: ashr i28 {{.+}}, %[[PROMO]]
+
+  LargeExt << i;
+  // CHECK: %[[PROMO:.+]] = zext i32 %{{.+}} to i65
+  // CHECK: shl i65 {{.+}}, %[[PROMO]]
+  LargeExt >> i;
+  // CHECK: %[[PROMO:.+]] = zext i32 %{{.+}} to i65
+  // CHECK: ashr i65 {{.+}}, %[[PROMO]]
+
+  Ext << LargeExt;
+  // CHECK: %[[PROMO:.+]] = trunc i65 %{{.+}} to i28
+  // CHECK: shl i28 {{.+}}, %[[PROMO]]
+  Ext >> LargeExt;
+  // CHECK: %[[PROMO:.+]] = trunc i65 %{{.+}} to i28
+  // CHECK: ashr i28 {{.+}}, %[[PROMO]]
+
+  LargeExt << Ext;
+  // CHECK: %[[PROMO:.+]] = zext i28 %{{.+}} to i65
+  // CHECK: shl i65 {{.+}}, %[[PROMO]]
+  LargeExt >> Ext;
+  // CHECK: %[[PROMO:.+]] = zext i28 %{{.+}} to i65
+  // CHECK: ashr i65 {{.+}}, %[[PROMO]]
+}
+
+void ComplexTest(_Complex _ExtInt(12) first,
+                                 _Complex _ExtInt(33) second) {
+  // LIN: define void @_Z11ComplexTestCU7_ExtIntILi12EEiCU7_ExtIntILi33EEi
+  // WIN: define dso_local void  @"?ComplexTest@@YAXU?$_Complex at U?$_ExtInt@$0M@@__clang@@@__clang@@U?$_Complex at U?$_ExtInt@$0CB@@__clang@@@2@@Z"
+  first + second;
+  // CHECK: %[[FIRST_REALP:.+]] = getelementptr inbounds { i12, i12 }, { i12, i12 }* %{{.+}}, i32 0, i32 0
+  // CHECK: %[[FIRST_REAL:.+]] = load i12, i12* %[[FIRST_REALP]]
+  // CHECK: %[[FIRST_IMAGP:.+]] = getelementptr inbounds { i12, i12 }, { i12, i12 }* %{{.+}}, i32 0, i32 1
+  // CHECK: %[[FIRST_IMAG:.+]] = load i12, i12* %[[FIRST_IMAGP]]
+  // CHECK: %[[FIRST_REAL_CONV:.+]] = sext i12 %[[FIRST_REAL]]
+  // CHECK: %[[FIRST_IMAG_CONV:.+]] = sext i12 %[[FIRST_IMAG]]
+  // CHECK: %[[SECOND_REALP:.+]] = getelementptr inbounds { i33, i33 }, { i33, i33 }* %{{.+}}, i32 0, i32 0
+  // CHECK: %[[SECOND_REAL:.+]] = load i33, i33* %[[SECOND_REALP]]
+  // CHECK: %[[SECOND_IMAGP:.+]] = getelementptr inbounds { i33, i33 }, { i33, i33 }* %{{.+}}, i32 0, i32 1
+  // CHECK: %[[SECOND_IMAG:.+]] = load i33, i33* %[[SECOND_IMAGP]]
+  // CHECK: %[[REAL:.+]] = add i33 %[[FIRST_REAL_CONV]], %[[SECOND_REAL]]
+  // CHECK: %[[IMAG:.+]] = add i33 %[[FIRST_IMAG_CONV]], %[[SECOND_IMAG]]
+}
+
+// Ensure that these types don't alias the normal int types.
+void TBAATest(_ExtInt(sizeof(int) * 8) ExtInt,
+              unsigned _ExtInt(sizeof(int) * 8) ExtUInt,
+              _ExtInt(6) Other) {
+  // CHECK-DAG: store i32 %{{.+}}, i32* %{{.+}}, align 4, !tbaa ![[EXTINT_TBAA:.+]]
+  // CHECK-DAG: store i32 %{{.+}}, i32* %{{.+}}, align 4, !tbaa ![[EXTINT_TBAA]]
+  // CHECK-DAG: store i6 %{{.+}}, i6* %{{.+}}, align 1, !tbaa ![[EXTINT6_TBAA:.+]]
+  ExtInt = 5;
+  ExtUInt = 5;
+  Other = 5;
+}
+
+// NoNewStructPathTBAA-DAG: ![[CHAR_TBAA_ROOT:.+]] = !{!"omnipotent char", ![[TBAA_ROOT:.+]], i64 0}
+// NoNewStructPathTBAA-DAG: ![[TBAA_ROOT]] = !{!"Simple C++ TBAA"}
+// NoNewStructPathTBAA-DAG: ![[EXTINT_TBAA]] = !{![[EXTINT_TBAA_ROOT:.+]], ![[EXTINT_TBAA_ROOT]], i64 0}
+// NoNewStructPathTBAA-DAG: ![[EXTINT_TBAA_ROOT]] = !{!"_ExtInt(32)", ![[CHAR_TBAA_ROOT]], i64 0}
+// NoNewStructPathTBAA-DAG: ![[EXTINT6_TBAA]] = !{![[EXTINT6_TBAA_ROOT:.+]], ![[EXTINT6_TBAA_ROOT]], i64 0}
+// NoNewStructPathTBAA-DAG: ![[EXTINT6_TBAA_ROOT]] = !{!"_ExtInt(6)", ![[CHAR_TBAA_ROOT]], i64 0}
+
+// NewStructPathTBAA-DAG: ![[CHAR_TBAA_ROOT:.+]] = !{![[TBAA_ROOT:.+]], i64 1, !"omnipotent char"}
+// NewStructPathTBAA-DAG: ![[TBAA_ROOT]] = !{!"Simple C++ TBAA"}
+// NewStructPathTBAA-DAG: ![[EXTINT_TBAA]] = !{![[EXTINT_TBAA_ROOT:.+]], ![[EXTINT_TBAA_ROOT]], i64 0, i64 4}
+// NewStructPathTBAA-DAG: ![[EXTINT_TBAA_ROOT]] = !{![[CHAR_TBAA_ROOT]], i64 4, !"_ExtInt(32)"}
+// NewStructPathTBAA-DAG: ![[EXTINT6_TBAA]] = !{![[EXTINT6_TBAA_ROOT:.+]], ![[EXTINT6_TBAA_ROOT]], i64 0, i64 1}
+// NewStructPathTBAA-DAG: ![[EXTINT6_TBAA_ROOT]] = !{![[CHAR_TBAA_ROOT]], i64 1, !"_ExtInt(6)"}

diff  --git a/clang/test/CodeGenOpenCL/ext-int-shift.cl b/clang/test/CodeGenOpenCL/ext-int-shift.cl
new file mode 100644
index 000000000000..4d2292daac77
--- /dev/null
+++ b/clang/test/CodeGenOpenCL/ext-int-shift.cl
@@ -0,0 +1,21 @@
+// RUN: %clang -cc1 -triple x86_64-linux-pc -O3 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s
+
+void Shifts(_ExtInt(12) E, int i) {
+  E << 99;
+  // CHECK: shl i12 %{{.+}}, 3
+
+  77 << E;
+  // CHECK: %[[PROM:.+]] = zext i12 %{{.+}} to i32
+  // CHECK: %[[MASK:.+]] = and i32 %[[PROM]], 31
+  // CHECK: shl i32 77, %[[MASK]]
+
+  E << i;
+  // CHECK: %[[PROM:.+]] = trunc i32 %{{.+}} to i12
+  // CHECK: %[[MASK:.+]] = urem i12 %[[PROM]], 12
+  // CHECK: shl i12 %{{.+}}, %[[MASK]]
+
+  i << E;
+  // CHECK: %[[PROM:.+]] = zext i12 %{{.+}} to i32
+  // CHECK: %[[MASK:.+]] = and i32 %[[PROM]], 31
+  // CHECK: shl i32 %{{.+}}, %[[MASK]]
+}

diff  --git a/clang/test/Parser/ext-int.cpp b/clang/test/Parser/ext-int.cpp
new file mode 100644
index 000000000000..4926d5190587
--- /dev/null
+++ b/clang/test/Parser/ext-int.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// expected-error at +5{{expected ')'}}
+// expected-note at +4{{to match this '('}}
+// expected-error at +3{{expected unqualified-id}}
+// expected-error at +2{{extraneous closing brace}}
+// expected-error at +1{{C++ requires a type specifier for all declarations}}
+_ExtInt(32} a;
+// expected-error at +2{{expected expression}}
+// expected-error at +1{{C++ requires a type specifier for all declarations}}
+_ExtInt(32* ) b;
+// expected-error at +3{{expected '('}}
+// expected-error at +2{{expected unqualified-id}}
+// expected-error at +1{{C++ requires a type specifier for all declarations}}
+_ExtInt{32} c;

diff  --git a/clang/test/SemaCXX/ext-int.cpp b/clang/test/SemaCXX/ext-int.cpp
new file mode 100644
index 000000000000..6a06280dceec
--- /dev/null
+++ b/clang/test/SemaCXX/ext-int.cpp
@@ -0,0 +1,278 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -Wimplicit-int-conversion
+
+template<int Bounds>
+struct HasExtInt {
+  _ExtInt(Bounds) b;
+  unsigned _ExtInt(Bounds) b2;
+};
+
+// Delcaring variables:
+_ExtInt(33) Declarations(_ExtInt(48) &Param) { // Useable in params and returns.
+  short _ExtInt(43) a; // expected-error {{'short _ExtInt' is invalid}}
+  _ExtInt(43) long b;  // expected-error {{'long _ExtInt' is invalid}}
+
+  // These should all be fine:
+  const _ExtInt(5) c = 3;
+  const unsigned _ExtInt(5) d; // expected-error {{default initialization of an object of const type 'const unsigned _ExtInt(5)'}}
+  unsigned _ExtInt(5) e = 5;
+  _ExtInt(5) unsigned f;
+
+  _ExtInt(-3) g; // expected-error{{signed _ExtInt must have a bit size of at least 2}}
+  _ExtInt(0) h; // expected-error{{signed _ExtInt must have a bit size of at least 2}}
+  _ExtInt(1) i; // expected-error{{signed _ExtInt must have a bit size of at least 2}}
+  _ExtInt(2) j;;
+  unsigned _ExtInt(0) k;// expected-error{{unsigned _ExtInt must have a bit size of at least 1}}
+  unsigned _ExtInt(1) l;
+  signed _ExtInt(1) m; // expected-error{{signed _ExtInt must have a bit size of at least 2}}
+
+  constexpr _ExtInt(6) n = 33; // expected-warning{{implicit conversion from 'int' to 'const _ExtInt(6)' changes value from 33 to -31}}
+  constexpr _ExtInt(7) o = 33;
+
+  // Check LLVM imposed max size.
+  _ExtInt(0xFFFFFFFFFF) p; // expected-error {{signed _ExtInt of bit sizes greater than 16777215 not supported}}
+  unsigned _ExtInt(0xFFFFFFFFFF) q; // expected-error {{unsigned _ExtInt of bit sizes greater than 16777215 not supported}}
+
+// Ensure template params are instantiated correctly.
+  // expected-error at 5{{signed _ExtInt must have a bit size of at least 2}}
+  // expected-error at 6{{unsigned _ExtInt must have a bit size of at least 1}}
+  // expected-note at +1{{in instantiation of template class }}
+  HasExtInt<-1> r;
+  // expected-error at 5{{signed _ExtInt must have a bit size of at least 2}}
+  // expected-error at 6{{unsigned _ExtInt must have a bit size of at least 1}}
+  // expected-note at +1{{in instantiation of template class }}
+  HasExtInt<0> s;
+  // expected-error at 5{{signed _ExtInt must have a bit size of at least 2}}
+  // expected-note at +1{{in instantiation of template class }}
+  HasExtInt<1> t;
+  HasExtInt<2> u;
+
+  _ExtInt(-3.0) v; // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'double'}}
+  _ExtInt(3.0) x; // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'double'}}
+
+  return 0;
+}
+
+template <_ExtInt(5) I>
+struct ExtIntTemplParam {
+  static constexpr _ExtInt(5) Var = I;
+};
+
+template<typename T>
+void deduced_whole_type(T){}
+template<int I>
+void deduced_bound(_ExtInt(I)){}
+
+// Ensure ext-int can be used in template places.
+void Templates() {
+  ExtIntTemplParam<13> a;
+  constexpr _ExtInt(3) b = 1;
+  ExtIntTemplParam<b> c;
+  constexpr _ExtInt(9) d = 1;
+  ExtIntTemplParam<b> e;
+
+  deduced_whole_type(b);
+  deduced_bound(b);
+}
+
+template <typename T, typename U>
+struct is_same {
+  static constexpr bool value = false;
+};
+template <typename T>
+struct is_same<T,T> {
+  static constexpr bool value = true;
+};
+
+// Reject vector types:
+// expected-error at +1{{invalid vector element type '_ExtInt(32)'}}
+typedef _ExtInt(32) __attribute__((vector_size(16))) VecTy;
+
+// Allow _Complex:
+_Complex _ExtInt(3) Cmplx;
+
+// Reject cases of _Atomic:
+// expected-error at +1{{_Atomic cannot be applied to integer type '_ExtInt(4)' with less than 1 byte of precision}}
+_Atomic _ExtInt(4) TooSmallAtomic;
+// expected-error at +1{{_Atomic cannot be applied to integer type '_ExtInt(9)' with a non power of 2 precision}}
+_Atomic _ExtInt(9) NotPow2Atomic;
+_Atomic _ExtInt(128) JustRightAtomic;
+
+// Test result types of Unary/Bitwise/Binary Operations:
+void Ops() {
+  _ExtInt(43) x43_s = 1, y43_s = 1;
+  _ExtInt(sizeof(int) * 8) x32_s = 1, y32_s = 1;
+  unsigned _ExtInt(sizeof(unsigned) * 8) x32_u = 1, y32_u = 1;
+  _ExtInt(4) x4_s = 1, y4_s = 1;
+  unsigned _ExtInt(43) x43_u = 1, y43_u = 1;
+  unsigned _ExtInt(4) x4_u = 1, y4_u = 1;
+  int x_int = 1, y_int = 1;
+  unsigned x_uint = 1, y_uint = 1;
+  bool b;
+
+  // Disabling mixed conversions:
+  // Signed/unsigned mixed.
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_u + y43_s;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_s - y4_u;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_s * y43_u;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_u / y4_s;
+
+  // Different Sizes.
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_s + y4_s;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_s - y4_u;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_u * y4_u;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_u / y43_u;
+
+  // Mixed with standard types.
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_s + x_int;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_u - x_int;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x32_s * x_int;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x32_u / x_int;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x32_s * x_uint;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x32_u / x_uint;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_s + x_int;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_u - x_int;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_s + b;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_u - b;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_s + b;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_u - b;
+
+  // Bitwise checks.
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_s % y4_u;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_u % y4_s;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_s | y43_u;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_u | y43_s;
+
+  // compassign.
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_s += 33;
+
+  // Comparisons.
+  // expected-error at +1{{invalid operands to binary expression}}
+  x43_s > 33;
+  // expected-error at +1{{invalid operands to binary expression}}
+  x4_s > 33;
+
+  // Same size/sign ops don't change type.
+  static_assert(is_same<decltype(x43_s + y43_s), _ExtInt(43)>::value,"");
+  static_assert(is_same<decltype(x4_s - y4_s), _ExtInt(4)>::value,"");
+  static_assert(is_same<decltype(x43_u * y43_u), unsigned _ExtInt(43)>::value,"");
+  static_assert(is_same<decltype(x4_u / y4_u), unsigned _ExtInt(4)>::value,"");
+
+  // Unary ops shouldn't go through integer promotions.
+  static_assert(is_same<decltype(~x43_s), _ExtInt(43)>::value,"");
+  static_assert(is_same<decltype(~x4_s), _ExtInt(4)>::value,"");
+  static_assert(is_same<decltype(+x43_s), _ExtInt(43)>::value,"");
+  static_assert(is_same<decltype(+x4_s), _ExtInt(4)>::value,"");
+  static_assert(is_same<decltype(-x43_u), unsigned _ExtInt(43)>::value,"");
+  static_assert(is_same<decltype(-x4_u), unsigned _ExtInt(4)>::value,"");
+  // expected-warning at +1{{expression with side effects has no effect in an unevaluated context}}
+  static_assert(is_same<decltype(++x43_s), _ExtInt(43)&>::value,"");
+  // expected-warning at +1{{expression with side effects has no effect in an unevaluated context}}
+  static_assert(is_same<decltype(--x4_s), _ExtInt(4)&>::value,"");
+  // expected-warning at +1{{expression with side effects has no effect in an unevaluated context}}
+  static_assert(is_same<decltype(x43_s--), _ExtInt(43)>::value,"");
+  // expected-warning at +1{{expression with side effects has no effect in an unevaluated context}}
+  static_assert(is_same<decltype(x4_s++), _ExtInt(4)>::value,"");
+  static_assert(is_same<decltype(x4_s >> 1), _ExtInt(4)>::value,"");
+  static_assert(is_same<decltype(x4_u << 1), unsigned _ExtInt(4)>::value,"");
+
+  static_assert(sizeof(x43_s) == 8, "");
+  static_assert(sizeof(x4_s) == 1, "");
+
+  static_assert(sizeof(_ExtInt(3340)) == 424, ""); // 424 * 8 == 3392.
+  static_assert(sizeof(_ExtInt(1049)) == 136, ""); // 136  *  8 == 1088.
+
+  static_assert(alignof(decltype(x43_s)) == 8, "");
+  static_assert(alignof(decltype(x4_s)) == 1, "");
+
+  static_assert(alignof(_ExtInt(3340)) == 8, "");
+  static_assert(alignof(_ExtInt(1049)) == 8, "");
+}
+
+constexpr int func() { return 42;}
+
+void ConstexprBitsize() {
+  _ExtInt(func()) F;
+  static_assert(is_same<decltype(F), _ExtInt(42)>::value, "");
+}
+
+// Useable as an underlying type.
+enum AsEnumUnderlyingType : _ExtInt(33) {
+};
+
+void overloaded(int);
+void overloaded(_ExtInt(32));
+void overloaded(_ExtInt(33));
+void overloaded(short);
+//expected-note at +1{{candidate function}}
+void overloaded2(_ExtInt(32));
+//expected-note at +1{{candidate function}}
+void overloaded2(_ExtInt(33));
+//expected-note at +1{{candidate function}}
+void overloaded2(short);
+
+void overload_use() {
+  int i;
+  _ExtInt(32) i32;
+  _ExtInt(33) i33;
+  short s;
+
+  // All of these get their corresponding exact matches.
+  overloaded(i);
+  overloaded(i32);
+  overloaded(i33);
+  overloaded(s);
+
+  overloaded2(i); // expected-error{{call to 'overloaded2' is ambiguous}}
+
+  overloaded2(i32);
+
+  overloaded2(s);
+}
+
+// no errors expected, this should 'just work'.
+struct UsedAsBitField {
+  _ExtInt(3) F : 3;
+  _ExtInt(3) G : 3;
+  _ExtInt(3) H : 3;
+};
+
+// expected-error at +1{{mode attribute only supported for integer and floating-point types}}
+typedef _ExtInt(33) IllegalMode __attribute__((mode(DI)));
+
+void ImplicitCasts(_ExtInt(31) s31, _ExtInt(33) s33, int i) {
+  // expected-warning at +1{{implicit conversion loses integer precision}}
+  s31 = i;
+  // expected-warning at +1{{implicit conversion loses integer precision}}
+  s31 = s33;
+  s33 = i;
+  s33 = s31;
+  i = s31;
+  // expected-warning at +1{{implicit conversion loses integer precision}}
+  i = s33;
+}
+

diff  --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index fc9d8db62b2d..dafe4ccda05f 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1793,6 +1793,8 @@ DEFAULT_TYPELOC_IMPL(Enum, TagType)
 DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type)
 DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type)
 DEFAULT_TYPELOC_IMPL(Auto, Type)
+DEFAULT_TYPELOC_IMPL(ExtInt, Type)
+DEFAULT_TYPELOC_IMPL(DependentExtInt, Type)
 
 bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
   // Visit the nested-name-specifier, if present.

diff  --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 0a3e8735c448..cbd8e78695f4 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -3987,6 +3987,9 @@ TypeSystemClang::GetTypeClass(lldb::opaque_compiler_type_t type) {
   case clang::Type::Vector:
     return lldb::eTypeClassVector;
   case clang::Type::Builtin:
+  // Ext-Int is just an integer type.
+  case clang::Type::ExtInt:
+  case clang::Type::DependentExtInt:
     return lldb::eTypeClassBuiltin;
   case clang::Type::ObjCObjectPointer:
     return lldb::eTypeClassObjCObjectPointer;
@@ -4661,6 +4664,11 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type,
     // TODO: Set this to more than one???
     break;
 
+  case clang::Type::ExtInt:
+  case clang::Type::DependentExtInt:
+    return qual_type->isUnsignedIntegerType() ? lldb::eEncodingUint
+                                              : lldb::eEncodingSint;
+
   case clang::Type::Builtin:
     switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
     case clang::BuiltinType::Void:
@@ -4915,6 +4923,11 @@ lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) {
   case clang::Type::Vector:
     break;
 
+  case clang::Type::ExtInt:
+  case clang::Type::DependentExtInt:
+    return qual_type->isUnsignedIntegerType() ? lldb::eFormatUnsigned
+                                              : lldb::eFormatDecimal;
+
   case clang::Type::Builtin:
     switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
     case clang::BuiltinType::UnknownAny:
@@ -7358,7 +7371,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
                     function_type->getReturnType())));
         cxx_conversion_decl->setType(method_qual_type);
         cxx_conversion_decl->setInlineSpecified(is_inline);
-        cxx_conversion_decl->setExplicitSpecifier(explicit_spec);        
+        cxx_conversion_decl->setExplicitSpecifier(explicit_spec);
         cxx_conversion_decl->setConstexprKind(CSK_unspecified);
         cxx_method_decl = cxx_conversion_decl;
       }


        


More information about the cfe-commits mailing list