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

>From 11e636093500994024282cbab138fcd33d2afa03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com>
Date: Wed, 23 Jul 2025 09:01:22 +0200
Subject: [PATCH] [clang][bytecode] Disable location tracking for implicit
 field inits

---
 clang/lib/AST/ByteCode/ByteCodeEmitter.cpp    |  4 +-
 clang/lib/AST/ByteCode/ByteCodeEmitter.h      |  1 +
 clang/lib/AST/ByteCode/Compiler.cpp           | 38 +++++++++++++++++++
 clang/lib/AST/ByteCode/Compiler.h             |  2 +
 clang/lib/AST/ByteCode/EvalEmitter.cpp        |  1 +
 clang/lib/AST/ByteCode/EvalEmitter.h          |  1 +
 clang/lib/AST/ByteCode/InterpFrame.cpp        | 12 +++++-
 clang/lib/AST/ByteCode/State.cpp              |  1 +
 clang/test/AST/ByteCode/lifetimes.cpp         |  3 +-
 clang/test/AST/ByteCode/mutable.cpp           |  8 ++++
 clang/test/AST/ByteCode/new-delete.cpp        |  5 +--
 clang/test/AST/ByteCode/unions.cpp            |  4 +-
 .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp |  3 ++
 13 files changed, 74 insertions(+), 9 deletions(-)

diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp 
b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index d4746052c5cfe..0c003b21f35d6 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -216,7 +216,9 @@ bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &...Args,
   // The opcode is followed by arguments. The source info is
   // attached to the address after the opcode.
   emit(P, Code, Op, Success);
-  if (SI)
+  if (LocOverride)
+    SrcMap.emplace_back(Code.size(), *LocOverride);
+  else if (SI)
     SrcMap.emplace_back(Code.size(), SI);
 
   (..., emit(P, Code, Args, Success));
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.h 
b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
index 9e9dd5e87cd7a..fafba3f68765c 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.h
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
@@ -73,6 +73,7 @@ class ByteCodeEmitter {
   ParamOffset LambdaThisCapture{0, false};
   /// Local descriptors.
   llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
+  std::optional<SourceInfo> LocOverride = std::nullopt;
 
 private:
   /// Current compilation context.
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 7a5bd4dfc0bed..f587be6afe4e4 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -185,6 +185,31 @@ template <class Emitter> class StmtExprScope final {
   bool OldFlag;
 };
 
+/// When generating code for e.g. implicit field initializers in constructors,
+/// we don't have anything to point to in case the initializer causes an error.
+/// In that case, we need to disable location tracking for the initializer so
+/// we later point to the call range instead.
+template <class Emitter> class LocOverrideScope final {
+public:
+  LocOverrideScope(Compiler<Emitter> *Ctx, SourceInfo NewValue,
+                   bool Enabled = true)
+      : Ctx(Ctx), OldFlag(Ctx->LocOverride), Enabled(Enabled) {
+
+    if (Enabled)
+      Ctx->LocOverride = NewValue;
+  }
+
+  ~LocOverrideScope() {
+    if (Enabled)
+      Ctx->LocOverride = OldFlag;
+  }
+
+private:
+  Compiler<Emitter> *Ctx;
+  std::optional<SourceInfo> OldFlag;
+  bool Enabled;
+};
+
 } // namespace interp
 } // namespace clang
 
