Introduce Type::isSignedIntegerOrEnumerationType() and

Type::isUnsignedIntegerOrEnumerationType(), which are like
Type::isSignedIntegerType() and Type::isUnsignedIntegerType() but also
consider the underlying type of a C++0x scoped enumeration type.

Audited all callers to the existing functions, switching those that
need to also handle scoped enumeration types (e.g., those that deal
with constant values) over to the new functions. Fixes PR9923 /
<rdar://problem/9447851>.

llvm-svn: 131735
This commit is contained in:
Douglas Gregor 2011-05-20 16:38:50 +00:00
parent 24b31b6b7d
commit 6ab2fa8f78
17 changed files with 91 additions and 39 deletions

View File

@ -1453,7 +1453,8 @@ public:
/// MakeIntValue - Make an APSInt of the appropriate width and /// MakeIntValue - Make an APSInt of the appropriate width and
/// signedness for the given \arg Value and integer \arg Type. /// signedness for the given \arg Value and integer \arg Type.
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const { llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerType()); llvm::APSInt Res(getIntWidth(Type),
!Type->isSignedIntegerOrEnumerationType());
Res = Value; Res = Value;
return Res; return Res;
} }

View File

@ -291,6 +291,8 @@ public:
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)

View File

@ -1436,6 +1436,14 @@ public:
/// or an enum decl which has an unsigned representation. /// or an enum decl which has an unsigned representation.
bool isUnsignedIntegerType() const; bool isUnsignedIntegerType() const;
/// Determines whether this is an integer type that is signed or an
/// enumeration types whose underlying type is a signed integer type.
bool isSignedIntegerOrEnumerationType() const;
/// Determines whether this is an integer type that is unsigned or an
/// enumeration types whose underlying type is a unsigned integer type.
bool isUnsignedIntegerOrEnumerationType() const;
/// isConstantSizeType - Return true if this is not a variable sized type, /// isConstantSizeType - Return true if this is not a variable sized type,
/// according to the rules of C99 6.7.5p3. It is not legal to call this on /// according to the rules of C99 6.7.5p3. It is not legal to call this on
/// incomplete types. /// incomplete types.

View File

