Author: Timm Baeder
Date: 2026-01-28T12:59:24+01:00
New Revision: 7c3a2113febd1df48b31c2ada5cbcf1935053807

URL: 
https://github.com/llvm/llvm-project/commit/7c3a2113febd1df48b31c2ada5cbcf1935053807
DIFF: 
https://github.com/llvm/llvm-project/commit/7c3a2113febd1df48b31c2ada5cbcf1935053807.diff

LOG: [clang][ExprConst] Fix rendering of explicit this parameters (#177551)

in compile-time backtraces.

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

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/InterpFrame.cpp
    clang/lib/AST/ExprConstant.cpp
    clang/test/SemaCXX/cxx2b-deducing-this.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/InterpFrame.cpp 
b/clang/lib/AST/ByteCode/InterpFrame.cpp
index a9f8823613b0a..ef70d9526c194 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,14 +196,12 @@ 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 (const ParmVarDecl *Param :
+       F->parameters().slice(ExplicitInstanceParam)) {
     OS << Comma;
-    QualType Ty = F->getParamDecl(I)->getType();
+    QualType Ty = Param->getType();
     PrimType PrimTy = S.Ctx.classify(Ty).value_or(PT_Ptr);
 
     TYPE_SWITCH(PrimTy, print(OS, stackRef<T>(Off), S.getASTContext(), Ty));

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 857688ed8039d..58748fa5ba49b 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(),
@@ -2007,25 +2009,19 @@ void CallStackFrame::describe(raw_ostream &Out) const {
     }
     Callee->getNameForDiagnostic(Out, Info.Ctx.getPrintingPolicy(),
                                  /*Qualified=*/false);
-    IsMemberCall = false;
   }
 
   Out << '(';
 
-  for (FunctionDecl::param_const_iterator I = Callee->param_begin(),
-       E = Callee->param_end(); I != E; ++I, ++ArgIndex) {
-    if (ArgIndex > (unsigned)IsMemberCall)
-      Out << ", ";
-
-    const ParmVarDecl *Param = *I;
-    APValue *V = Info.getParamSlot(Arguments, Param);
+  llvm::ListSeparator Comma;
+  for (const ParmVarDecl *Param :
+       Callee->parameters().slice(ExplicitInstanceParam)) {
+    Out << Comma;
+    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