[clang] 61ba148 - Implement _ExtInt as an extended int type specifier.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 17 07:11:15 PDT 2020


Author: Erich Keane
Date: 2020-04-17T07:10:57-07:00
New Revision: 61ba1481e200b5b35baa81ffcff81acb678e8508

URL: https://github.com/llvm/llvm-project/commit/61ba1481e200b5b35baa81ffcff81acb678e8508
DIFF: https://github.com/llvm/llvm-project/commit/61ba1481e200b5b35baa81ffcff81acb678e8508.diff

LOG: Implement _ExtInt as an extended int type specifier.

Introduction/Motivation:
LLVM-IR supports integers of non-power-of-2 bitwidth, in the iN syntax.
Integers of non-power-of-two aren't particularly interesting or useful
on most hardware, so much so that no language in Clang has been
motivated to expose it before.

However, in the case of FPGA hardware normal integer types where the
full bitwidth isn't used, is extremely wasteful and has severe
performance/space concerns.  Because of this, Intel has introduced this
functionality in the High Level Synthesis compiler[0]
under the name "Arbitrary Precision Integer" (ap_int for short). This
has been extremely useful and effective for our users, permitting them
to optimize their storage and operation space on an architecture where
both can be extremely expensive.

We are proposing upstreaming a more palatable version of this to the
community, in the form of this proposal and accompanying patch.  We are
proposing the syntax _ExtInt(N).  We intend to propose this to the WG14
committee[1], and the underscore-capital seems like the active direction
for a WG14 paper's acceptance.  An alternative that Richard Smith
suggested on the initial review was __int(N), however we believe that
is much less acceptable by WG14.  We considered _Int, however _Int is
used as an identifier in libstdc++ and there is no good way to fall
back to an identifier (since _Int(5) is indistinguishable from an
unnamed initializer of a template type named _Int).

[0]https://www.intel.com/content/www/us/en/software/programmable/quartus-prime/hls-compiler.html)
[1]http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2472.pdf

Differential Revision: https://reviews.llvm.org/D73967

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

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 539b655fdf6a..4a45847c9425 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 97e96941ec2f..343c62273ec4 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);
@@ -3770,6 +3775,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.
@@ -3784,8 +3804,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);
@@ -3847,8 +3866,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.


        


More information about the cfe-commits mailing list