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'}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits