aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-11-09 22:22:12 +0000
committerJohn McCall <rjmccall@apple.com>2010-11-09 22:22:12 +0000
commit091f23f1d6d4bcffd6641cda72a6831e08c02ea7 (patch)
tree68b3412e591456abb9639ef22cf2d705511b5db1 /lib/Sema/SemaChecking.cpp
parent73167ec561c1dc3f34cbca2287c83985cbf2bfdf (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.cpp26
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)