Author: aaronballman Date: Tue Aug 27 05:42:45 2019 New Revision: 370052 URL: http://llvm.org/viewvc/llvm-project?rev=370052&view=rev Log: 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. Added: cfe/trunk/test/CodeGenCXX/ms-union-member-ref.cpp Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=370052&r1=370051&r2=370052&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Aug 27 05:42:45 2019 @@ -4056,7 +4056,6 @@ LValue CodeGenFunction::EmitLValueForFie unsigned RecordCVR = base.getVRQualifiers(); if (rec->isUnion()) { // For unions, there is no pointer adjustment. - assert(!FieldType->isReferenceType() && "union has reference member"); if (CGM.getCodeGenOpts().StrictVTablePointers && hasAnyVptr(FieldType, getContext())) // Because unions can easily skip invariant.barriers, we need to add @@ -4073,27 +4072,30 @@ LValue CodeGenFunction::EmitLValueForFie addr.getPointer(), getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), addr.getAlignment()); } - } else { + if (FieldType->isReferenceType()) + addr = Builder.CreateElementBitCast( + addr, CGM.getTypes().ConvertTypeForMem(FieldType), field->getName()); + } else { if (!IsInPreservedAIRegion) // For structs, we GEP to the field that the record layout suggests. addr = emitAddrOfFieldStorage(*this, addr, field); else // Remember the original struct field index addr = emitPreserveStructAccess(*this, addr, field); + } - // If this is a reference field, load the reference right now. - if (FieldType->isReferenceType()) { - LValue RefLVal = MakeAddrLValue(addr, FieldType, FieldBaseInfo, - FieldTBAAInfo); - if (RecordCVR & Qualifiers::Volatile) - RefLVal.getQuals().addVolatile(); - addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo); + // If this is a reference field, load the reference right now. + if (FieldType->isReferenceType()) { + LValue RefLVal = + MakeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo); + if (RecordCVR & Qualifiers::Volatile) + RefLVal.getQuals().addVolatile(); + addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo); - // Qualifiers on the struct don't apply to the referencee. - RecordCVR = 0; - FieldType = FieldType->getPointeeType(); - } + // Qualifiers on the struct don't apply to the referencee. + RecordCVR = 0; + FieldType = FieldType->getPointeeType(); } // Make sure that the address is pointing to the right type. This is critical Added: cfe/trunk/test/CodeGenCXX/ms-union-member-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ms-union-member-ref.cpp?rev=370052&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/ms-union-member-ref.cpp (added) +++ cfe/trunk/test/CodeGenCXX/ms-union-member-ref.cpp Tue Aug 27 05:42:45 2019 @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fms-extensions %s -emit-llvm -o- | FileCheck %s + +union A { + int *&ref; + int **ptr; +}; + +int *f1(A *a) { + return a->ref; +} +// CHECK-LABEL: define {{.*}}i32* @_Z2f1P1A(%union.A* %a) +// CHECK: [[REF:%[^[:space:]]+]] = bitcast %union.A* %{{.*}} to i32*** +// CHECK: [[IPP:%[^[:space:]]+]] = load i32**, i32*** [[REF]] +// CHECK: [[IP:%[^[:space:]]+]] = load i32*, i32** [[IPP]] +// CHECK: ret i32* [[IP]] + +void f2(A *a) { + *a->ref = 1; +} +// CHECK-LABEL: define {{.*}}void @_Z2f2P1A(%union.A* %a) +// CHECK: [[REF:%[^[:space:]]+]] = bitcast %union.A* %{{.*}} to i32*** +// CHECK: [[IPP:%[^[:space:]]+]] = load i32**, i32*** [[REF]] +// CHECK: [[IP:%[^[:space:]]+]] = load i32*, i32** [[IPP]] +// CHECK: store i32 1, i32* [[IP]] + +bool f3(A *a, int *b) { + return a->ref != b; +} +// CHECK-LABEL: define {{.*}}i1 @_Z2f3P1APi(%union.A* %a, i32* %b) +// CHECK: [[REF:%[^[:space:]]+]] = bitcast %union.A* %{{.*}} to i32*** +// CHECK: [[IPP:%[^[:space:]]+]] = load i32**, i32*** [[REF]] +// CHECK: [[IP:%[^[:space:]]+]] = load i32*, i32** [[IPP]] +// CHECK: [[IP2:%[^[:space:]]+]] = load i32*, i32** %b.addr +// CHECK: icmp ne i32* [[IP]], [[IP2]] _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits