When -Wconversion computes the range of a type, it uses the (bit-)range
of the enumerators rather than the actual expressible range. This is
great when dealing with opaque *values* of that type, but when computing
the range of the type for purposes of converting *into* it, it produces
warnings in cases we don't care about (e.g. enum_t x = 500;). Divide
the logic into these two cases and use the more conservative range for
targets.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118735 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 921df8e..2f3abfc 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -2145,19 +2145,19 @@
: Width(Width), NonNegative(NonNegative)
{}
- // Returns the range of the bool type.
+ /// Returns the range of the bool type.
static IntRange forBoolType() {
return IntRange(1, true);
}
- // Returns the range of an integral type.
- static IntRange forType(ASTContext &C, QualType T) {
- return forCanonicalType(C, T->getCanonicalTypeInternal().getTypePtr());
+ /// Returns the range of an opaque value of the given integral type.
+ static IntRange forValueOfType(ASTContext &C, QualType T) {
+ return forValueOfCanonicalType(C,
+ T->getCanonicalTypeInternal().getTypePtr());
}
- // Returns the range of an integeral type based on its canonical
- // representation.
- static IntRange forCanonicalType(ASTContext &C, const Type *T) {
+ /// Returns the range of an opaque value of a canonical integral type.
+ static IntRange forValueOfCanonicalType(ASTContext &C, const Type *T) {
assert(T->isCanonicalUnqualified());
if (const VectorType *VT = dyn_cast<VectorType>(T))
@@ -2183,13 +2183,34 @@
return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
}
- // Returns the supremum of two ranges: i.e. their conservative merge.
+ /// Returns the "target" range of a canonical integral type, i.e.
+ /// the range of values expressible in the type.
+ ///
+ /// This matches forValueOfCanonicalType except that enums have the
+ /// full range of their type, not the range of their enumerators.
+ static IntRange forTargetOfCanonicalType(ASTContext &C, const Type *T) {
+ assert(T->isCanonicalUnqualified());
+
+ if (const VectorType *VT = dyn_cast<VectorType>(T))
+ T = VT->getElementType().getTypePtr();
+ if (const ComplexType *CT = dyn_cast<ComplexType>(T))
+ T = CT->getElementType().getTypePtr();
+ if (const EnumType *ET = dyn_cast<EnumType>(T))
+ T = ET->getDecl()->getIntegerType().getTypePtr();
+
+ const BuiltinType *BT = cast<BuiltinType>(T);
+ assert(BT->isInteger());
+
+ return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
+ }
+
+ /// Returns the supremum of two ranges: i.e. their conservative merge.
static IntRange join(IntRange L, IntRange R) {
return IntRange(std::max(L.Width, R.Width),
L.NonNegative && R.NonNegative);
}
- // Returns the infinum of two ranges: i.e. their aggressive merge.
+ /// Returns the infinum of two ranges: i.e. their aggressive merge.
static IntRange meet(IntRange L, IntRange R) {
return IntRange(std::min(L.Width, R.Width),
L.NonNegative || R.NonNegative);
@@ -2256,7 +2277,7 @@
if (CE->getCastKind() == CK_NoOp)
return GetExprRange(C, CE->getSubExpr(), MaxWidth);
- IntRange OutputTypeRange = IntRange::forType(C, CE->getType());
+ IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType());
bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast);
if (!isIntegerCast && CE->getCastKind() == CK_Unknown)
@@ -2315,12 +2336,12 @@
case BO_RemAssign:
case BO_AddAssign:
case BO_SubAssign:
- return IntRange::forType(C, E->getType());
+ return IntRange::forValueOfType(C, E->getType());
// Operations with opaque sources are black-listed.
case BO_PtrMemD:
case BO_PtrMemI:
- return IntRange::forType(C, E->getType());
+ return IntRange::forValueOfType(C, E->getType());
// Bitwise-and uses the *infinum* of the two source ranges.
case BO_And:
@@ -2335,14 +2356,14 @@
if (IntegerLiteral *I
= dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) {
if (I->getValue() == 1) {
- IntRange R = IntRange::forType(C, E->getType());
+ IntRange R = IntRange::forValueOfType(C, E->getType());
return IntRange(R.Width, /*NonNegative*/ true);
}
}
// fallthrough
case BO_ShlAssign:
- return IntRange::forType(C, E->getType());
+ return IntRange::forValueOfType(C, E->getType());
// Right shift by a constant can narrow its left argument.
case BO_Shr:
@@ -2371,7 +2392,7 @@
// Black-list pointer subtractions.
case BO_Sub:
if (BO->getLHS()->getType()->isPointerType())
- return IntRange::forType(C, E->getType());
+ return IntRange::forValueOfType(C, E->getType());
// fallthrough
default:
@@ -2394,7 +2415,7 @@
// Operations with opaque sources are black-listed.
case UO_Deref:
case UO_AddrOf: // should be impossible
- return IntRange::forType(C, E->getType());
+ return IntRange::forValueOfType(C, E->getType());
default:
return GetExprRange(C, UO->getSubExpr(), MaxWidth);
@@ -2402,7 +2423,7 @@
}
if (dyn_cast<OffsetOfExpr>(E)) {
- IntRange::forType(C, E->getType());
+ IntRange::forValueOfType(C, E->getType());
}
FieldDecl *BitField = E->getBitField();
@@ -2413,7 +2434,7 @@
return IntRange(BitWidth, BitField->getType()->isUnsignedIntegerType());
}
- return IntRange::forType(C, E->getType());
+ return IntRange::forValueOfType(C, E->getType());
}
IntRange GetExprRange(ASTContext &C, Expr *E) {
@@ -2733,7 +2754,7 @@
return;
IntRange SourceRange = GetExprRange(S.Context, E);
- IntRange TargetRange = IntRange::forCanonicalType(S.Context, Target);
+ IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target);
if (SourceRange.Width > TargetRange.Width) {
// If the source is a constant, use a default-on diagnostic.
diff --git a/test/Sema/constant-conversion.c b/test/Sema/constant-conversion.c
index 9586212..b01813a 100644
--- a/test/Sema/constant-conversion.c
+++ b/test/Sema/constant-conversion.c
@@ -18,3 +18,9 @@
struct { int bit : 1; } a;
a.bit = 1; // shouldn't warn
}
+
+enum Test2 { K_zero, K_one };
+enum Test2 test2(enum Test2 *t) {
+ *t = 20;
+ return 10; // shouldn't warn
+}