@ -221,7 +221,7 @@ static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType,
APFloat &Value, const ASTContext &Ctx) { APFloat &Value, const ASTContext &Ctx) {
unsigned DestWidth = Ctx.getIntWidth(DestType); unsigned DestWidth = Ctx.getIntWidth(DestType);
// Determine whether we are converting to unsigned or signed. // Determine whether we are converting to unsigned or signed.
bool DestSigned = DestType->isSignedIntegerType(); bool DestSigned = DestType->isSignedIntegerOrEnumerationType();
// FIXME: Warning for overflow. // FIXME: Warning for overflow.
uint64_t Space[4]; uint64_t Space[4];
@ -247,7 +247,7 @@ static APSInt HandleIntToIntCast(QualType DestType, QualType SrcType,
// Figure out if this is a truncate, extend or noop cast. // Figure out if this is a truncate, extend or noop cast.
// If the input is signed, do a sign extend, noop, or truncate. // If the input is signed, do a sign extend, noop, or truncate.
Result = Result.extOrTrunc(DestWidth); Result = Result.extOrTrunc(DestWidth);
Result.setIsUnsigned(DestType->isUnsignedIntegerType()); Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType());
return Result; return Result;
} }
@ -947,7 +947,7 @@ public:
bool Success(const llvm::APSInt &SI, const Expr *E) { bool Success(const llvm::APSInt &SI, const Expr *E) {
assert(E->getType()->isIntegralOrEnumerationType() && assert(E->getType()->isIntegralOrEnumerationType() &&
"Invalid evaluation result."); "Invalid evaluation result.");
assert(SI.isSigned() == E->getType()->isSignedIntegerType() && assert(SI.isSigned() == E->getType()->isSignedIntegerOrEnumerationType() &&
"Invalid evaluation result."); "Invalid evaluation result.");
assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
"Invalid evaluation result."); "Invalid evaluation result.");
@ -961,7 +961,8 @@ public:
assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
"Invalid evaluation result."); "Invalid evaluation result.");
Result = APValue(APSInt(I)); Result = APValue(APSInt(I));
Result.getInt().setIsUnsigned(E->getType()->isUnsignedIntegerType()); Result.getInt().setIsUnsigned(
E->getType()->isUnsignedIntegerOrEnumerationType());
return true; return true;
} }
@ -2558,7 +2559,7 @@ static bool Evaluate(EvalInfo &Info, const Expr *E) {
if (E->getType()->isVectorType()) { if (E->getType()->isVectorType()) {
if (!EvaluateVector(E, Info.EvalResult.Val, Info)) if (!EvaluateVector(E, Info.EvalResult.Val, Info))
return false; return false;
} else if (E->getType()->isIntegerType()) { } else if (E->getType()->isIntegralOrEnumerationType()) {
if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(E)) if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(E))
return false; return false;
if (Info.EvalResult.Val.isLValue() && if (Info.EvalResult.Val.isLValue() &&

View File

@ -648,6 +648,20 @@ bool Type::isSignedIntegerType() const {
return false; return false;
} }
bool Type::isSignedIntegerOrEnumerationType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
BT->getKind() <= BuiltinType::Int128;
}
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
if (ET->getDecl()->isComplete())
return ET->getDecl()->getIntegerType()->isSignedIntegerType();
}
return false;
}
bool Type::hasSignedIntegerRepresentation() const { bool Type::hasSignedIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerType(); return VT->getElementType()->isSignedIntegerType();
@ -674,6 +688,20 @@ bool Type::isUnsignedIntegerType() const {
return false; return false;
} }
bool Type::isUnsignedIntegerOrEnumerationType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::UInt128;
}
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
if (ET->getDecl()->isComplete())
return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
}
return false;
}
bool Type::hasUnsignedIntegerRepresentation() const { bool Type::hasUnsignedIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerType(); return VT->getElementType()->isUnsignedIntegerType();

View File

@ -809,9 +809,9 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// sense to do it here because parameters are so messed up. // sense to do it here because parameters are so messed up.
switch (AI.getKind()) { switch (AI.getKind()) {
case ABIArgInfo::Extend: case ABIArgInfo::Extend:
if (ParamType->isSignedIntegerType()) if (ParamType->isSignedIntegerOrEnumerationType())
Attributes |= llvm::Attribute::SExt; Attributes |= llvm::Attribute::SExt;
else if (ParamType->isUnsignedIntegerType()) else if (ParamType->isUnsignedIntegerOrEnumerationType())
Attributes |= llvm::Attribute::ZExt; Attributes |= llvm::Attribute::ZExt;
// FALL THROUGH // FALL THROUGH
case ABIArgInfo::Direct: case ABIArgInfo::Direct:

View File

@ -1390,7 +1390,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
// The index must always be an integer, which is not an aggregate. Emit it. // The index must always be an integer, which is not an aggregate. Emit it.
llvm::Value *Idx = EmitScalarExpr(E->getIdx()); llvm::Value *Idx = EmitScalarExpr(E->getIdx());
QualType IdxTy = E->getIdx()->getType(); QualType IdxTy = E->getIdx()->getType();
bool IdxSigned = IdxTy->isSignedIntegerType(); bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType();
// If the base is a vector type, then we are forming a vector element lvalue // If the base is a vector type, then we are forming a vector element lvalue
// with this subscript. // with this subscript.

View File

@ -489,7 +489,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// size_t. That's just a gloss, though, and it's wrong in one // size_t. That's just a gloss, though, and it's wrong in one
// important way: if the count is negative, it's an error even if // important way: if the count is negative, it's an error even if
// the cookie size would bring the total size >= 0. // the cookie size would bring the total size >= 0.
bool isSigned = e->getArraySize()->getType()->isSignedIntegerType(); bool isSigned
= e->getArraySize()->getType()->isSignedIntegerOrEnumerationType();
const llvm::IntegerType *numElementsType const llvm::IntegerType *numElementsType
= cast<llvm::IntegerType>(numElements->getType()); = cast<llvm::IntegerType>(numElements->getType());
unsigned numElementsWidth = numElementsType->getBitWidth(); unsigned numElementsWidth = numElementsType->getBitWidth();

View File

@ -610,12 +610,12 @@ public:
return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(destType)); return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(destType));
case CK_IntegralCast: { case CK_IntegralCast: {
bool isSigned = subExpr->getType()->isSignedIntegerType(); bool isSigned = subExpr->getType()->isSignedIntegerOrEnumerationType();
return llvm::ConstantExpr::getIntegerCast(C, destType, isSigned); return llvm::ConstantExpr::getIntegerCast(C, destType, isSigned);
} }
case CK_IntegralToPointer: { case CK_IntegralToPointer: {
bool isSigned = subExpr->getType()->isSignedIntegerType(); bool isSigned = subExpr->getType()->isSignedIntegerOrEnumerationType();
C = llvm::ConstantExpr::getIntegerCast(C, CGM.IntPtrTy, isSigned); C = llvm::ConstantExpr::getIntegerCast(C, CGM.IntPtrTy, isSigned);
return llvm::ConstantExpr::getIntToPtr(C, destType); return llvm::ConstantExpr::getIntToPtr(C, destType);
} }
@ -625,13 +625,13 @@ public:
llvm::Constant::getNullValue(C->getType())); llvm::Constant::getNullValue(C->getType()));
case CK_IntegralToFloating: case CK_IntegralToFloating:
if (subExpr->getType()->isSignedIntegerType()) if (subExpr->getType()->isSignedIntegerOrEnumerationType())
return llvm::ConstantExpr::getSIToFP(C, destType); return llvm::ConstantExpr::getSIToFP(C, destType);
else else
return llvm::ConstantExpr::getUIToFP(C, destType); return llvm::ConstantExpr::getUIToFP(C, destType);
case CK_FloatingToIntegral: case CK_FloatingToIntegral:
if (E->getType()->isSignedIntegerType()) if (E->getType()->isSignedIntegerOrEnumerationType())
return llvm::ConstantExpr::getFPToSI(C, destType); return llvm::ConstantExpr::getFPToSI(C, destType);
else else
return llvm::ConstantExpr::getFPToUI(C, destType); return llvm::ConstantExpr::getFPToUI(C, destType);

