From: Douglas Gregor Date: Fri, 20 May 2011 16:38:50 +0000 (+0000) Subject: Introduce Type::isSignedIntegerOrEnumerationType() and X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=575a1c9dc8dc5b4977194993e289f9eda7295c39;p=clang 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 / . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131735 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 2e84c5b08d..f519af712c 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1453,7 +1453,8 @@ public: /// MakeIntValue - Make an APSInt of the appropriate width and /// signedness for the given \arg Value and integer \arg Type. 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; return Res; } diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index b3550f8773..fb00d86301 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -291,6 +291,8 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) 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, isSpecifierType) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index b883002f9f..1e8642f76a 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1436,6 +1436,14 @@ public: /// or an enum decl which has an unsigned representation. 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, /// according to the rules of C99 6.7.5p3. It is not legal to call this on /// incomplete types. diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index b0af5f8c91..1126289aee 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -221,7 +221,7 @@ static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType, APFloat &Value, const ASTContext &Ctx) { unsigned DestWidth = Ctx.getIntWidth(DestType); // Determine whether we are converting to unsigned or signed. - bool DestSigned = DestType->isSignedIntegerType(); + bool DestSigned = DestType->isSignedIntegerOrEnumerationType(); // FIXME: Warning for overflow. 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. // If the input is signed, do a sign extend, noop, or truncate. Result = Result.extOrTrunc(DestWidth); - Result.setIsUnsigned(DestType->isUnsignedIntegerType()); + Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType()); return Result; } @@ -947,7 +947,7 @@ public: bool Success(const llvm::APSInt &SI, const Expr *E) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); - assert(SI.isSigned() == E->getType()->isSignedIntegerType() && + assert(SI.isSigned() == E->getType()->isSignedIntegerOrEnumerationType() && "Invalid evaluation result."); assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); @@ -961,7 +961,8 @@ public: assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(APSInt(I)); - Result.getInt().setIsUnsigned(E->getType()->isUnsignedIntegerType()); + Result.getInt().setIsUnsigned( + E->getType()->isUnsignedIntegerOrEnumerationType()); return true; } @@ -2558,7 +2559,7 @@ static bool Evaluate(EvalInfo &Info, const Expr *E) { if (E->getType()->isVectorType()) { if (!EvaluateVector(E, Info.EvalResult.Val, Info)) return false; - } else if (E->getType()->isIntegerType()) { + } else if (E->getType()->isIntegralOrEnumerationType()) { if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(E)) return false; if (Info.EvalResult.Val.isLValue() && diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1e78393341..9f576db535 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -648,6 +648,20 @@ bool Type::isSignedIntegerType() const { return false; } +bool Type::isSignedIntegerOrEnumerationType() const { + if (const BuiltinType *BT = dyn_cast(CanonicalType)) { + return BT->getKind() >= BuiltinType::Char_S && + BT->getKind() <= BuiltinType::Int128; + } + + if (const EnumType *ET = dyn_cast(CanonicalType)) { + if (ET->getDecl()->isComplete()) + return ET->getDecl()->getIntegerType()->isSignedIntegerType(); + } + + return false; +} + bool Type::hasSignedIntegerRepresentation() const { if (const VectorType *VT = dyn_cast(CanonicalType)) return VT->getElementType()->isSignedIntegerType(); @@ -674,6 +688,20 @@ bool Type::isUnsignedIntegerType() const { return false; } +bool Type::isUnsignedIntegerOrEnumerationType() const { + if (const BuiltinType *BT = dyn_cast(CanonicalType)) { + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::UInt128; + } + + if (const EnumType *ET = dyn_cast(CanonicalType)) { + if (ET->getDecl()->isComplete()) + return ET->getDecl()->getIntegerType()->isUnsignedIntegerType(); + } + + return false; +} + bool Type::hasUnsignedIntegerRepresentation() const { if (const VectorType *VT = dyn_cast(CanonicalType)) return VT->getElementType()->isUnsignedIntegerType(); diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index fba89a76fc..4c9f3d467a 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -809,9 +809,9 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, // sense to do it here because parameters are so messed up. switch (AI.getKind()) { case ABIArgInfo::Extend: - if (ParamType->isSignedIntegerType()) + if (ParamType->isSignedIntegerOrEnumerationType()) Attributes |= llvm::Attribute::SExt; - else if (ParamType->isUnsignedIntegerType()) + else if (ParamType->isUnsignedIntegerOrEnumerationType()) Attributes |= llvm::Attribute::ZExt; // FALL THROUGH case ABIArgInfo::Direct: diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index bc2cd35bc5..59f700efb8 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1390,7 +1390,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { // The index must always be an integer, which is not an aggregate. Emit it. llvm::Value *Idx = EmitScalarExpr(E->getIdx()); 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 // with this subscript. diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 1d668477c1..81fee677f6 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -489,7 +489,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, // 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 // 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 = cast(numElements->getType()); unsigned numElementsWidth = numElementsType->getBitWidth(); diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 8054d4b037..da37bd5b0a 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -610,12 +610,12 @@ public: return llvm::ConstantPointerNull::get(cast(destType)); case CK_IntegralCast: { - bool isSigned = subExpr->getType()->isSignedIntegerType(); + bool isSigned = subExpr->getType()->isSignedIntegerOrEnumerationType(); return llvm::ConstantExpr::getIntegerCast(C, destType, isSigned); } case CK_IntegralToPointer: { - bool isSigned = subExpr->getType()->isSignedIntegerType(); + bool isSigned = subExpr->getType()->isSignedIntegerOrEnumerationType(); C = llvm::ConstantExpr::getIntegerCast(C, CGM.IntPtrTy, isSigned); return llvm::ConstantExpr::getIntToPtr(C, destType); } @@ -625,13 +625,13 @@ public: llvm::Constant::getNullValue(C->getType())); case CK_IntegralToFloating: - if (subExpr->getType()->isSignedIntegerType()) + if (subExpr->getType()->isSignedIntegerOrEnumerationType()) return llvm::ConstantExpr::getSIToFP(C, destType); else return llvm::ConstantExpr::getUIToFP(C, destType); case CK_FloatingToIntegral: - if (E->getType()->isSignedIntegerType()) + if (E->getType()->isSignedIntegerOrEnumerationType()) return llvm::ConstantExpr::getFPToSI(C, destType); else return llvm::ConstantExpr::getFPToUI(C, destType); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index fcada3a92a..be9089a9c5 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -400,7 +400,7 @@ public: // Binary Operators. Value *EmitMul(const BinOpInfo &Ops) { - if (Ops.Ty->isSignedIntegerType()) { + if (Ops.Ty->isSignedIntegerOrEnumerationType()) { switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { case LangOptions::SOB_Undefined: 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 // extension. const llvm::Type *MiddleTy = CGF.IntPtrTy; - bool InputSigned = SrcType->isSignedIntegerType(); + bool InputSigned = SrcType->isSignedIntegerOrEnumerationType(); llvm::Value* IntResult = Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); // Then, cast to pointer. @@ -610,7 +610,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, // Finally, we have the arithmetic types: real int/float. if (isa(Src->getType())) { - bool InputSigned = SrcType->isSignedIntegerType(); + bool InputSigned = SrcType->isSignedIntegerOrEnumerationType(); if (isa(DstTy)) return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); else if (InputSigned) @@ -621,7 +621,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, assert(Src->getType()->isFloatingPointTy() && "Unknown real conversion"); if (isa(DstTy)) { - if (DstType->isSignedIntegerType()) + if (DstType->isSignedIntegerOrEnumerationType()) return Builder.CreateFPToSI(Src, DstTy, "conv"); else return Builder.CreateFPToUI(Src, DstTy, "conv"); @@ -807,7 +807,7 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { // integer value. Value *Base = Visit(E->getBase()); 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"); 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 // extension. const llvm::Type *MiddleTy = CGF.IntPtrTy; - bool InputSigned = E->getType()->isSignedIntegerType(); + bool InputSigned = E->getType()->isSignedIntegerOrEnumerationType(); llvm::Value* IntResult = 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 // overflow because of promotion rules; we're just eliding a few steps here. - if (type->isSignedIntegerType() && + if (type->isSignedIntegerOrEnumerationType() && value->getType()->getPrimitiveSizeInBits() >= CGF.CGM.IntTy->getBitWidth()) value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc); @@ -1438,7 +1438,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { // Compute the index Expr *IdxExpr = E->getIndexExpr(ON.getArrayExprIndex()); llvm::Value* Idx = CGF.EmitScalarExpr(IdxExpr); - bool IdxSigned = IdxExpr->getType()->isSignedIntegerType(); + bool IdxSigned = IdxExpr->getType()->isSignedIntegerOrEnumerationType(); Idx = Builder.CreateIntCast(Idx, ResultType, IdxSigned, "conv"); // Save the element type @@ -1820,7 +1820,7 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { if (!Ops.Ty->isAnyPointerType()) { - if (Ops.Ty->isSignedIntegerType()) { + if (Ops.Ty->isSignedIntegerOrEnumerationType()) { switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { case LangOptions::SOB_Undefined: 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 // signed or not. const llvm::Type *IdxType = CGF.IntPtrTy; - if (IdxExp->getType()->isSignedIntegerType()) + if (IdxExp->getType()->isSignedIntegerOrEnumerationType()) Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext"); else Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext"); @@ -1905,7 +1905,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { if (!isa(Ops.LHS->getType())) { - if (Ops.Ty->isSignedIntegerType()) { + if (Ops.Ty->isSignedIntegerOrEnumerationType()) { switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { case LangOptions::SOB_Undefined: 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 // signed or not. const llvm::Type *IdxType = CGF.IntPtrTy; - if (BinOp->getRHS()->getType()->isSignedIntegerType()) + if (BinOp->getRHS()->getType()->isSignedIntegerOrEnumerationType()) Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext"); else Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext"); diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 3d9fd88613..0d72f854ba 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -234,7 +234,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty)); uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes); - bool IsSigned = FD->getType()->isSignedIntegerType(); + bool IsSigned = FD->getType()->isSignedIntegerOrEnumerationType(); if (FieldSize > TypeSizeInBits) { // We have a wide bit-field. The extra bits are only used for padding, so diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 31a5f92dac..c7038322e1 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -1334,6 +1334,7 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, return; } + // FIXME: Scoped enums? if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) || (SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) { if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index aafab7d37b..2501e7f4d4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8262,7 +8262,7 @@ static bool isRepresentableIntegerValue(ASTContext &Context, unsigned BitWidth = Context.getIntWidth(T); if (Value.isUnsigned() || Value.isNonNegative()) { - if (T->isSignedIntegerType()) + if (T->isSignedIntegerOrEnumerationType()) --BitWidth; return Value.getActiveBits() <= BitWidth; } @@ -8285,8 +8285,8 @@ static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { }; unsigned BitWidth = Context.getTypeSize(T); - QualType *Types = T->isSignedIntegerType()? SignedIntegralTypes - : UnsignedIntegralTypes; + QualType *Types = T->isSignedIntegerOrEnumerationType()? SignedIntegralTypes + : UnsignedIntegralTypes; for (unsigned I = 0; I != NumTypes; ++I) if (Context.getTypeSize(Types[I]) > BitWidth) return Types[I]; @@ -8420,7 +8420,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // type that is supposed to be large enough to represent the incremented // value, then increment. EnumVal = LastEnumConst->getInitVal(); - EnumVal.setIsSigned(EltTy->isSignedIntegerType()); + EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType()); EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); ++EnumVal; @@ -8444,7 +8444,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // Make the enumerator value match the signedness and size of the // enumerator's type. EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); - EnumVal.setIsSigned(EltTy->isSignedIntegerType()); + EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType()); } return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, @@ -8702,7 +8702,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, } else { NewTy = BestType; NewWidth = BestWidth; - NewSign = BestType->isSignedIntegerType(); + NewSign = BestType->isSignedIntegerOrEnumerationType(); } // Adjust the APSInt value. diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index e541870ce8..186136b793 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -501,7 +501,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, = CondExpr->isTypeDependent() || CondExpr->isValueDependent(); unsigned CondWidth = 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 // and detect duplicates. This vector contains the APInt for the case after diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index aaadac2e5f..9d8d7f608e 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3707,7 +3707,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, unsigned AllowedBits = Context.getTypeSize(IntegerType); if (Value.getBitWidth() != AllowedBits) Value = Value.extOrTrunc(AllowedBits); - Value.setIsSigned(IntegerType->isSignedIntegerType()); + Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType()); } else { llvm::APSInt OldValue = Value; @@ -3716,10 +3716,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, unsigned AllowedBits = Context.getTypeSize(IntegerType); if (Value.getBitWidth() != AllowedBits) Value = Value.extOrTrunc(AllowedBits); - Value.setIsSigned(IntegerType->isSignedIntegerType()); + Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType()); // Complain if an unsigned parameter received a negative value. - if (IntegerType->isUnsignedIntegerType() + if (IntegerType->isUnsignedIntegerOrEnumerationType() && (OldValue.isSigned() && OldValue.isNegative())) { Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative) << 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. unsigned RequiredBits; - if (IntegerType->isUnsignedIntegerType()) + if (IntegerType->isUnsignedIntegerOrEnumerationType()) RequiredBits = OldValue.getActiveBits(); else if (OldValue.isUnsigned()) RequiredBits = OldValue.getActiveBits() + 1; diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 69ef4cfc4c..60b16abd19 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -2464,7 +2464,7 @@ void ExprEngine::VisitOffsetOfExpr(const OffsetOfExpr* OOE, const APSInt &IV = Res.Val.getInt(); assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType())); assert(OOE->getType()->isIntegerType()); - assert(IV.isSigned() == OOE->getType()->isSignedIntegerType()); + assert(IV.isSigned() == OOE->getType()->isSignedIntegerOrEnumerationType()); SVal X = svalBuilder.makeIntVal(IV); MakeNode(Dst, OOE, Pred, GetState(Pred)->BindExpr(OOE, X)); return; diff --git a/test/CodeGenCXX/scoped-enums.cpp b/test/CodeGenCXX/scoped-enums.cpp new file mode 100644 index 0000000000..d40ab36511 --- /dev/null +++ b/test/CodeGenCXX/scoped-enums.cpp @@ -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); +}