[clang] 4fbc95d - [clang][Interp] Skip union members in default initializers
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Wed May 22 08:57:24 PDT 2024
Author: Timm Bäder
Date: 2024-05-22T17:57:00+02:00
New Revision: 4fbc95d1360147e9c4aceeadd1bda17d68364b85
URL: https://github.com/llvm/llvm-project/commit/4fbc95d1360147e9c4aceeadd1bda17d68364b85
DIFF: https://github.com/llvm/llvm-project/commit/4fbc95d1360147e9c4aceeadd1bda17d68364b85.diff
LOG: [clang][Interp] Skip union members in default initializers
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/EvaluationResult.cpp
clang/test/AST/Interp/unions.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 859a3fabea32b..50c85bf7d35f5 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1061,6 +1061,10 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
R->getField(InitIndex)->Decl->isUnnamedBitField())
++InitIndex;
+ // Potentially skip ahead. This is especially relevant in unions.
+ if (const auto *D = dyn_cast<CXXDefaultInitExpr>(Init))
+ InitIndex = D->getField()->getFieldIndex();
+
if (!this->emitDupPtr(E))
return false;
diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp
index 79f222ce2b30c..150a793da881d 100644
--- a/clang/lib/AST/Interp/EvaluationResult.cpp
+++ b/clang/lib/AST/Interp/EvaluationResult.cpp
@@ -101,6 +101,10 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
Pointer FieldPtr = BasePtr.atField(F.Offset);
QualType FieldType = F.Decl->getType();
+ // Don't check inactive union members.
+ if (R->isUnion() && !FieldPtr.isActive())
+ continue;
+
if (FieldType->isRecordType()) {
Result &= CheckFieldsInitialized(S, Loc, FieldPtr, FieldPtr.getRecord());
} else if (FieldType->isIncompleteArrayType()) {
@@ -115,10 +119,6 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
DiagnoseUninitializedSubobject(S, Loc, F.Decl);
Result = false;
}
-
- // Only the first member of a union needs to be initialized.
- if (R->isUnion())
- break;
}
// Check Fields in all bases
diff --git a/clang/test/AST/Interp/unions.cpp b/clang/test/AST/Interp/unions.cpp
index 004e500de064f..46ba514b47b98 100644
--- a/clang/test/AST/Interp/unions.cpp
+++ b/clang/test/AST/Interp/unions.cpp
@@ -10,3 +10,11 @@ constexpr U a = {12};
static_assert(a.a == 12, "");
static_assert(a.b == 0, ""); // both-error {{not an integral constant expression}} \
// both-note {{read of member 'b' of union with active member 'a'}}
+union U1 {
+ int i;
+ float f = 3.0f;
+};
+constexpr U1 u1{};
+static_assert(u1.f == 3.0, "");
+static_assert(u1.i == 1, ""); // both-error {{not an integral constant expression}} \
+ // both-note {{read of member 'i' of union with active member 'f'}}
More information about the cfe-commits
mailing list