diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -13374,44 +13374,6 @@ } } -/// 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()); - - if (E->getLHS()->getType()->isAtomicType()) - S.Diag(E->getOperatorLoc(), diag::warn_atomic_implicit_seq_cst); - - // 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 an integer. - if (ResultBT->isInteger()) - return DiagnoseImpCast(S, E, E->getRHS()->getType(), E->getLHS()->getType(), - E->getExprLoc(), diag::warn_impcast_float_integer); - - if (!ResultBT->isFloatingPoint()) - return; - - // If both source and target are floating points, warn about losing precision. - int Order = S.getASTContext().getFloatingTypeSemanticOrder( - QualType(ResultBT, 0), QualType(RBT, 0)); - if (Order < 0 && !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"; @@ -14150,6 +14112,49 @@ } } +/// 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()); + + if (E->getLHS()->getType()->isAtomicType()) + S.Diag(E->getOperatorLoc(), diag::warn_atomic_implicit_seq_cst); + + // Now check the outermost expression + const auto *ResultBT = E->getLHS()->getType()->getAs(); + const auto *RBT = cast(E) + ->getComputationResultType() + ->getAs(); + + // Check for implicit conversion loss of precision form 64-to-32 for compound + // statements. + if (E->getLHS()->getType()->isIntegerType() && E->getRHS()->getType()->isIntegerType() && !E->isShiftAssignOp()) + CheckImplicitConversion(S, E->getRHS(), E->getType(), E->getRHS()->getExprLoc()); + + // The below checks assume source is floating point. + if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return; + + // If source is floating point but target is an integer. + if (ResultBT->isInteger()) + return DiagnoseImpCast(S, E, E->getRHS()->getType(), E->getLHS()->getType(), + E->getExprLoc(), diag::warn_impcast_float_integer); + + if (!ResultBT->isFloatingPoint()) + return; + + // If both source and target are floating points, warn about losing precision. + int Order = S.getASTContext().getFloatingTypeSemanticOrder( + QualType(ResultBT, 0), QualType(RBT, 0)); + if (Order < 0 && !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 void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E, SourceLocation CC, QualType T); diff --git a/clang/test/Sema/conversion-64-32.c b/clang/test/Sema/conversion-64-32.c --- a/clang/test/Sema/conversion-64-32.c +++ b/clang/test/Sema/conversion-64-32.c @@ -17,3 +17,25 @@ int test2(long v) { return v / 2; // expected-warning {{implicit conversion loses integer precision: 'long' to 'int'}} } + +// rdar://10466193 +void test3(int i, long long ll) { + i += ll; // expected-warning {{implicit conversion loses integer precision}} + i -= ll; // expected-warning {{implicit conversion loses integer precision}} + i *= ll; // expected-warning {{implicit conversion loses integer precision}} + i /= ll; // expected-warning {{implicit conversion loses integer precision}} +} + +void test4(int i, long long ll) { + i += i-ll; // expected-warning {{implicit conversion loses integer precision}} + i += i+ll; // expected-warning {{implicit conversion loses integer precision}} + i -= i-ll; // expected-warning {{implicit conversion loses integer precision}} + i -= i+ll; // expected-warning {{implicit conversion loses integer precision}} +} + +void test5(int i, int j, long long ll) { + i += (i-j)*ll; // expected-warning {{implicit conversion loses integer precision}} + i += (i+j)*ll; // expected-warning {{implicit conversion loses integer precision}} + i -= ll/(i-j); // expected-warning {{implicit conversion loses integer precision}} + i -= ll/(i-j); // expected-warning {{implicit conversion loses integer precision}} +}