Skip to content
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ Bug Fixes in This Version
- Fixed a failed assertion with empty filename in ``#embed`` directive. (#GH162951)
- Fixed a crash triggered by unterminated ``__has_embed``. (#GH162953)
- Accept empty enumerations in MSVC-compatible C mode. (#GH114402)
- Fix a bug leading to incorrect code generation with complex number compound assignment and bitfield values, which also caused a crash with UBsan. (#GH166798)
- Fixed false-positive shadow diagnostics for lambdas in explicit object member functions. (#GH163731)

Bug Fixes to Compiler Builtins
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,7 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
else
OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc);
} else {
llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS, Loc);
llvm::Value *LHSVal = CGF.EmitLoadOfLValue(LHS, Loc).getScalarVal();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also need to change the call to EmitStoreOfScalar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it does make sense to replace it with EmitStoreThroughLValue, what do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems fine.

// For floating point real operands we can directly pass the scalar form
// to the binary operator emission and potentially get more efficient code.
if (LHSTy->isRealFloatingType()) {
Expand Down Expand Up @@ -1318,7 +1318,7 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
} else {
llvm::Value *ResVal =
CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy, Loc);
CGF.EmitStoreOfScalar(ResVal, LHS, /*isInit*/ false);
CGF.EmitStoreThroughLValue(RValue::get(ResVal), LHS, /*isInit*/ false);
Val = RValue::get(ResVal);
}

Expand Down
25 changes: 25 additions & 0 deletions clang/test/CodeGen/complex-compound-assign-bitfield.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -std=c23 -emit-llvm -o - | FileCheck %s

struct Bits {
int pad1: 30;
bool b: 1;
int pad2: 1;
};

int main(void) {
// CHECK-LABEL: define dso_local i32 @main() #0 {
struct Bits x;
x.b += __builtin_complex(-1.0f, 0.0f);
// CHECK: %bf.load = load i32, ptr %x, align 4
// CHECK-NEXT: %bf.lshr = lshr i32 %bf.load, 30
// CHECK-NEXT: %bf.clear = and i32 %bf.lshr, 1
// CHECK-NEXT: %bf.cast = trunc i32 %bf.clear to i1
// CHECK-NEXT: %conv = uitofp i1 %bf.cast to float

// CHECK: %0 = zext i1 %tobool1 to i32
// CHECK-NEXT: %bf.load2 = load i32, ptr %x, align 4
// CHECK-NEXT: %bf.shl = shl i32 %0, 30
// CHECK-NEXT: %bf.clear3 = and i32 %bf.load2, -1073741825
// CHECK-NEXT: %bf.set = or i32 %bf.clear3, %bf.shl
// CHECK-NEXT: store i32 %bf.set, ptr %x, align 4
}