https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/177551

in compile-time backtraces.

The two test cases used to be rendered as `foo(s, 0) and `foo2(s)`.

>From 90b980dded80a8525700f7eef4e4e0f98fd4f7ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Fri, 23 Jan 2026 10:16:49 +0100
Subject: [PATCH] [clang][ExprConst] Fix rendering of explicit this parameters

in compile-time backtraces.

The two test cases used to be rendered as `foo(s, 0) and `foo2(s)`.
---
 clang/lib/AST/ByteCode/InterpFrame.cpp     | 17 +++++++-----
 clang/lib/AST/ExprConstant.cpp             | 25 +++++++++---------
 clang/test/SemaCXX/cxx2b-deducing-this.cpp | 30 ++++++++++++++++++++++
 3 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp 
b/clang/lib/AST/ByteCode/InterpFrame.cpp
index a9f8823613b0a..5a103e5af38f8 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.cpp
+++ b/clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -158,8 +158,14 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
 
   const Expr *CallExpr = Caller->getExpr(getRetPC());
   const FunctionDecl *F = getCallee();
-  bool IsMemberCall = isa<CXXMethodDecl>(F) && !isa<CXXConstructorDecl>(F) &&
-                      cast<CXXMethodDecl>(F)->isImplicitObjectMemberFunction();
+
+  bool IsMemberCall = false;
+  bool ExplicitInstanceParam = false;
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) {
+    IsMemberCall = !isa<CXXConstructorDecl>(MD) && !MD->isStatic();
+    ExplicitInstanceParam = MD->isExplicitObjectMemberFunction();
+  }
+
   if (Func->hasThisPointer() && IsMemberCall) {
     if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(CallExpr)) {
       const Expr *Object = MCE->getImplicitObjectArgument();
@@ -190,12 +196,9 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
   unsigned Off = 0;
 
   Off += Func->hasRVO() ? primSize(PT_Ptr) : 0;
-  Off += (Func->hasThisPointer() && !Func->isThisPointerExplicit())
-             ? primSize(PT_Ptr)
-             : 0;
-
+  Off += Func->hasThisPointer() ? primSize(PT_Ptr) : 0;
   llvm::ListSeparator Comma;
-  for (unsigned I = 0, N = F->getNumParams(); I < N; ++I) {
+  for (unsigned I = ExplicitInstanceParam, N = F->getNumParams(); I != N; ++I) 
{
     OS << Comma;
     QualType Ty = F->getParamDecl(I)->getType();
     PrimType PrimTy = S.Ctx.classify(Ty).value_or(PT_Ptr);
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 857688ed8039d..deb08d4bddb19 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -1973,10 +1973,12 @@ APValue *EvalInfo::createHeapAlloc(const Expr *E, 
QualType T, LValue &LV) {
 
 /// Produce a string describing the given constexpr call.
 void CallStackFrame::describe(raw_ostream &Out) const {
-  unsigned ArgIndex = 0;
-  bool IsMemberCall =
-      isa<CXXMethodDecl>(Callee) && !isa<CXXConstructorDecl>(Callee) &&
-      cast<CXXMethodDecl>(Callee)->isImplicitObjectMemberFunction();
+  bool IsMemberCall = false;
+  bool ExplicitInstanceParam = false;
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee)) {
+    IsMemberCall = !isa<CXXConstructorDecl>(MD) && !MD->isStatic();
+    ExplicitInstanceParam = MD->isExplicitObjectMemberFunction();
+  }
 
   if (!IsMemberCall)
     Callee->getNameForDiagnostic(Out, Info.Ctx.getPrintingPolicy(),
@@ -2012,20 +2014,17 @@ void CallStackFrame::describe(raw_ostream &Out) const {
 
   Out << '(';
 
-  for (FunctionDecl::param_const_iterator I = Callee->param_begin(),
-       E = Callee->param_end(); I != E; ++I, ++ArgIndex) {
-    if (ArgIndex > (unsigned)IsMemberCall)
-      Out << ", ";
+  llvm::ListSeparator Comma;
+  for (unsigned ArgIndex = ExplicitInstanceParam, N = Callee->getNumParams();
+       ArgIndex != N; ++ArgIndex) {
+    Out << Comma;
 
-    const ParmVarDecl *Param = *I;
-    APValue *V = Info.getParamSlot(Arguments, Param);
+    const ParmVarDecl *Param = Callee->getParamDecl(ArgIndex);
+    const APValue *V = Info.getParamSlot(Arguments, Param);
     if (V)
       V->printPretty(Out, Info.Ctx, Param->getType());
     else
       Out << "<...>";
-
-    if (ArgIndex == 0 && IsMemberCall)
-      Out << "->" << *Callee << '(';
   }
 
   Out << ')';
diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp 
b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
index a9e31c3d06676..7b4924a1e5285 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -1400,3 +1400,33 @@ a void Bar(this int) { // expected-note {{candidate 
function}}
 }
 
 }
+
+namespace ConstexprBacktrace {
+  struct S {
+    constexpr int foo(this const S& self, int b) {
+      (void)(1/b); // expected-note {{division by zero}}
+      return 0;
+    }
+    constexpr int foo2(this const S& self) {
+      (void)(1/0); // expected-note {{division by zero}} \
+                   // expected-warning {{division by zero is undefined}}
+      return 0;
+    }
+  };
+
+  constexpr bool test() {
+    S s;
+    s.foo(0); // expected-note {{in call to 's.foo(0)'}}
+    return true;
+  }
+  static_assert(test()); // expected-error {{not an integral constant 
expression}} \
+                         // expected-note {{in call to}}
+
+  constexpr bool test2() {
+    S s;
+    s.foo2(); // expected-note {{in call to 's.foo2()'}}
+    return true;
+  }
+  static_assert(test2()); // expected-error {{not an integral constant 
expression}} \
+                          // expected-note {{in call to}}
+}

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

Reply via email to