]> granicus.if.org Git - clang/commitdiff
Introduce Type::isSignedIntegerOrEnumerationType() and
authorDouglas Gregor <dgregor@apple.com>
Fri, 20 May 2011 16:38:50 +0000 (16:38 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 20 May 2011 16:38:50 +0000 (16:38 +0000)
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>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131735 91177308-0d34-0410-b5e6-96231b3b80d8

17 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/CanonicalType.h
include/clang/AST/Type.h
lib/AST/ExprConstant.cpp
lib/AST/Type.cpp
lib/CodeGen/CGCall.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprCXX.cpp
lib/CodeGen/CGExprConstant.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CGRecordLayoutBuilder.cpp
lib/Sema/SemaCXXCast.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaStmt.cpp
lib/Sema/SemaTemplate.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/CodeGenCXX/scoped-enums.cpp [new file with mode: 0644]

index 2e84c5b08da087f052bb9dd03baf44f9db33f803..f519af712cb725831ff296975ae88c2bfb510b0f 100644 (file)
@@ -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;
   }
index b3550f87732350cbdaac0a691cb3b4882fe3010d..fb00d8630166d2ea1a4eb5afa83f696cb8c83fc5 100644 (file)
@@ -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)
 
index b883002f9f4419d2b561698b1ac9b86f0d15fdc6..1e8642f76a61fc00377cfb0e93f7bbaa7b42b012 100644 (file)
@@ -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.
index b0af5f8c91dfcc8c6709dc1e5959fb1dddad7b65..1126289aee496169d9ea1a66f2bc3d6afaec7a0c 100644 (file)
@@ -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() &&
index 1e7839334146030aa1815063fcf4b0e51ac78e69..9f576db5355abe9557612ba010348467c9442583 100644 (file)
@@ -648,6 +648,20 @@ bool Type::isSignedIntegerType() const {
   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 {
   if (const VectorType *VT = dyn_cast<VectorType>(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<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 {
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isUnsignedIntegerType();
index fba89a76fc65df9482f1a020c3a7cc128a672dad..4c9f3d467a11e75b9dc4469a33c440ff2db5d862 100644 (file)
@@ -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:
index bc2cd35bc5912b3d48b98147dc5e7b7061e12003..59f700efb85967c8d84a72a7d9e4d76fd027220e 100644 (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.
   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.
index 1d668477c1bb429a2a14e9836d659c2f7c2cef8b..81fee677f61a2184a06b22a039ce921310110a2c 100644 (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
   // 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<llvm::IntegerType>(numElements->getType());
   unsigned numElementsWidth = numElementsType->getBitWidth();
index 8054d4b0372ce57e6d0f5263e3a6f62d6b541caa..da37bd5b0a1fa6d93b83b92ad5c0f28142681f02 100644 (file)
@@ -610,12 +610,12 @@ public:
       return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(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);
index fcada3a92add4f1258670c854eca8264d9a3c1fe..be9089a9c5258322f1cd2e84b517d06fa655b1de 100644 (file)
@@ -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<llvm::IntegerType>(Src->getType())) {
-    bool InputSigned = SrcType->isSignedIntegerType();
+    bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
     if (isa<llvm::IntegerType>(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<llvm::IntegerType>(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<llvm::PointerType>(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");
index 3d9fd88613b793cf898c50639ab7ba2bb92ba506..0d72f854ba3e0e5e8387c50c014fa13f82047937 100644 (file)
@@ -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
index 31a5f92dacc5db3633dee1098c3bd180cb5f38d3..c7038322e1c3950cb0d58aa0293609fa2ea0c0ed 100644 (file)
@@ -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)) {
index aafab7d37b85cc70506bc7a6002061b35ff9a40d..2501e7f4d4a5855f3e3fbb1be174f0fc4eb4c045 100644 (file)
@@ -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.
index e541870ce8f815d8e1336e959e728a2df829fac9..186136b7939bd73b1800a5bea475fc1992798e1f 100644 (file)
@@ -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
index aaadac2e5f443e79c87d9fb41e57d42706490214..9d8d7f608e3c8844f53979c50e93259e653bc452 100644 (file)
@@ -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;
index 69ef4cfc4cad443365c86d81541f321af544e28e..60b16abd196b234a815c9c43a38ef26028e340b6 100644 (file)
@@ -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 (file)
index 0000000..d40ab36
--- /dev/null
@@ -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);
+}