Author: Timm Baeder Date: 2026-09-22T10:13:48+02:00 New Revision: 80310178c079fc4ec712ace6d72a97bb5c619a12
URL: https://github.com/llvm/llvm-project/commit/80310178c079fc4ec712ace6d72a97bb5c619a12 DIFF: https://github.com/llvm/llvm-project/commit/80310178c079fc4ec712ace6d72a97bb5c619a12.diff LOG: [clang][bytecode] Mark fields as being initialized, even without running a ctor for them (#225295) To fix the diagnostics. Added: Modified: clang/lib/AST/ByteCode/Compiler.cpp clang/lib/AST/ByteCode/Interp.h clang/lib/AST/ByteCode/Opcodes.td clang/test/AST/ByteCode/invalid.cpp clang/test/SemaCXX/aggregate-default-member-initializers.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 38a095f8a1164..ecece6f08f3ab 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -2362,10 +2362,18 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, auto initPrimitiveField = [=](const Record::Field *FieldToInit, const Expr *Init, PrimType T, bool Activate = false) -> bool { - InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init)); + bool DefaultInit = isa<CXXDefaultInitExpr>(Init); + InitStackScope<Emitter> ISS(this, DefaultInit); + + if (DefaultInit && !this->emitStartFieldInit(FieldToInit->Offset, Init)) + return false; + if (!this->visit(Init)) return false; + if (DefaultInit && !this->emitEndInit(Init)) + return false; + bool BitField = FieldToInit->isBitField(); if (BitField && Activate) return this->emitInitBitFieldActivate(T, FieldToInit->Offset, @@ -2392,7 +2400,10 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, if (Activate && !this->emitActivate(E)) return false; - return this->visitInitializerPop(Init); + if (!this->emitStartInit(Init)) + return false; + + return this->visitInitializerPop(Init) && this->emitEndInit(Init); }; if (R->isUnion()) { diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index f7d396b720767..d95d799288938 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -3738,6 +3738,12 @@ inline bool StartInit(InterpState &S) { return true; } +inline bool StartFieldInit(InterpState &S, uint32_t FieldOffset) { + const Pointer &Ptr = S.Stk.peek<Pointer>(); + S.InitializingPtrs.push_back(Ptr.view().atField(FieldOffset)); + return true; +} + inline bool EndInit(InterpState &S) { S.InitializingPtrs.pop_back(); return true; diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index afed0014c1a10..78d99bf3c433f 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -190,6 +190,9 @@ def PushIgnoreDiags : SuccessOpcode; def PopIgnoreDiags : SuccessOpcode; def StartInit : SuccessOpcode; +def StartFieldInit : SuccessOpcode { + let Args = [ArgUint32]; +} def EndInit : SuccessOpcode; def StartSpeculation : SuccessOpcode; diff --git a/clang/test/AST/ByteCode/invalid.cpp b/clang/test/AST/ByteCode/invalid.cpp index 3dd2dc91df9c1..565d65f60514a 100644 --- a/clang/test/AST/ByteCode/invalid.cpp +++ b/clang/test/AST/ByteCode/invalid.cpp @@ -282,3 +282,22 @@ namespace NonRecordNonArrayDesc { F foo(42); } + +namespace CompositeFieldInit { + struct S { + static consteval int decrement(int &x) { + return --x; + } + + int a = 10; + int b = decrement(a); // both-error {{is not a constant expression}} \ + // both-note {{declared here}} \ + // both-note {{implicit use of 'this'}} + }; + + struct S2 { + const S s{10}; // both-note {{in the default initializer of 'b'}} + }; + + constexpr S2 s2{}; +} diff --git a/clang/test/SemaCXX/aggregate-default-member-initializers.cpp b/clang/test/SemaCXX/aggregate-default-member-initializers.cpp index 27fb4deab77d6..849e02e244bd4 100644 --- a/clang/test/SemaCXX/aggregate-default-member-initializers.cpp +++ b/clang/test/SemaCXX/aggregate-default-member-initializers.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -std=c++20 -Wno-unused-value -verify=expected %s -// RUN: %clang_cc1 -std=c++23 -Wno-unused-value -verify=expected %s -// RUN: %clang_cc1 -std=c++20 -Wno-unused-value -verify=expected,bytecode %s \ -// RUN: -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++20 -Wno-unused-value -verify %s +// RUN: %clang_cc1 -std=c++23 -Wno-unused-value -verify %s +// RUN: %clang_cc1 -std=c++20 -Wno-unused-value -verify %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++23 -Wno-unused-value -verify %s -fexperimental-new-constant-interpreter namespace lifetime { @@ -69,25 +69,22 @@ namespace immediate { struct Inner { int a; static consteval int decrement(int &x) { - return --x; // bytecode-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}} + return --x; } // FIXME: The aggregate result object does not exist yet when the immediate // invocation is checked, so reading 'a' fails. This is long-standing and is // independent of which full-expression the initializer belongs to. int b = decrement(a); // expected-error {{call to consteval function 'immediate::Inner::decrement' is not a constant expression}} \ // expected-note {{implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function}} \ - // expected-note {{declared here}} \ - // bytecode-note {{in call to 'decrement(Inner{1}.a)'}} + // expected-note {{declared here}} }; struct Outer { const Inner &inner = Inner{1}; // expected-note {{in the default initializer of 'b'}} }; -constexpr int value = Outer{}.inner.a; // bytecode-error {{constexpr variable 'value' must be initialized by a constant expression}} \ - // bytecode-note {{declared here}} -static_assert(value == 0); // bytecode-error {{static assertion expression is not an integral constant expression}} \ - // bytecode-note {{initializer of 'value' is not a constant expression}} +constexpr int value = Outer{}.inner.a; +static_assert(value == 0); consteval unsigned currentLine(unsigned line = __builtin_LINE()) { return line; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
