diff options
author | John McCall <rjmccall@apple.com> | 2010-11-10 23:38:19 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-11-10 23:38:19 +0000 |
commit | 1844a6e1074a5c1fd8eadac7fc7317c3e29d4653 (patch) | |
tree | 31b15e15db63aa9e6196ec1fcf3b464278c75bee /lib/Sema/SemaChecking.cpp | |
parent | 3473a10ee6ba13ebba7b71f31b244afb94917a86 (diff) |
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
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 921df8e2fb..2f3abfcb3d 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2145,19 +2145,19 @@ struct IntRange { : 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 @@ struct IntRange { 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 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { 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 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { 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 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { 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 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // 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 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // 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 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { } if (dyn_cast<OffsetOfExpr>(E)) { - IntRange::forType(C, E->getType()); + IntRange::forValueOfType(C, E->getType()); } FieldDecl *BitField = E->getBitField(); @@ -2413,7 +2434,7 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { 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 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, 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. |