diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 958373ed94fe3..dd0b8e790d444 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -2827,10 +2827,10 @@ bool Compiler::VisitCompoundAssignOperator( return false; if (!this->emitLoad(*LT, E)) return false; - if (LT != LHSComputationT) { - if (!this->emitCast(*LT, *LHSComputationT, E)) - return false; - } + if (LT != LHSComputationT && + !this->emitIntegralCast(*LT, *LHSComputationT, E->getComputationLHSType(), + E)) + return false; // Get the RHS value on the stack. if (!this->emitGetLocal(*RT, TempOffset, E)) @@ -2883,10 +2883,9 @@ bool Compiler::VisitCompoundAssignOperator( } // And now cast from LHSComputationT to ResultT. - if (ResultT != LHSComputationT) { - if (!this->emitCast(*LHSComputationT, *ResultT, E)) - return false; - } + if (ResultT != LHSComputationT && + !this->emitIntegralCast(*LHSComputationT, *ResultT, E->getType(), E)) + return false; // And store the result in LHS. if (DiscardResult) { @@ -7243,6 +7242,19 @@ bool Compiler::emitPrimCast(PrimType FromT, PrimType ToT, return false; } +template +bool Compiler::emitIntegralCast(PrimType FromT, PrimType ToT, + QualType ToQT, const Expr *E) { + assert(FromT != ToT); + + if (ToT == PT_IntAP) + return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E); + if (ToT == PT_IntAPS) + return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E); + + return this->emitCast(FromT, ToT, E); +} + /// Emits __real(SubExpr) template bool Compiler::emitComplexReal(const Expr *SubExpr) { diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 6a9fe1e954530..54d39bbc25952 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -393,6 +393,8 @@ class Compiler : public ConstStmtVisitor, bool>, } bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E); + bool emitIntegralCast(PrimType FromT, PrimType ToT, QualType ToQT, + const Expr *E); PrimType classifyComplexElementType(QualType T) const { assert(T->isAnyComplexType()); diff --git a/clang/test/AST/ByteCode/intap.cpp b/clang/test/AST/ByteCode/intap.cpp index 05ab319bf16df..efb60cb0abffe 100644 --- a/clang/test/AST/ByteCode/intap.cpp +++ b/clang/test/AST/ByteCode/intap.cpp @@ -305,6 +305,46 @@ namespace UnderlyingInt128 { static_assert(foo() == 0, ""); // both-error {{not an integral constant expression}} \ // both-note {{in call to}} } + +namespace CompoundAssignOperators { + constexpr unsigned __int128 foo() { + long b = 10; + + b += (__int128)1; + b -= (__int128)1; + b *= (__int128)1; + b /= (__int128)1; + + b += (unsigned __int128)1; + b -= (unsigned __int128)1; + b *= (unsigned __int128)1; + b /= (unsigned __int128)1; + + __int128 i = 10; + i += (__int128)1; + i -= (__int128)1; + i *= (__int128)1; + i /= (__int128)1; + i += (unsigned __int128)1; + i -= (unsigned __int128)1; + i *= (unsigned __int128)1; + i /= (unsigned __int128)1; + + unsigned __int128 i2 = 10; + i2 += (__int128)1; + i2 -= (__int128)1; + i2 *= (__int128)1; + i2 /= (__int128)1; + i2 += (unsigned __int128)1; + i2 -= (unsigned __int128)1; + i2 *= (unsigned __int128)1; + i2 /= (unsigned __int128)1; + + return (int)b; + } + static_assert(foo() == 10); +} + #endif #endif