Skip to content

Commit 4fbc95d

Browse files
committed
[clang][Interp] Skip union members in default initializers
1 parent ac1dc05 commit 4fbc95d

File tree

3 files changed

+16
-4
lines changed

3 files changed

+16
-4
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,10 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
10611061
R->getField(InitIndex)->Decl->isUnnamedBitField())
10621062
++InitIndex;
10631063

1064+
// Potentially skip ahead. This is especially relevant in unions.
1065+
if (const auto *D = dyn_cast<CXXDefaultInitExpr>(Init))
1066+
InitIndex = D->getField()->getFieldIndex();
1067+
10641068
if (!this->emitDupPtr(E))
10651069
return false;
10661070

clang/lib/AST/Interp/EvaluationResult.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
101101
Pointer FieldPtr = BasePtr.atField(F.Offset);
102102
QualType FieldType = F.Decl->getType();
103103

104+
// Don't check inactive union members.
105+
if (R->isUnion() && !FieldPtr.isActive())
106+
continue;
107+
104108
if (FieldType->isRecordType()) {
105109
Result &= CheckFieldsInitialized(S, Loc, FieldPtr, FieldPtr.getRecord());
106110
} else if (FieldType->isIncompleteArrayType()) {
@@ -115,10 +119,6 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
115119
DiagnoseUninitializedSubobject(S, Loc, F.Decl);
116120
Result = false;
117121
}
118-
119-
// Only the first member of a union needs to be initialized.
120-
if (R->isUnion())
121-
break;
122122
}
123123

124124
// Check Fields in all bases

clang/test/AST/Interp/unions.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,11 @@ constexpr U a = {12};
1010
static_assert(a.a == 12, "");
1111
static_assert(a.b == 0, ""); // both-error {{not an integral constant expression}} \
1212
// both-note {{read of member 'b' of union with active member 'a'}}
13+
union U1 {
14+
int i;
15+
float f = 3.0f;
16+
};
17+
constexpr U1 u1{};
18+
static_assert(u1.f == 3.0, "");
19+
static_assert(u1.i == 1, ""); // both-error {{not an integral constant expression}} \
20+
// both-note {{read of member 'i' of union with active member 'f'}}

0 commit comments

Comments
 (0)