@@ -6012,6 +6037,8 @@ bool Compiler<Emitter>::compileConstructor(const 
CXXConstructorDecl *Ctor) {
   bool IsUnion = R->isUnion();
 
   if (IsUnion && Ctor->isCopyOrMoveConstructor()) {
+    LocOverrideScope<Emitter> LOS(this, SourceInfo{});
+
     if (R->getNumFields() == 0)
       return this->emitRetVoid(Ctor);
     // union copy and move ctors are special.
@@ -6038,6 +6065,11 @@ bool Compiler<Emitter>::compileConstructor(const 
CXXConstructorDecl *Ctor) {
     if (const FieldDecl *Member = Init->getMember()) {
       const Record::Field *F = R->getField(Member);
 
+      LocOverrideScope<Emitter> LOS(this, SourceInfo{},
+                                    !Init->isWritten() &&
+                                        !Init->isInClassMemberInitializer() &&
+                                        (!isa<CXXConstructExpr>(InitExpr) ||
+                                         Member->isAnonymousStructOrUnion()));
       if (!emitFieldInitializer(F, F->Offset, InitExpr, IsUnion))
         return false;
     } else if (const Type *Base = Init->getBaseClass()) {
@@ -6066,6 +6098,10 @@ bool Compiler<Emitter>::compileConstructor(const 
CXXConstructorDecl *Ctor) {
       if (!this->emitFinishInitPop(InitExpr))
         return false;
     } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
+      LocOverrideScope<Emitter> LOS(this, SourceInfo{},
+                                    !Init->isWritten() &&
+                                        !Init->isInClassMemberInitializer() &&
+                                        !isa<CXXConstructExpr>(InitExpr));
 
       assert(IFD->getChainingSize() >= 2);
 
@@ -6144,6 +6180,8 @@ bool Compiler<Emitter>::compileDestructor(const 
CXXDestructorDecl *Dtor) {
 
   assert(R);
   if (!R->isUnion()) {
+
+    LocOverrideScope<Emitter> LOS(this, SourceInfo{});
     // First, destroy all fields.
     for (const Record::Field &Field : llvm::reverse(R->fields())) {
       const Descriptor *D = Field.Desc;
diff --git a/clang/lib/AST/ByteCode/Compiler.h 
b/clang/lib/AST/ByteCode/Compiler.h
index 16f108fb5d141..ee8327d8fee1e 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -40,6 +40,7 @@ template <class Emitter> class LoopScope;
 template <class Emitter> class LabelScope;
 template <class Emitter> class SwitchScope;
 template <class Emitter> class StmtExprScope;
+template <class Emitter> class LocOverrideScope;
 
 template <class Emitter> class Compiler;
 struct InitLink {
@@ -333,6 +334,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, 
bool>,
   friend class LabelScope<Emitter>;
   friend class SwitchScope<Emitter>;
   friend class StmtExprScope<Emitter>;
+  friend class LocOverrideScope<Emitter>;
 
   /// Emits a zero initializer.
   bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp 
b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index fd7f3423c0f9b..8eaee09fea664 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -53,6 +53,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
                                             bool CheckFullyInitialized) {
   this->CheckFullyInitialized = CheckFullyInitialized;
   S.EvaluatingDecl = VD;
+  S.setEvalLocation(VD->getLocation());
   EvalResult.setSource(VD);
 
   if (const Expr *Init = VD->getAnyInitializer()) {
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.h 
b/clang/lib/AST/ByteCode/EvalEmitter.h
index 2fe7da608c739..85a0a99fbb4b0 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.h
+++ b/clang/lib/AST/ByteCode/EvalEmitter.h
@@ -95,6 +95,7 @@ class EvalEmitter : public SourceMapper {
   ParamOffset LambdaThisCapture{0, false};
   /// Local descriptors.
   llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
+  std::optional<SourceInfo> LocOverride = std::nullopt;
 
 private:
   /// Current compilation context.
diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp 
b/clang/lib/AST/ByteCode/InterpFrame.cpp
index d62a4f6275b50..14f99c7b76847 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.cpp
+++ b/clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -202,7 +202,17 @@ SourceRange InterpFrame::getCallRange() const {
       return NullRange;
     return S.EvalLocation;
   }
-  return S.getRange(Caller->Func, RetPC - sizeof(uintptr_t));
+
+  // Move up to the frame that has a valid location for the caller.
+  for (const InterpFrame *C = this; C; C = C->Caller) {
+    if (!C->RetPC)
+      continue;
+    SourceRange CallRange =
+        S.getRange(C->Caller->Func, C->RetPC - sizeof(uintptr_t));
+    if (CallRange.isValid())
+      return CallRange;
+  }
+  return S.EvalLocation;
 }
 
 const FunctionDecl *InterpFrame::getCallee() const {
diff --git a/clang/lib/AST/ByteCode/State.cpp b/clang/lib/AST/ByteCode/State.cpp
index 3204d1a193a74..dc3d0da7a4a46 100644
--- a/clang/lib/AST/ByteCode/State.cpp
+++ b/clang/lib/AST/ByteCode/State.cpp
@@ -131,6 +131,7 @@ void State::addCallStack(unsigned Limit) {
   const Frame *Bottom = getBottomFrame();
   for (const Frame *F = Top; F != Bottom; F = F->getCaller(), ++CallIdx) {
     SourceRange CallRange = F->getCallRange();
+    assert(CallRange.isValid());
 
     // Skip this call?
     if (CallIdx >= SkipStart && CallIdx < SkipEnd) {
diff --git a/clang/test/AST/ByteCode/lifetimes.cpp 
b/clang/test/AST/ByteCode/lifetimes.cpp
index 5e021387348b5..5c8d56291f079 100644
--- a/clang/test/AST/ByteCode/lifetimes.cpp
+++ b/clang/test/AST/ByteCode/lifetimes.cpp
@@ -31,8 +31,7 @@ struct S {
                                 // expected-note {{read of temporary whose 
lifetime has ended}}
 };
 constexpr int k1 = S().t; // both-error {{must be initialized by a constant 
expression}} \
-                          // ref-note {{in call to}} \
-                          // expected-note {{in call to}}
+                          // both-note {{in call to}}
 
 
 namespace MoveFnWorks {
diff --git a/clang/test/AST/ByteCode/mutable.cpp 
b/clang/test/AST/ByteCode/mutable.cpp
index 35c5a0389921e..16c8ce9125d5e 100644
--- a/clang/test/AST/ByteCode/mutable.cpp
+++ b/clang/test/AST/ByteCode/mutable.cpp
@@ -66,3 +66,11 @@ namespace MutableInConst {
   static_assert(mutableInConst() == 1, "");
 }
 #endif
+
+struct D { mutable int y; }; // both-note {{declared here}}
+constexpr D d1 = { 1 };
+constexpr D d2 = d1; // both-error {{must be initialized by a constant 
expression}} \
+                     // both-note {{read of mutable member 'y}} \
+                     // both-note {{in call to}}
+
+
diff --git a/clang/test/AST/ByteCode/new-delete.cpp 
b/clang/test/AST/ByteCode/new-delete.cpp
index 3c0bdbc8c99fe..c5f1878c41734 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -546,14 +546,13 @@ namespace FaultyDtorCalledByDelete {
       a = new int(13);
       IF.mem = new int(100);
     }
-    constexpr ~Foo() { delete a; } // expected-note {{in call to}}
+    constexpr ~Foo() { delete a; }
   };
 
   constexpr int abc() {
     Foo *F = new Foo();
     int n = *F->a;
-    delete F; // both-note {{in call to}} \
-              // ref-note {{in call to}}
+    delete F; // both-note 2{{in call to}}
 
     return n;
   }
diff --git a/clang/test/AST/ByteCode/unions.cpp 
b/clang/test/AST/ByteCode/unions.cpp
index 139e318e1ba68..8ed76258b879a 100644
--- a/clang/test/AST/ByteCode/unions.cpp
+++ b/clang/test/AST/ByteCode/unions.cpp
@@ -849,14 +849,14 @@ namespace Activation2 {
 
 namespace CopyCtorMutable {
   struct E {
-    union { // expected-note {{read of mutable member 'b'}}
+    union {
       int a;
       mutable int b; // both-note {{here}}
     };
   };
   constexpr E e1 = {{1}};
   constexpr E e2 = e1; // both-error {{constant}} \
-                       // ref-note {{read of mutable member 'b'}} \
+                       // both-note {{read of mutable member 'b'}} \
                        // both-note {{in call}}
 }
 
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp 
b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
index 270bc3cb48be9..dd0f1fc3cba8e 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
@@ -1,6 +1,9 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s
 
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s 
-fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s 
-fexperimental-new-constant-interpreter
+
 // A constexpr specifier used in an object declaration declares the object as
 // const.
 constexpr int a = 0;

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to