Reland Implement _ExtInt as an extended int type specifier.
I fixed the LLDB issue, so re-applying the patch.
This reverts commit a4b88c044980337bb14390be654fe76864aa60ec.
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index ae4a78a..276e35a 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -360,6 +360,7 @@
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 @@
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 @@
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 @@
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 @@
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 e7bc499..037e9c3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -9793,6 +9793,9 @@
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 @@
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 ed082db..27c8365 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14811,12 +14811,16 @@
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 3205b44..869ae5c 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4087,8 +4087,9 @@
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 31d6948..fbb5d4b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1482,6 +1482,11 @@
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 different arithmetic types.
// Diagnose attempts to convert between __float128 and long double where
@@ -4261,6 +4266,7 @@
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 @@
<< 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 82a1971..08d29fa 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2967,6 +2967,7 @@
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 f425ec7..7bd1291 100755
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5998,6 +5998,15 @@
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 @@
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 @@
// 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 8e3c618..e1d438f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1515,6 +1515,7 @@
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::ExtInt:
if (TDF & TDF_SkipNonDependent)
return Sema::TDK_Success;
@@ -2106,6 +2107,33 @@
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 @@
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 @@
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 825b062..466cb08 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -847,6 +847,7 @@
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 53e4366..4ecd362 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 87b07897e..abde968 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1183,6 +1183,14 @@
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 @@
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 @@
: 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,