View File

@ -400,7 +400,7 @@ public:
// Binary Operators. // Binary Operators.
Value *EmitMul(const BinOpInfo &Ops) { Value *EmitMul(const BinOpInfo &Ops) {
if (Ops.Ty->isSignedIntegerType()) { if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
case LangOptions::SOB_Undefined: case LangOptions::SOB_Undefined:
return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul"); return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
@ -568,7 +568,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
// First, convert to the correct width so that we control the kind of // First, convert to the correct width so that we control the kind of
// extension. // extension.
const llvm::Type *MiddleTy = CGF.IntPtrTy; const llvm::Type *MiddleTy = CGF.IntPtrTy;
bool InputSigned = SrcType->isSignedIntegerType(); bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
llvm::Value* IntResult = llvm::Value* IntResult =
Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
// Then, cast to pointer. // Then, cast to pointer.
@ -610,7 +610,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
// Finally, we have the arithmetic types: real int/float. // Finally, we have the arithmetic types: real int/float.
if (isa<llvm::IntegerType>(Src->getType())) { if (isa<llvm::IntegerType>(Src->getType())) {
bool InputSigned = SrcType->isSignedIntegerType(); bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
if (isa<llvm::IntegerType>(DstTy)) if (isa<llvm::IntegerType>(DstTy))
return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
else if (InputSigned) else if (InputSigned)
@ -621,7 +621,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
assert(Src->getType()->isFloatingPointTy() && "Unknown real conversion"); assert(Src->getType()->isFloatingPointTy() && "Unknown real conversion");
if (isa<llvm::IntegerType>(DstTy)) { if (isa<llvm::IntegerType>(DstTy)) {
if (DstType->isSignedIntegerType()) if (DstType->isSignedIntegerOrEnumerationType())
return Builder.CreateFPToSI(Src, DstTy, "conv"); return Builder.CreateFPToSI(Src, DstTy, "conv");
else else
return Builder.CreateFPToUI(Src, DstTy, "conv"); return Builder.CreateFPToUI(Src, DstTy, "conv");
@ -807,7 +807,7 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
// integer value. // integer value.
Value *Base = Visit(E->getBase()); Value *Base = Visit(E->getBase());
Value *Idx = Visit(E->getIdx()); Value *Idx = Visit(E->getIdx());
bool IdxSigned = E->getIdx()->getType()->isSignedIntegerType(); bool IdxSigned = E->getIdx()->getType()->isSignedIntegerOrEnumerationType();
Idx = Builder.CreateIntCast(Idx, CGF.Int32Ty, IdxSigned, "vecidxcast"); Idx = Builder.CreateIntCast(Idx, CGF.Int32Ty, IdxSigned, "vecidxcast");
return Builder.CreateExtractElement(Base, Idx, "vecext"); return Builder.CreateExtractElement(Base, Idx, "vecext");
} }
@ -1136,7 +1136,7 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
// First, convert to the correct width so that we control the kind of // First, convert to the correct width so that we control the kind of
// extension. // extension.
const llvm::Type *MiddleTy = CGF.IntPtrTy; const llvm::Type *MiddleTy = CGF.IntPtrTy;
bool InputSigned = E->getType()->isSignedIntegerType(); bool InputSigned = E->getType()->isSignedIntegerOrEnumerationType();
llvm::Value* IntResult = llvm::Value* IntResult =
Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
@ -1279,7 +1279,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
// Note that signed integer inc/dec with width less than int can't // Note that signed integer inc/dec with width less than int can't
// overflow because of promotion rules; we're just eliding a few steps here. // overflow because of promotion rules; we're just eliding a few steps here.
if (type->isSignedIntegerType() && if (type->isSignedIntegerOrEnumerationType() &&
value->getType()->getPrimitiveSizeInBits() >= value->getType()->getPrimitiveSizeInBits() >=
CGF.CGM.IntTy->getBitWidth()) CGF.CGM.IntTy->getBitWidth())
value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc); value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc);
@ -1438,7 +1438,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
// Compute the index // Compute the index
Expr *IdxExpr = E->getIndexExpr(ON.getArrayExprIndex()); Expr *IdxExpr = E->getIndexExpr(ON.getArrayExprIndex());
llvm::Value* Idx = CGF.EmitScalarExpr(IdxExpr); llvm::Value* Idx = CGF.EmitScalarExpr(IdxExpr);
bool IdxSigned = IdxExpr->getType()->isSignedIntegerType(); bool IdxSigned = IdxExpr->getType()->isSignedIntegerOrEnumerationType();
Idx = Builder.CreateIntCast(Idx, ResultType, IdxSigned, "conv"); Idx = Builder.CreateIntCast(Idx, ResultType, IdxSigned, "conv");
// Save the element type // Save the element type
@ -1820,7 +1820,7 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
if (!Ops.Ty->isAnyPointerType()) { if (!Ops.Ty->isAnyPointerType()) {
if (Ops.Ty->isSignedIntegerType()) { if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
case LangOptions::SOB_Undefined: case LangOptions::SOB_Undefined:
return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add"); return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add");
@ -1870,7 +1870,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
// Zero or sign extend the pointer value based on whether the index is // Zero or sign extend the pointer value based on whether the index is
// signed or not. // signed or not.
const llvm::Type *IdxType = CGF.IntPtrTy; const llvm::Type *IdxType = CGF.IntPtrTy;
if (IdxExp->getType()->isSignedIntegerType()) if (IdxExp->getType()->isSignedIntegerOrEnumerationType())
Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext"); Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext");
else else
Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext"); Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext");
@ -1905,7 +1905,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
if (!isa<llvm::PointerType>(Ops.LHS->getType())) { if (!isa<llvm::PointerType>(Ops.LHS->getType())) {
if (Ops.Ty->isSignedIntegerType()) { if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
case LangOptions::SOB_Undefined: case LangOptions::SOB_Undefined:
return Builder.CreateNSWSub(Ops.LHS, Ops.RHS, "sub"); return Builder.CreateNSWSub(Ops.LHS, Ops.RHS, "sub");
@ -1945,7 +1945,7 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
// Zero or sign extend the pointer value based on whether the index is // Zero or sign extend the pointer value based on whether the index is
// signed or not. // signed or not.
const llvm::Type *IdxType = CGF.IntPtrTy; const llvm::Type *IdxType = CGF.IntPtrTy;
if (BinOp->getRHS()->getType()->isSignedIntegerType()) if (BinOp->getRHS()->getType()->isSignedIntegerOrEnumerationType())
Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext"); Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext");
else else
Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext"); Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext");

View File

@ -234,7 +234,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty)); CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty));
uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes); uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes);
bool IsSigned = FD->getType()->isSignedIntegerType(); bool IsSigned = FD->getType()->isSignedIntegerOrEnumerationType();
if (FieldSize > TypeSizeInBits) { if (FieldSize > TypeSizeInBits) {
// We have a wide bit-field. The extra bits are only used for padding, so // We have a wide bit-field. The extra bits are only used for padding, so

View File

@ -1334,6 +1334,7 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
return; return;
} }
// FIXME: Scoped enums?
if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) || if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) ||
(SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) { (SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) {
if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) { if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) {

View File

@ -8262,7 +8262,7 @@ static bool isRepresentableIntegerValue(ASTContext &Context,
unsigned BitWidth = Context.getIntWidth(T); unsigned BitWidth = Context.getIntWidth(T);
if (Value.isUnsigned() || Value.isNonNegative()) { if (Value.isUnsigned() || Value.isNonNegative()) {
if (T->isSignedIntegerType()) if (T->isSignedIntegerOrEnumerationType())
--BitWidth; --BitWidth;
return Value.getActiveBits() <= BitWidth; return Value.getActiveBits() <= BitWidth;
} }
@ -8285,8 +8285,8 @@ static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
}; };
unsigned BitWidth = Context.getTypeSize(T); unsigned BitWidth = Context.getTypeSize(T);
QualType *Types = T->isSignedIntegerType()? SignedIntegralTypes QualType *Types = T->isSignedIntegerOrEnumerationType()? SignedIntegralTypes
: UnsignedIntegralTypes; : UnsignedIntegralTypes;
for (unsigned I = 0; I != NumTypes; ++I) for (unsigned I = 0; I != NumTypes; ++I)
if (Context.getTypeSize(Types[I]) > BitWidth) if (Context.getTypeSize(Types[I]) > BitWidth)
return Types[I]; return Types[I];
@ -8420,7 +8420,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
// type that is supposed to be large enough to represent the incremented // type that is supposed to be large enough to represent the incremented
// value, then increment. // value, then increment.
EnumVal = LastEnumConst->getInitVal(); EnumVal = LastEnumConst->getInitVal();
EnumVal.setIsSigned(EltTy->isSignedIntegerType()); EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType());
EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy));
++EnumVal; ++EnumVal;
@ -8444,7 +8444,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
// Make the enumerator value match the signedness and size of the // Make the enumerator value match the signedness and size of the
// enumerator's type. // enumerator's type.
EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy));
EnumVal.setIsSigned(EltTy->isSignedIntegerType()); EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType());
} }
return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
@ -8702,7 +8702,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
} else { } else {
NewTy = BestType; NewTy = BestType;
NewWidth = BestWidth; NewWidth = BestWidth;
NewSign = BestType->isSignedIntegerType(); NewSign = BestType->isSignedIntegerOrEnumerationType();
} }
// Adjust the APSInt value. // Adjust the APSInt value.

