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,6 +13374,11 @@ } } +static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, + SourceLocation CC, + bool *ICContext = nullptr, + bool IsListInit = false); + /// Analyze the given compound assignment for the possible losing of /// floating-point precision. static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { @@ -13392,8 +13397,16 @@ ->getComputationResultType() ->getAs(); + // Check for implicit conversions for compound assignment statements with + // intergral operands. + 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 (!ResultBT || !RBT || !RBT->isFloatingPoint()) + return; // If source is floating point but target is an integer. if (ResultBT->isInteger()) @@ -13682,9 +13695,8 @@ } static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, - SourceLocation CC, - bool *ICContext = nullptr, - bool IsListInit = false) { + SourceLocation CC, bool *ICContext, + bool IsListInit) { if (E->isTypeDependent() || E->isValueDependent()) return; const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr(); 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,36 @@ 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}} +} + +void test6(char c) { + c <<= 999999; // expected-warning {{shift count >= width of type}} \ + // cxx17-warning {{shift count >= width of type}} \ + // ref-warning {{shift count >= width of type}} \ + // ref-cxx17-warning {{shift count >= width of type}} + c >>= 999999; // expected-warning {{shift count >= width of type}} \ + // cxx17-warning {{shift count >= width of type}} \ + // ref-warning {{shift count >= width of type}} \ + // ref-cxx17-warning {{shift count >= width of type}} +} diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -246,7 +246,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { const uint8_t *p = (uint8_t *)addr; const uint8_t *pend = (uint8_t *)end; - int64_t result = 0; + uint64_t result = 0; int bit = 0; uint8_t byte; do { @@ -260,7 +260,7 @@ if ((byte & 0x40) != 0 && bit < 64) result |= (-1ULL) << bit; addr = (pint_t) p; - return result; + return (int64_t)result; } inline LocalAddressSpace::pint_t