================ @@ -14578,21 +14578,56 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr) { if (getLangOpts().CPlusPlus11 && isa<InitListExpr>(RHSExpr)) { - // The syntax only allows initializer lists on the RHS of assignment, - // so we don't need to worry about accepting invalid code for - // non-assignment operators. - // C++11 5.17p9: - // The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning - // of x = {} is x = T(). - InitializationKind Kind = InitializationKind::CreateDirectList( - RHSExpr->getBeginLoc(), RHSExpr->getBeginLoc(), RHSExpr->getEndLoc()); - InitializedEntity Entity = - InitializedEntity::InitializeTemporary(LHSExpr->getType()); - InitializationSequence InitSeq(*this, Entity, Kind, RHSExpr); - ExprResult Init = InitSeq.Perform(*this, Entity, Kind, RHSExpr); - if (Init.isInvalid()) - return Init; - RHSExpr = Init.get(); + // C++11 [expr.ass]p9, per CWG2768: + // A braced-init-list B may appear on the right-hand side of + // - an assignment to a scalar of type T, in which case the initializer + // list shall have at most a single element. The meaning of x = B is + // x = t, where t is an invented temporary variable declared and + // initialized as T t = B. + switch (Opc) { + case BO_Assign: { + QualType LHSTy = LHSExpr->getType(); + assert(!LHSTy->isDependentType() && + "Should not have tried to create a builtin binary operator"); + if (LHSTy->isScalarType()) { + InitializationKind Kind = + InitializationKind::CreateCopy(RHSExpr->getBeginLoc(), OpLoc); + InitializedEntity Entity = + InitializedEntity::InitializeTemporary(LHSExpr->getType()); + InitializationSequence InitSeq(*this, Entity, Kind, RHSExpr); + ExprResult InventedTemporary = + InitSeq.Perform(*this, Entity, Kind, RHSExpr); + if (InventedTemporary.isInvalid()) + return InventedTemporary; + assert(cast<InitListExpr>(RHSExpr)->getNumInits() <= 1 && + "The initialization should have failed"); + RHSExpr = InventedTemporary.get(); + } + break; + } + case BO_MulAssign: + case BO_DivAssign: + case BO_RemAssign: + case BO_AddAssign: + case BO_SubAssign: + case BO_ShlAssign: + case BO_ShrAssign: + case BO_AndAssign: + case BO_XorAssign: + case BO_OrAssign: { + // A compound assignment like `i += {0}` is equivalent to `i = i + {0}`, + // which is a parsing error + StringRef Op = BinaryOperator::getOpcodeStr(Opc); + [[maybe_unused]] bool AssignmentStripped = Op.consume_back("="); ---------------- cor3ntin wrote:
We have `getOpForCompoundAssignment`, I think using that would be cleaner that doing string manipulations https://github.com/llvm/llvm-project/pull/100548 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits