From 97b6875b657e10e3f43e3901a1b160ff4ab5a433 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Sat, 30 May 2015 09:12:07 +0000 Subject: [PATCH] [CodeGen] Indirect fields can initialize a union The first named data member is the field used to default initialize the union. An IndirectFieldDecl can introduce the first named data member of a union. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@238649 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExprConstant.cpp | 10 ++++++++-- lib/CodeGen/CGRecordLayoutBuilder.cpp | 10 +++++++--- test/CodeGenCXX/pointers-to-data-members.cpp | 10 ++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 73ca0cc1c3..b90b3ab61d 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -1349,8 +1349,14 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM, } // For unions, stop after the first named field. - if (record->isUnion() && Field->getDeclName()) - break; + if (record->isUnion()) { + if (Field->getIdentifier()) + break; + if (const auto *FieldRD = + dyn_cast_or_null(Field->getType()->getAsTagDecl())) + if (FieldRD->findFirstNamedDataMember()) + break; + } } // Fill in the virtual bases, if we're working with the complete object. diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 72ecd65c28..c89d5cc389 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -314,9 +314,13 @@ void CGRecordLowering::lowerUnion() { // If this is the case, then we aught not to try and come up with a "better" // type, it might not be very easy to come up with a Constant which // correctly initializes it. - if (!SeenNamedMember && Field->getDeclName()) { - SeenNamedMember = true; - if (!isZeroInitializable(Field)) { + if (!SeenNamedMember) { + SeenNamedMember = Field->getIdentifier(); + if (!SeenNamedMember) + if (const auto *FieldRD = + dyn_cast_or_null(Field->getType()->getAsTagDecl())) + SeenNamedMember = FieldRD->findFirstNamedDataMember(); + if (SeenNamedMember && !isZeroInitializable(Field)) { IsZeroInitializable = IsZeroInitializableAsBase = false; StorageType = FieldType; } diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp index 0f2ddaac23..94337d98a1 100644 --- a/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -285,4 +285,14 @@ S s; // CHECK-GLOBAL: @_ZN19FlexibleArrayMember1sE = global %"struct.FlexibleArrayMember::S" zeroinitializer, align 8 } +namespace IndirectPDM { +union U { + union { + int U::*m; + }; +}; +U u; +// CHECK-GLOBAL: @_ZN11IndirectPDM1uE = global %"union.IndirectPDM::U" { %union.anon { i64 -1 } }, align 8 +} + // CHECK-O3: attributes [[NUW]] = { nounwind readnone{{.*}} } -- 2.40.0