diff options
author | Richard Trieu <rtrieu@google.com> | 2016-04-21 21:04:55 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2016-04-21 21:04:55 +0000 |
commit | be234c30ada79e38b47ee7b58abf4c87d419a60f (patch) | |
tree | fa97f34720cb6aeda17f9e2eebcea2b93f003a55 /clang/lib/Sema/SemaChecking.cpp | |
parent | 1725bde4cc55419ee8758b6f8fd42eec32fb0513 (diff) | |
download | bcm5719-llvm-be234c30ada79e38b47ee7b58abf4c87d419a60f.tar.gz bcm5719-llvm-be234c30ada79e38b47ee7b58abf4c87d419a60f.zip |
Split interesting warnings off from -Wfloat-conversion
Restructure the implict floating point to integer conversions so that
interesting sub-groups are under different flags. Breakdown of warnings:
No warning:
Exact conversions from floating point to integer:
int x = 10.0;
int x = 1e10;
-Wliteral-conversion - Floating point literal to integer with rounding:
int x = 5.5;
int x = -3.4;
-Wfloat-conversion - All conversions not covered by the above two:
int x = GetFloat();
int x = 5.5 + 3.5;
-Wfloat-zero-conversion - The expression converted has a non-zero floating
point value that gets converted to a zero integer value, excluded the cases
falling under -Wliteral-conversion. Subset of -Wfloat-conversion.
int x = 1.0 / 2.0;
-Wfloat-overflow-conversion - The floating point value is outside the range
of the integer type, exluding cases from -Wliteral conversion. Subset of
-Wfloat-conversion.
char x = 500;
char x = -1000;
-Wfloat-bool-conversion - Any conversion of a floating point type to bool.
Subset of -Wfloat-conversion.
if (GetFloat()) {}
bool x = 5.0;
-Wfloat-bool-constant-conversion - Conversion of a compile time evaluatable
floating point value to bool. Subset of -Wfloat-bool-conversion.
bool x = 1.0;
bool x = 4.0 / 20.0;
Also add EvaluateAsFloat to Sema, which is similar to EvaluateAsInt, but for
floating point values.
llvm-svn: 267054
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 111 |
1 files changed, 84 insertions, 27 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b1e6b99ce48..0592a830113 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7382,19 +7382,78 @@ void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow); } -/// Diagnose an implicit cast from a literal expression. Does not warn when the -/// cast wouldn't lose information. -void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, - SourceLocation CContext) { - // Try to convert the literal exactly to an integer. If we can, don't warn. + +/// Diagnose an implicit cast from a floating point value to an integer value. +void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, + + SourceLocation CContext) { + const bool IsBool = T->isSpecificBuiltinType(BuiltinType::Bool); + const bool PruneWarnings = !S.ActiveTemplateInstantiations.empty(); + + Expr *InnerE = E->IgnoreParenImpCasts(); + // We also want to warn on, e.g., "int i = -1.234" + if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(InnerE)) + if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus) + InnerE = UOp->getSubExpr()->IgnoreParenImpCasts(); + + const bool IsLiteral = + isa<FloatingLiteral>(E) || isa<FloatingLiteral>(InnerE); + + llvm::APFloat Value(0.0); + bool IsConstant = + E->EvaluateAsFloat(Value, S.Context, Expr::SE_AllowSideEffects); + if (!IsConstant) { + if (IsBool) { + return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_float_bool, + PruneWarnings); + } else { + return DiagnoseImpCast(S, E, T, CContext, + diag::warn_impcast_float_integer, PruneWarnings); + } + } + bool isExact = false; - const llvm::APFloat &Value = FL->getValue(); + llvm::APSInt IntegerValue(S.Context.getIntWidth(T), T->hasUnsignedIntegerRepresentation()); - if (Value.convertToInteger(IntegerValue, - llvm::APFloat::rmTowardZero, &isExact) - == llvm::APFloat::opOK && isExact) - return; + if (Value.convertToInteger(IntegerValue, llvm::APFloat::rmTowardZero, + &isExact) == llvm::APFloat::opOK && + isExact && !IsBool) { + if (IsLiteral) return; + return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_float_integer, + PruneWarnings); + } + + unsigned DiagID = 0; + if (IsBool) { + // Warn on all floating point to bool conversions + DiagID = diag::warn_impcast_float_to_bool; + } else if (IsLiteral) { + // Warn on floating point literal to integer. + DiagID = diag::warn_impcast_literal_float_to_integer; + } else if (IntegerValue == 0) { + if (Value.isZero()) { // Skip -0.0 to 0 conversion. + return DiagnoseImpCast(S, E, T, CContext, + diag::warn_impcast_float_integer, PruneWarnings); + } + // Warn on non-zero to zero conversion. + DiagID = diag::warn_impcast_float_to_integer_zero; + } else { + if (IntegerValue.isUnsigned()) { + if (!IntegerValue.isMaxValue()) { + return DiagnoseImpCast(S, E, T, CContext, + diag::warn_impcast_float_integer, PruneWarnings); + } + } else { // IntegerValue.isSigned() + if (!IntegerValue.isMaxSignedValue() && + !IntegerValue.isMinSignedValue()) { + return DiagnoseImpCast(S, E, T, CContext, + diag::warn_impcast_float_integer, PruneWarnings); + } + } + // Warn on evaluatable floating point expression to integer conversion. + DiagID = diag::warn_impcast_float_to_integer; + } // FIXME: Force the precision of the source value down so we don't print // digits which are usually useless (we don't really care here if we @@ -7407,14 +7466,22 @@ void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, Value.toString(PrettySourceValue, precision); SmallString<16> PrettyTargetValue; - if (T->isSpecificBuiltinType(BuiltinType::Bool)) + if (IsBool) PrettyTargetValue = Value.isZero() ? "false" : "true"; else IntegerValue.toString(PrettyTargetValue); - S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) - << FL->getType() << T.getUnqualifiedType() << PrettySourceValue - << PrettyTargetValue << FL->getSourceRange() << SourceRange(CContext); + if (PruneWarnings) { + S.DiagRuntimeBehavior(E->getExprLoc(), E, + S.PDiag(DiagID) + << E->getType() << T.getUnqualifiedType() + << PrettySourceValue << PrettyTargetValue + << E->getSourceRange() << SourceRange(CContext)); + } else { + S.Diag(E->getExprLoc(), DiagID) + << E->getType() << T.getUnqualifiedType() << PrettySourceValue + << PrettyTargetValue << E->getSourceRange() << SourceRange(CContext); + } } std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { @@ -7748,22 +7815,12 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; } - // If the target is integral, always warn. + // If the target is integral, always warn. if (TargetBT && TargetBT->isInteger()) { if (S.SourceMgr.isInSystemMacro(CC)) return; - - Expr *InnerE = E->IgnoreParenImpCasts(); - // We also want to warn on, e.g., "int i = -1.234" - if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(InnerE)) - if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus) - InnerE = UOp->getSubExpr()->IgnoreParenImpCasts(); - - if (FloatingLiteral *FL = dyn_cast<FloatingLiteral>(InnerE)) { - DiagnoseFloatingLiteralImpCast(S, FL, T, CC); - } else { - DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer); - } + + DiagnoseFloatingImpCast(S, E, T, CC); } // Detect the case where a call result is converted from floating-point to |