Skip to content

Commit 0299dbd

Browse files
committed
Implement codegen for MSVC unions with reference members.
Currently, clang accepts a union with a reference member when given the -fms-extensions flag. This change fixes the codegen for this case. Patch by Dominic Ferreira. llvm-svn: 370052
1 parent d0698b6 commit 0299dbd

File tree

2 files changed

+50
-14
lines changed

2 files changed

+50
-14
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4056,7 +4056,6 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
40564056
unsigned RecordCVR = base.getVRQualifiers();
40574057
if (rec->isUnion()) {
40584058
// For unions, there is no pointer adjustment.
4059-
assert(!FieldType->isReferenceType() && "union has reference member");
40604059
if (CGM.getCodeGenOpts().StrictVTablePointers &&
40614060
hasAnyVptr(FieldType, getContext()))
40624061
// Because unions can easily skip invariant.barriers, we need to add
@@ -4073,27 +4072,30 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
40734072
addr.getPointer(), getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo),
40744073
addr.getAlignment());
40754074
}
4076-
} else {
40774075

4076+
if (FieldType->isReferenceType())
4077+
addr = Builder.CreateElementBitCast(
4078+
addr, CGM.getTypes().ConvertTypeForMem(FieldType), field->getName());
4079+
} else {
40784080
if (!IsInPreservedAIRegion)
40794081
// For structs, we GEP to the field that the record layout suggests.
40804082
addr = emitAddrOfFieldStorage(*this, addr, field);
40814083
else
40824084
// Remember the original struct field index
40834085
addr = emitPreserveStructAccess(*this, addr, field);
4086+
}
40844087

4085-
// If this is a reference field, load the reference right now.
4086-
if (FieldType->isReferenceType()) {
4087-
LValue RefLVal = MakeAddrLValue(addr, FieldType, FieldBaseInfo,
4088-
FieldTBAAInfo);
4089-
if (RecordCVR & Qualifiers::Volatile)
4090-
RefLVal.getQuals().addVolatile();
4091-
addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo);
4092-
4093-
// Qualifiers on the struct don't apply to the referencee.
4094-
RecordCVR = 0;
4095-
FieldType = FieldType->getPointeeType();
4096-
}
4088+
// If this is a reference field, load the reference right now.
4089+
if (FieldType->isReferenceType()) {
4090+
LValue RefLVal =
4091+
MakeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo);
4092+
if (RecordCVR & Qualifiers::Volatile)
4093+
RefLVal.getQuals().addVolatile();
4094+
addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo);
4095+
4096+
// Qualifiers on the struct don't apply to the referencee.
4097+
RecordCVR = 0;
4098+
FieldType = FieldType->getPointeeType();
40974099
}
40984100

40994101
// Make sure that the address is pointing to the right type. This is critical
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %clang_cc1 -fms-extensions %s -emit-llvm -o- | FileCheck %s
2+
3+
union A {
4+
int *&ref;
5+
int **ptr;
6+
};
7+
8+
int *f1(A *a) {
9+
return a->ref;
10+
}
11+
// CHECK-LABEL: define {{.*}}i32* @_Z2f1P1A(%union.A* %a)
12+
// CHECK: [[REF:%[^[:space:]]+]] = bitcast %union.A* %{{.*}} to i32***
13+
// CHECK: [[IPP:%[^[:space:]]+]] = load i32**, i32*** [[REF]]
14+
// CHECK: [[IP:%[^[:space:]]+]] = load i32*, i32** [[IPP]]
15+
// CHECK: ret i32* [[IP]]
16+
17+
void f2(A *a) {
18+
*a->ref = 1;
19+
}
20+
// CHECK-LABEL: define {{.*}}void @_Z2f2P1A(%union.A* %a)
21+
// CHECK: [[REF:%[^[:space:]]+]] = bitcast %union.A* %{{.*}} to i32***
22+
// CHECK: [[IPP:%[^[:space:]]+]] = load i32**, i32*** [[REF]]
23+
// CHECK: [[IP:%[^[:space:]]+]] = load i32*, i32** [[IPP]]
24+
// CHECK: store i32 1, i32* [[IP]]
25+
26+
bool f3(A *a, int *b) {
27+
return a->ref != b;
28+
}
29+
// CHECK-LABEL: define {{.*}}i1 @_Z2f3P1APi(%union.A* %a, i32* %b)
30+
// CHECK: [[REF:%[^[:space:]]+]] = bitcast %union.A* %{{.*}} to i32***
31+
// CHECK: [[IPP:%[^[:space:]]+]] = load i32**, i32*** [[REF]]
32+
// CHECK: [[IP:%[^[:space:]]+]] = load i32*, i32** [[IPP]]
33+
// CHECK: [[IP2:%[^[:space:]]+]] = load i32*, i32** %b.addr
34+
// CHECK: icmp ne i32* [[IP]], [[IP2]]

0 commit comments

Comments
 (0)