Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -525,10 +525,13 @@ const CompoundAssignOperator *E) { const Expr *LHS = E->getLHS(); const Expr *RHS = E->getRHS(); - std::optional LT = classify(E->getLHS()->getType()); - std::optional RT = classify(E->getRHS()->getType()); + std::optional LHSComputationT = + classify(E->getComputationLHSType()); + std::optional LT = classify(LHS->getType()); + std::optional RT = classify(E->getComputationResultType()); + std::optional ResultT = classify(E->getType()); - if (!LT || !RT) + if (!LT || !RT || !ResultT || !LHSComputationT) return false; assert(!E->getType()->isPointerType() && @@ -539,29 +542,36 @@ return false; if (!this->emitLoad(*LT, E)) return false; + // If necessary, cast LHS to its computation type. + if (*LT != *LHSComputationT) { + if (!this->emitCast(*LT, *LHSComputationT, E)) + return false; + } + if (!visit(RHS)) return false; // Perform operation. switch (E->getOpcode()) { case BO_AddAssign: - if (!this->emitAdd(*LT, E)) + if (!this->emitAdd(*LHSComputationT, E)) return false; break; case BO_SubAssign: - if (!this->emitSub(*LT, E)) + if (!this->emitSub(*LHSComputationT, E)) return false; break; case BO_MulAssign: case BO_DivAssign: case BO_RemAssign: + case BO_ShlAssign: - if (!this->emitShl(*LT, *RT, E)) + if (!this->emitShl(*LHSComputationT, *RT, E)) return false; break; case BO_ShrAssign: - if (!this->emitShr(*LT, *RT, E)) + if (!this->emitShr(*LHSComputationT, *RT, E)) return false; break; case BO_AndAssign: @@ -571,10 +581,16 @@ llvm_unreachable("Unimplemented compound assign operator"); } + // And now cast from LHSComputationT to ResultT. + if (*ResultT != *LHSComputationT) { + if (!this->emitCast(*LHSComputationT, *ResultT, E)) + return false; + } + // And store the result in LHS. if (DiscardResult) - return this->emitStorePop(*LT, E); - return this->emitStore(*LT, E); + return this->emitStorePop(*ResultT, E); + return this->emitStore(*ResultT, E); } template bool ByteCodeExprGen::discard(const Expr *E) {