-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[CIR] Add support for compound assignment statements #137740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) ChangesCompound assignment in C++ goes through a different path than the binary assignment operators that were already handled for C. This change adds the necessary handler to get this working with C++. Full diff: https://github.com/llvm/llvm-project/pull/137740.diff 4 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 4ca54940a60b8..aef5b125a2877 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1010,6 +1010,55 @@ mlir::Value ScalarExprEmitter::emitCompoundAssign(
} // namespace
+LValue
+CIRGenFunction::emitCompoundAssignmentLValue(const CompoundAssignOperator *e) {
+ ScalarExprEmitter emitter(*this, builder);
+ mlir::Value result;
+ switch (e->getOpcode()) {
+#define COMPOUND_OP(Op) \
+ case BO_##Op##Assign: \
+ return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
+ result)
+ COMPOUND_OP(Mul);
+ COMPOUND_OP(Div);
+ COMPOUND_OP(Rem);
+ COMPOUND_OP(Add);
+ COMPOUND_OP(Sub);
+ COMPOUND_OP(Shl);
+ COMPOUND_OP(Shr);
+ COMPOUND_OP(And);
+ COMPOUND_OP(Xor);
+ COMPOUND_OP(Or);
+#undef COMPOUND_OP
+
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_Cmp:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ case BO_LAnd:
+ case BO_LOr:
+ case BO_Assign:
+ case BO_Comma:
+ llvm_unreachable("Not valid compound assignment operators");
+ }
+ llvm_unreachable("Unhandled compound assignment operator");
+}
+
/// Emit the computation of the specified expression of scalar type.
mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e) {
assert(e && hasScalarEvaluationKind(e->getType()) &&
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 5412f9f602711..fa86fce2f6e5c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -517,6 +517,19 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
return emitMemberExpr(cast<MemberExpr>(e));
case Expr::BinaryOperatorClass:
return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
+ case Expr::CompoundAssignOperatorClass: {
+ QualType ty = e->getType();
+ if (const AtomicType *at = ty->getAs<AtomicType>()) {
+ cgm.errorNYI(e->getSourceRange(),
+ "CompoundAssignOperator with AtomicType");
+ return LValue();
+ }
+ if (!ty->isAnyComplexType())
+ return emitCompoundAssignmentLValue(cast<CompoundAssignOperator>(e));
+ cgm.errorNYI(e->getSourceRange(),
+ "CompoundAssignOperator with ComplexType");
+ return LValue();
+ }
case Expr::ParenExprClass:
return emitLValue(cast<ParenExpr>(e)->getSubExpr());
case Expr::DeclRefExprClass:
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 74fcd081dec18..26dc9c433db7d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -469,6 +469,8 @@ class CIRGenFunction : public CIRGenTypeCache {
ReturnValueSlot returnValue = ReturnValueSlot());
CIRGenCallee emitCallee(const clang::Expr *e);
+ LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e);
+
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
diff --git a/clang/test/CIR/CodeGen/compound_assign.cpp b/clang/test/CIR/CodeGen/compound_assign.cpp
new file mode 100644
index 0000000000000..c54eb9e626016
--- /dev/null
+++ b/clang/test/CIR/CodeGen/compound_assign.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+int compound_assign(int b) {
+ int x = 1;
+ x *= b;
+ x /= b;
+ x %= b;
+ x += b;
+ x -= b;
+ x >>= b;
+ x <<= b;
+ x &= b;
+ x ^= b;
+ x |= b;
+ return x;
+}
+
+// CIR: cir.func @_Z15compound_assigni
+// CIR: %[[MUL:.*]] = cir.binop(mul, %{{.*}}, %{{.*}}) nsw : !s32i
+// CIR: cir.store %[[MUL]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[DIV:.*]] = cir.binop(div, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[DIV]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[REM:.*]] = cir.binop(rem, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[REM]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[ADD:.*]] = cir.binop(add, %{{.*}}, %{{.*}}) nsw : !s32i
+// CIR: cir.store %[[ADD]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[SUB:.*]] = cir.binop(sub, %{{.*}}, %{{.*}}) nsw : !s32i
+// CIR: cir.store %[[SUB]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[SHR:.*]] = cir.shift(right, %{{.*}} : !s32i, %{{.*}} : !s32i) -> !s32i
+// CIR: cir.store %[[SHR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[SHL:.*]] = cir.shift(left, %{{.*}} : !s32i, %{{.*}} : !s32i) -> !s32i
+// CIR: cir.store %[[SHL]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[AND:.*]] = cir.binop(and, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[AND]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[XOR:.*]] = cir.binop(xor, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[XOR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[OR:.*]] = cir.binop(or, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[OR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+
+// LLVM: define {{.*}}i32 @_Z15compound_assigni
+// LLVM: %[[MUL:.*]] = mul nsw i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[MUL]], ptr %{{.*}}
+// LLVM: %[[DIV:.*]] = sdiv i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[DIV]], ptr %{{.*}}
+// LLVM: %[[REM:.*]] = srem i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[REM]], ptr %{{.*}}
+// LLVM: %[[ADD:.*]] = add nsw i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[ADD]], ptr %{{.*}}
+// LLVM: %[[SUB:.*]] = sub nsw i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[SUB]], ptr %{{.*}}
+// LLVM: %[[SHR:.*]] = ashr i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[SHR]], ptr %{{.*}}
+// LLVM: %[[SHL:.*]] = shl i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[SHL]], ptr %{{.*}}
+// LLVM: %[[AND:.*]] = and i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[AND]], ptr %{{.*}}
+// LLVM: %[[XOR:.*]] = xor i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[XOR]], ptr %{{.*}}
+// LLVM: %[[OR:.*]] = or i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[OR]], ptr %{{.*}}
+
+// OGCG: define {{.*}}i32 @_Z15compound_assigni
+// OGCG: %[[MUL:.*]] = mul nsw i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[MUL]], ptr %{{.*}}
+// OGCG: %[[DIV:.*]] = sdiv i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[DIV]], ptr %{{.*}}
+// OGCG: %[[REM:.*]] = srem i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[REM]], ptr %{{.*}}
+// OGCG: %[[ADD:.*]] = add nsw i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[ADD]], ptr %{{.*}}
+// OGCG: %[[SUB:.*]] = sub nsw i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[SUB]], ptr %{{.*}}
+// OGCG: %[[SHR:.*]] = ashr i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[SHR]], ptr %{{.*}}
+// OGCG: %[[SHL:.*]] = shl i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[SHL]], ptr %{{.*}}
+// OGCG: %[[AND:.*]] = and i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[AND]], ptr %{{.*}}
+// OGCG: %[[XOR:.*]] = xor i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[XOR]], ptr %{{.*}}
+// OGCG: %[[OR:.*]] = or i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[OR]], ptr %{{.*}}
|
@llvm/pr-subscribers-clangir Author: Andy Kaylor (andykaylor) ChangesCompound assignment in C++ goes through a different path than the binary assignment operators that were already handled for C. This change adds the necessary handler to get this working with C++. Full diff: https://github.com/llvm/llvm-project/pull/137740.diff 4 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 4ca54940a60b8..aef5b125a2877 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1010,6 +1010,55 @@ mlir::Value ScalarExprEmitter::emitCompoundAssign(
} // namespace
+LValue
+CIRGenFunction::emitCompoundAssignmentLValue(const CompoundAssignOperator *e) {
+ ScalarExprEmitter emitter(*this, builder);
+ mlir::Value result;
+ switch (e->getOpcode()) {
+#define COMPOUND_OP(Op) \
+ case BO_##Op##Assign: \
+ return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
+ result)
+ COMPOUND_OP(Mul);
+ COMPOUND_OP(Div);
+ COMPOUND_OP(Rem);
+ COMPOUND_OP(Add);
+ COMPOUND_OP(Sub);
+ COMPOUND_OP(Shl);
+ COMPOUND_OP(Shr);
+ COMPOUND_OP(And);
+ COMPOUND_OP(Xor);
+ COMPOUND_OP(Or);
+#undef COMPOUND_OP
+
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_Cmp:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ case BO_LAnd:
+ case BO_LOr:
+ case BO_Assign:
+ case BO_Comma:
+ llvm_unreachable("Not valid compound assignment operators");
+ }
+ llvm_unreachable("Unhandled compound assignment operator");
+}
+
/// Emit the computation of the specified expression of scalar type.
mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e) {
assert(e && hasScalarEvaluationKind(e->getType()) &&
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 5412f9f602711..fa86fce2f6e5c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -517,6 +517,19 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
return emitMemberExpr(cast<MemberExpr>(e));
case Expr::BinaryOperatorClass:
return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
+ case Expr::CompoundAssignOperatorClass: {
+ QualType ty = e->getType();
+ if (const AtomicType *at = ty->getAs<AtomicType>()) {
+ cgm.errorNYI(e->getSourceRange(),
+ "CompoundAssignOperator with AtomicType");
+ return LValue();
+ }
+ if (!ty->isAnyComplexType())
+ return emitCompoundAssignmentLValue(cast<CompoundAssignOperator>(e));
+ cgm.errorNYI(e->getSourceRange(),
+ "CompoundAssignOperator with ComplexType");
+ return LValue();
+ }
case Expr::ParenExprClass:
return emitLValue(cast<ParenExpr>(e)->getSubExpr());
case Expr::DeclRefExprClass:
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 74fcd081dec18..26dc9c433db7d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -469,6 +469,8 @@ class CIRGenFunction : public CIRGenTypeCache {
ReturnValueSlot returnValue = ReturnValueSlot());
CIRGenCallee emitCallee(const clang::Expr *e);
+ LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e);
+
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
diff --git a/clang/test/CIR/CodeGen/compound_assign.cpp b/clang/test/CIR/CodeGen/compound_assign.cpp
new file mode 100644
index 0000000000000..c54eb9e626016
--- /dev/null
+++ b/clang/test/CIR/CodeGen/compound_assign.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+int compound_assign(int b) {
+ int x = 1;
+ x *= b;
+ x /= b;
+ x %= b;
+ x += b;
+ x -= b;
+ x >>= b;
+ x <<= b;
+ x &= b;
+ x ^= b;
+ x |= b;
+ return x;
+}
+
+// CIR: cir.func @_Z15compound_assigni
+// CIR: %[[MUL:.*]] = cir.binop(mul, %{{.*}}, %{{.*}}) nsw : !s32i
+// CIR: cir.store %[[MUL]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[DIV:.*]] = cir.binop(div, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[DIV]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[REM:.*]] = cir.binop(rem, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[REM]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[ADD:.*]] = cir.binop(add, %{{.*}}, %{{.*}}) nsw : !s32i
+// CIR: cir.store %[[ADD]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[SUB:.*]] = cir.binop(sub, %{{.*}}, %{{.*}}) nsw : !s32i
+// CIR: cir.store %[[SUB]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[SHR:.*]] = cir.shift(right, %{{.*}} : !s32i, %{{.*}} : !s32i) -> !s32i
+// CIR: cir.store %[[SHR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[SHL:.*]] = cir.shift(left, %{{.*}} : !s32i, %{{.*}} : !s32i) -> !s32i
+// CIR: cir.store %[[SHL]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[AND:.*]] = cir.binop(and, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[AND]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[XOR:.*]] = cir.binop(xor, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[XOR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[OR:.*]] = cir.binop(or, %{{.*}}, %{{.*}}) : !s32i
+// CIR: cir.store %[[OR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+
+// LLVM: define {{.*}}i32 @_Z15compound_assigni
+// LLVM: %[[MUL:.*]] = mul nsw i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[MUL]], ptr %{{.*}}
+// LLVM: %[[DIV:.*]] = sdiv i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[DIV]], ptr %{{.*}}
+// LLVM: %[[REM:.*]] = srem i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[REM]], ptr %{{.*}}
+// LLVM: %[[ADD:.*]] = add nsw i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[ADD]], ptr %{{.*}}
+// LLVM: %[[SUB:.*]] = sub nsw i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[SUB]], ptr %{{.*}}
+// LLVM: %[[SHR:.*]] = ashr i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[SHR]], ptr %{{.*}}
+// LLVM: %[[SHL:.*]] = shl i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[SHL]], ptr %{{.*}}
+// LLVM: %[[AND:.*]] = and i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[AND]], ptr %{{.*}}
+// LLVM: %[[XOR:.*]] = xor i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[XOR]], ptr %{{.*}}
+// LLVM: %[[OR:.*]] = or i32 %{{.*}}, %{{.*}}
+// LLVM: store i32 %[[OR]], ptr %{{.*}}
+
+// OGCG: define {{.*}}i32 @_Z15compound_assigni
+// OGCG: %[[MUL:.*]] = mul nsw i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[MUL]], ptr %{{.*}}
+// OGCG: %[[DIV:.*]] = sdiv i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[DIV]], ptr %{{.*}}
+// OGCG: %[[REM:.*]] = srem i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[REM]], ptr %{{.*}}
+// OGCG: %[[ADD:.*]] = add nsw i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[ADD]], ptr %{{.*}}
+// OGCG: %[[SUB:.*]] = sub nsw i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[SUB]], ptr %{{.*}}
+// OGCG: %[[SHR:.*]] = ashr i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[SHR]], ptr %{{.*}}
+// OGCG: %[[SHL:.*]] = shl i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[SHL]], ptr %{{.*}}
+// OGCG: %[[AND:.*]] = and i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[AND]], ptr %{{.*}}
+// OGCG: %[[XOR:.*]] = xor i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[XOR]], ptr %{{.*}}
+// OGCG: %[[OR:.*]] = or i32 %{{.*}}, %{{.*}}
+// OGCG: store i32 %[[OR]], ptr %{{.*}}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonable.
Compound assignment in C++ goes through a different path than the binary assignment operators that were already handled for C. This change adds the necessary handler to get this working with C++.
f7c3b27
to
17ac341
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/205/builds/7835 Here is the relevant piece of the build log for the reference
|
Compound assignment in C++ goes through a different path than the binary assignment operators that were already handled for C. This change adds the necessary handler to get this working with C++.
Compound assignment in C++ goes through a different path than the binary assignment operators that were already handled for C. This change adds the necessary handler to get this working with C++.
Compound assignment in C++ goes through a different path than the binary assignment operators that were already handled for C. This change adds the necessary handler to get this working with C++.
Compound assignment in C++ goes through a different path than the binary assignment operators that were already handled for C. This change adds the necessary handler to get this working with C++.
Compound assignment in C++ goes through a different path than the binary assignment operators that were already handled for C. This change adds the necessary handler to get this working with C++.
Compound assignment in C++ goes through a different path than the binary assignment operators that were already handled for C. This change adds the necessary handler to get this working with C++.