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
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index b1e6b99..0592a83 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -7382,19 +7382,78 @@
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 @@
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 @@
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