diff options
author | John McCall <rjmccall@apple.com> | 2010-11-09 22:22:12 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-11-09 22:22:12 +0000 |
commit | 091f23f1d6d4bcffd6641cda72a6831e08c02ea7 (patch) | |
tree | 68b3412e591456abb9639ef22cf2d705511b5db1 /lib/Sema/SemaChecking.cpp | |
parent | 73167ec561c1dc3f34cbca2287c83985cbf2bfdf (diff) |
Split out -Wconversion warnings about constant precision into their
own subcategory, -Wconstant-conversion, which is on by default.
Tweak the constant folder to give better results in the invalid
case of a negative shift amount.
Implements rdar://problem/6792488
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118636 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index acd830ddec..4cf466311b 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2165,8 +2165,12 @@ struct IntRange { if (const ComplexType *CT = dyn_cast<ComplexType>(T)) T = CT->getElementType().getTypePtr(); + // For enum types, use the known bit width of the enumerators. if (const EnumType *ET = dyn_cast<EnumType>(T)) { EnumDecl *Enum = ET->getDecl(); + if (!Enum->isDefinition()) + return IntRange(C.getIntWidth(QualType(T, 0)), false); + unsigned NumPositive = Enum->getNumPositiveBits(); unsigned NumNegative = Enum->getNumNegativeBits(); @@ -2590,6 +2594,15 @@ void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, << E->getType() << T << E->getSourceRange() << SourceRange(CContext); } +std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { + if (!Range.Width) return "0"; + + llvm::APSInt ValueInRange = Value; + ValueInRange.setIsSigned(!Range.NonNegative); + ValueInRange.trunc(Range.Width); + return ValueInRange.toString(10); +} + void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, bool *ICContext = 0) { if (E->isTypeDependent() || E->isValueDependent()) return; @@ -2670,6 +2683,19 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, IntRange TargetRange = IntRange::forCanonicalType(S.Context, Target); if (SourceRange.Width > TargetRange.Width) { + // If the source is a constant, use a default-on diagnostic. + // TODO: this should happen for bitfield stores, too. + llvm::APSInt Value(32); + if (E->isIntegerConstantExpr(Value, S.Context)) { + std::string PrettySourceValue = Value.toString(10); + std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); + + S.Diag(E->getExprLoc(), diag::warn_impcast_integer_precision_constant) + << PrettySourceValue << PrettyTargetValue + << E->getType() << T << E->getSourceRange() << clang::SourceRange(CC); + return; + } + // People want to build with -Wshorten-64-to-32 and not -Wconversion // and by god we'll let them. if (SourceRange.Width == 64 && TargetRange.Width == 32) |