View File

@ -501,7 +501,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
= CondExpr->isTypeDependent() || CondExpr->isValueDependent(); = CondExpr->isTypeDependent() || CondExpr->isValueDependent();
unsigned CondWidth unsigned CondWidth
= HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion);
bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType(); bool CondIsSigned
= CondTypeBeforePromotion->isSignedIntegerOrEnumerationType();
// Accumulate all of the case values in a vector so that we can sort them // Accumulate all of the case values in a vector so that we can sort them
// and detect duplicates. This vector contains the APInt for the case after // and detect duplicates. This vector contains the APInt for the case after

View File

@ -3707,7 +3707,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
unsigned AllowedBits = Context.getTypeSize(IntegerType); unsigned AllowedBits = Context.getTypeSize(IntegerType);
if (Value.getBitWidth() != AllowedBits) if (Value.getBitWidth() != AllowedBits)
Value = Value.extOrTrunc(AllowedBits); Value = Value.extOrTrunc(AllowedBits);
Value.setIsSigned(IntegerType->isSignedIntegerType()); Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
} else { } else {
llvm::APSInt OldValue = Value; llvm::APSInt OldValue = Value;
@ -3716,10 +3716,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
unsigned AllowedBits = Context.getTypeSize(IntegerType); unsigned AllowedBits = Context.getTypeSize(IntegerType);
if (Value.getBitWidth() != AllowedBits) if (Value.getBitWidth() != AllowedBits)
Value = Value.extOrTrunc(AllowedBits); Value = Value.extOrTrunc(AllowedBits);
Value.setIsSigned(IntegerType->isSignedIntegerType()); Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
// Complain if an unsigned parameter received a negative value. // Complain if an unsigned parameter received a negative value.
if (IntegerType->isUnsignedIntegerType() if (IntegerType->isUnsignedIntegerOrEnumerationType()
&& (OldValue.isSigned() && OldValue.isNegative())) { && (OldValue.isSigned() && OldValue.isNegative())) {
Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative) Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative)
<< OldValue.toString(10) << Value.toString(10) << Param->getType() << OldValue.toString(10) << Value.toString(10) << Param->getType()
@ -3729,7 +3729,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// Complain if we overflowed the template parameter's type. // Complain if we overflowed the template parameter's type.
unsigned RequiredBits; unsigned RequiredBits;
if (IntegerType->isUnsignedIntegerType()) if (IntegerType->isUnsignedIntegerOrEnumerationType())
RequiredBits = OldValue.getActiveBits(); RequiredBits = OldValue.getActiveBits();
else if (OldValue.isUnsigned()) else if (OldValue.isUnsigned())
RequiredBits = OldValue.getActiveBits() + 1; RequiredBits = OldValue.getActiveBits() + 1;

View File

@ -2464,7 +2464,7 @@ void ExprEngine::VisitOffsetOfExpr(const OffsetOfExpr* OOE,
const APSInt &IV = Res.Val.getInt(); const APSInt &IV = Res.Val.getInt();
assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType())); assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
assert(OOE->getType()->isIntegerType()); assert(OOE->getType()->isIntegerType());
assert(IV.isSigned() == OOE->getType()->isSignedIntegerType()); assert(IV.isSigned() == OOE->getType()->isSignedIntegerOrEnumerationType());
SVal X = svalBuilder.makeIntVal(IV); SVal X = svalBuilder.makeIntVal(IV);
MakeNode(Dst, OOE, Pred, GetState(Pred)->BindExpr(OOE, X)); MakeNode(Dst, OOE, Pred, GetState(Pred)->BindExpr(OOE, X));
return; return;

View File

@ -0,0 +1,9 @@
// RUN: %clang_cc1 -std=c++0x -emit-llvm -o - %s
// PR9923
enum class Color { red, blue, green };
void f(Color);
void g() {
f(Color::red);
}