Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -10292,33 +10292,6 @@ DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow); } -/// Analyze the given compound assignment for the possible losing of -/// floating-point precision. -static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { - assert(isa(E) && - "Must be compound assignment operation"); - // Recurse on the LHS and RHS in here - AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); - AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); - - // Now check the outermost expression - const auto *ResultBT = E->getLHS()->getType()->getAs(); - const auto *RBT = cast(E) - ->getComputationResultType() - ->getAs(); - - // If both source and target are floating points. - if (ResultBT && ResultBT->isFloatingPoint() && RBT && RBT->isFloatingPoint()) - // Builtin FP kinds are ordered by increasing FP rank. - if (ResultBT->getKind() < RBT->getKind()) - // We don't want to warn for system macro. - if (!S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) - // warn about dropping FP rank. - DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), - E->getOperatorLoc(), - diag::warn_impcast_float_result_precision); -} - /// Diagnose an implicit cast from a floating point value to an integer value. static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext) { @@ -10421,6 +10394,39 @@ } } +/// Analyze the given compound assignment for the possible losing of +/// floating-point precision. +static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { + assert(isa(E) && + "Must be compound assignment operation"); + // Recurse on the LHS and RHS in here + AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); + AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); + + // Now check the outermost expression + const auto *ResultBT = E->getLHS()->getType()->getAs(); + const auto *RBT = cast(E) + ->getComputationResultType() + ->getAs(); + + // The below checks assume source is floating point. + if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return; + + // If source is floating point but target is not. + if (!ResultBT->isFloatingPoint()) + return DiagnoseFloatingImpCast(S, E, E->getRHS()->getType(), + E->getExprLoc()); + + // If both source and target are floating points. + // Builtin FP kinds are ordered by increasing FP rank. + if (ResultBT->getKind() < RBT->getKind() && + // We don't want to warn for system macro. + !S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) + // warn about dropping FP rank. + DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), E->getOperatorLoc(), + diag::warn_impcast_float_result_precision); +} + static std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { if (!Range.Width) return "0"; Index: test/SemaCXX/warn-float-conversion.cpp =================================================================== --- test/SemaCXX/warn-float-conversion.cpp +++ test/SemaCXX/warn-float-conversion.cpp @@ -41,6 +41,32 @@ l = ld; //expected-warning{{conversion}} } +void CompoundAssignment() { + int x = 3; + + x += 1.234; //expected-warning{{conversion}} + x -= -0.0; //expected-warning{{conversion}} + x *= 1.1f; //expected-warning{{conversion}} + x /= -2.2f; //expected-warning{{conversion}} + + int y = x += 1.4f; //expected-warning{{conversion}} + + float z = 1.1f; + double w = -2.2; + + y += z + w; //expected-warning{{conversion}} +} + +# 1 "foo.h" 3 +// ^ the following text comes from a system header file. +#define SYSTEM_MACRO_FLOAT(x) do { (x) += 1.1; } while(0) +# 1 "warn-float-conversion.cpp" 1 +// ^ start of a new file. +void SystemMacro() { + float x = 0.0f; + SYSTEM_MACRO_FLOAT(x); +} + void Test() { int a1 = 10.0/2.0; //expected-warning{{conversion}} int a2 = 1.0/2.0; //expected-warning{{conversion}}