https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/224839

>From cd1b6f9af512f86e7a80e4a6230b3b56b503dde3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Sat, 19 Sep 2026 15:47:00 +0200
Subject: [PATCH] default ctor

---
 clang/lib/AST/ByteCode/Compiler.cpp           | 10 +++
 clang/lib/AST/ByteCode/Interp.cpp             | 63 +++++++++++++++++++
 clang/lib/AST/ByteCode/Interp.h               |  1 +
 clang/lib/AST/ByteCode/Opcodes.td             |  5 ++
 .../AST/ByteCode/Inputs/default-ctor.cppm     | 12 ++++
 .../test/AST/ByteCode/module-default-ctor.cpp | 11 ++++
 6 files changed, 102 insertions(+)
 create mode 100644 clang/test/AST/ByteCode/Inputs/default-ctor.cppm
 create mode 100644 clang/test/AST/ByteCode/module-default-ctor.cpp

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index d7bdb2f217a9a..83b118c18b7aa 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -3899,6 +3899,16 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const 
CXXConstructExpr *E) {
         return true;
     }
 
+    // Trivial default constructors might never be implicitly defined by the
+    // AST, so we need to special-case them here.
+    if (Ctor->isTrivial() && Ctor->isDefaultConstructor()) {
+      if (!this->emitDefaultInit(Ctor, E))
+        return false;
+      if (DiscardResult)
+        return this->emitPopPtr(E);
+      return true;
+    }
+
     // Avoid materializing a temporary for an elidable copy/move constructor.
     if (!ZeroInit && E->isElidable()) {
       const Expr *SrcObj = E->getArg(0);
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index ab6b474503a3b..dde7e54d86977 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -2683,6 +2683,69 @@ bool MarkDestroyed(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
+// Initializes all bases and virtual bases.
+// Only starts the lifetime of fields, but doesn't initialize them.
+static void initBasesRecurse(PtrView Ptr) {
+  assert(Ptr.getRecord());
+
+  const Record *R = Ptr.getRecord();
+  for (const Record::Base &B : R->bases()) {
+    PtrView BasePtr = Ptr.atField(B.Offset);
+    BasePtr.initialize();
+    BasePtr.startLifetime();
+    initBasesRecurse(BasePtr);
+  }
+
+  for (const Record::Field &F : R->fields()) {
+    PtrView FieldPtr = Ptr.atField(F.Offset);
+    FieldPtr.startLifetime();
+    if (FieldPtr.getRecord())
+      initBasesRecurse(FieldPtr);
+  }
+
+  for (const Record::Base &B : R->virtual_bases()) {
+    PtrView BasePtr = Ptr.atField(B.Offset);
+    BasePtr.initialize();
+    BasePtr.startLifetime();
+    initBasesRecurse(BasePtr);
+  }
+}
+
+bool DefaultInit(InterpState &S, CodePtr OpPC, const CXXConstructorDecl *Ctor) 
{
+  auto Ptr = S.Stk.peek<Pointer>();
+
+  if (!Ptr.isBlockPointer())
+    return false;
+  const Record *R = Ptr.getRecord();
+  if (!R)
+    return false;
+
+  if (Ctor->isInvalidDecl() || Ctor->getParent()->isInvalidDecl())
+    return false;
+
+  if (!Ctor->isConstexpr()) {
+    if (S.getLangOpts().CPlusPlus11) {
+      // FIXME: If DiagDecl is an implicitly-declared special member function,
+      // we should be much more explicit about why it's not constexpr.
+      S.CCEDiag(S.Current->getSource(OpPC),
+                diag::note_constexpr_invalid_function, 1)
+          << /*IsConstexpr*/ 0 << /*IsConstructor*/ 1 << Ctor;
+      S.Note(Ctor->getLocation(), diag::note_declared_at);
+    } else {
+      S.CCEDiag(S.Current->getSource(OpPC),
+                diag::note_invalid_subexpr_in_const_expr);
+    }
+  }
+
+  Ptr.startLifetime();
+  Ptr.initialize();
+
+  startLifetimeRecurse(Ptr.view());
+  initBasesRecurse(Ptr.view());
+
+  return true;
+}
+
 bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
                           std::optional<uint64_t> ArraySize) {
   Pointer &Orig = S.Stk.peek<Pointer>();
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index edbf2adcda637..f7d396b720767 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1642,6 +1642,7 @@ bool PseudoDtor(InterpState &S, CodePtr OpPC);
 bool StartThisLifetime(InterpState &S);
 bool StartThisLifetime1(InterpState &S);
 bool MarkDestroyed(InterpState &S, CodePtr OpPC);
+bool DefaultInit(InterpState &S, CodePtr OpPC, const CXXConstructorDecl *Ctor);
 
 /// 1) Pops the value from the stack.
 /// 2) Writes the value to the local variable with the
diff --git a/clang/lib/AST/ByteCode/Opcodes.td 
b/clang/lib/AST/ByteCode/Opcodes.td
index 11ba6ddf41b74..afed0014c1a10 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -73,6 +73,7 @@ def ArgPrimType : ArgType { let Name = "PrimType"; }
 def ArgEnumDecl : ArgType { let Name = "const EnumDecl *"; }
 def ArgTypePtr : ArgType { let Name = "const Type *"; }
 def ArgDeclOrExpr : ArgType { let Name = "DeclOrExpr"; }
+def ArgCtorDecl : ArgType { let Name = "const CXXConstructorDecl *"; }
 
 
//===----------------------------------------------------------------------===//
 // Classes of types instructions operate on.
@@ -479,6 +480,10 @@ def StartThisLifetime1 : Opcode {
   let NeedsOpPC = 0;
 }
 
+def DefaultInit : Opcode {
+  let Args = [ArgCtorDecl];
+}
+
 def CheckDecl : Opcode {
   let Args = [ArgVarDecl];
   let NeedsOpPC = 0;
diff --git a/clang/test/AST/ByteCode/Inputs/default-ctor.cppm 
b/clang/test/AST/ByteCode/Inputs/default-ctor.cppm
new file mode 100644
index 0000000000000..ee945435eaea1
--- /dev/null
+++ b/clang/test/AST/ByteCode/Inputs/default-ctor.cppm
@@ -0,0 +1,12 @@
+export module m;
+
+export struct allocator_like {
+  constexpr allocator_like() noexcept = default;
+};
+
+export struct box {
+  allocator_like allocation;
+  int value = 42;
+  constexpr box() = default;
+  [[nodiscard]] constexpr int get() const { return value; }
+};
diff --git a/clang/test/AST/ByteCode/module-default-ctor.cpp 
b/clang/test/AST/ByteCode/module-default-ctor.cpp
new file mode 100644
index 0000000000000..4883b2a6e28ba
--- /dev/null
+++ b/clang/test/AST/ByteCode/module-default-ctor.cpp
@@ -0,0 +1,11 @@
+// RUN: mkdir -p %t
+// RUN: %clang    -std=c++20 %p/Inputs/default-ctor.cppm --precompile -o 
%t/default-ctor.pcm
+// RUN: %clang -c -std=c++20 -fmodule-file=m=%t/default-ctor.pcm 
-fexperimental-new-constant-interpreter %s
+import m;
+
+
+consteval int evaluate() {
+  box b;
+  return b.get();
+}
+static_assert(evaluate() == 42);

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to