llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> Zero-initializing all of them accidentally left the last member active. Only initialize the first one. --- Full diff: https://github.com/llvm/llvm-project/pull/102744.diff 3 Files Affected: - (modified) clang/lib/AST/Interp/Compiler.cpp (+8-13) - (modified) clang/test/AST/Interp/records.cpp (+3-5) - (modified) clang/test/AST/Interp/unions.cpp (+45) ``````````diff diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp index d0e4d409b6580..6c4d607706c6b 100644 --- a/clang/lib/AST/Interp/Compiler.cpp +++ b/clang/lib/AST/Interp/Compiler.cpp @@ -1386,18 +1386,8 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, if (R->isUnion()) { if (Inits.size() == 0) { - // Zero-initialize the first union field. - if (R->getNumFields() == 0) - return this->emitFinishInit(E); - const Record::Field *FieldToInit = R->getField(0u); - QualType FieldType = FieldToInit->Desc->getType(); - if (std::optional<PrimType> T = classify(FieldType)) { - if (!this->visitZeroInitializer(*T, FieldType, E)) - return false; - if (!this->emitInitField(*T, FieldToInit->Offset, E)) - return false; - } - // FIXME: Non-primitive case? + if (!this->visitZeroRecordInitializer(R, E)) + return false; } else { const Expr *Init = Inits[0]; const FieldDecl *FToInit = nullptr; @@ -3374,6 +3364,8 @@ bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R, return false; if (!this->emitInitField(T, Field.Offset, E)) return false; + if (R->isUnion()) + break; continue; } @@ -3409,8 +3401,11 @@ bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R, assert(false); } - if (!this->emitPopPtr(E)) + if (!this->emitFinishInitPop(E)) return false; + + if (R->isUnion()) + break; } for (const Record::Base &B : R->bases()) { diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 9c8c1c344e1e8..343665003c23e 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -964,8 +964,6 @@ namespace TemporaryObjectExpr { static_assert(foo(F()) == 0, ""); } - /// FIXME: This needs support for unions on the new interpreter. - /// We diagnose an uninitialized object in c++14. #if __cplusplus > 201402L namespace Unions { struct F { @@ -978,10 +976,10 @@ namespace TemporaryObjectExpr { }; constexpr int foo(F f) { - return f.i + f.U.f; // ref-note {{read of member 'f' of union with active member 'a'}} + return f.i + f.U.f; // both-note {{read of member 'f' of union with active member 'a'}} } - static_assert(foo(F()) == 0, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to}} + static_assert(foo(F()) == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} } #endif diff --git a/clang/test/AST/Interp/unions.cpp b/clang/test/AST/Interp/unions.cpp index a51f30cd9185b..6f6bc3d6891b4 100644 --- a/clang/test/AST/Interp/unions.cpp +++ b/clang/test/AST/Interp/unions.cpp @@ -253,4 +253,49 @@ namespace Nested { // both-note {{in call to}} } + + +namespace Zeroing { + struct non_trivial_constructor { + constexpr non_trivial_constructor() : x(100) {} + int x; + }; + union U2 { + int a{1000}; + non_trivial_constructor b; + }; + + static_assert(U2().b.x == 100, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of member 'b' of union with active member 'a'}} + + union { int a; int b; } constexpr u1{}; + static_assert(u1.a == 0, ""); + static_assert(u1.b == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of member 'b' of union with active member 'a'}} + + union U { int a; int b; } constexpr u2 = U(); + static_assert(u2.a == 0, ""); + static_assert(u2.b == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of member 'b' of union with active member 'a'}} + + + struct F {int x; int y; }; + union { F a; int b; } constexpr u3{}; + static_assert(u3.a.x == 0, ""); + + union U4 { F a; int b; } constexpr u4 = U4(); + static_assert(u4.a.x == 0, ""); + + union { int a[5]; int b; } constexpr u5{}; + static_assert(u5.a[0] == 0, ""); + static_assert(u5.a[4] == 0, ""); + static_assert(u5.b == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of member 'b' of union with active member 'a'}} + + union U6 { int a[5]; int b; } constexpr u6 = U6(); + static_assert(u6.a[0] == 0, ""); + static_assert(u6.a[4] == 0, ""); + static_assert(u6.b == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of member 'b' of union with active member 'a'}} +} #endif `````````` </details> https://github.com/llvm/llvm-project/pull/102744 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits