Skip to content

[clang][bytecode] Refactor backtrace param printing#202325

Merged
tbaederr merged 2 commits into
llvm:mainfrom
tbaederr:param-print
Jun 9, 2026
Merged

[clang][bytecode] Refactor backtrace param printing#202325
tbaederr merged 2 commits into
llvm:mainfrom
tbaederr:param-print

Conversation

@tbaederr

@tbaederr tbaederr commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Instead of classify()ing the parameter types here, just use the saved PrimType in the ParamDescriptor.

This also fixed an oddity with interp::Context: Pointer::toRValue() takes an interp::Context, but some call sites passed an ASTContext instead, which worked because of the implicit constructor. Make it explicit.

@llvmorg-github-actions llvmorg-github-actions Bot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:bytecode Issues for the clang bytecode constexpr interpreter labels Jun 8, 2026
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

Instead of classify()ing the parameter types here, just use the saved PrimType in the ParamDescriptor.

This also fixed an oddity with interp::Context: Pointer::toRValue() takes an interp::Context, but some call sites passed an ASTContext instead, which worked because of the implicit constructor. Make it explicit.


Full diff: https://github.com/llvm/llvm-project/pull/202325.diff

4 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Context.h (+1-1)
  • (modified) clang/lib/AST/ByteCode/EvalEmitter.cpp (+1-1)
  • (modified) clang/lib/AST/ByteCode/Function.h (+1-1)
  • (modified) clang/lib/AST/ByteCode/InterpFrame.cpp (+21-21)
diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h
index 9a66226807e4e..235a4e44a9342 100644
--- a/clang/lib/AST/ByteCode/Context.h
+++ b/clang/lib/AST/ByteCode/Context.h
@@ -47,7 +47,7 @@ class EvalIDScope;
 class Context final {
 public:
   /// Initialises the constexpr VM.
-  Context(ASTContext &Ctx);
+  explicit Context(ASTContext &Ctx);
 
   /// Cleans up the constexpr VM.
   ~Context();
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index 3e1aade65afc8..a7afd3008afb8 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -298,7 +298,7 @@ bool EvalEmitter::emitRetValue(SourceInfo Info) {
     return false;
 
   if (std::optional<APValue> APV =
-          Ptr.toRValue(S.getASTContext(), EvalResult.getSourceType())) {
+          Ptr.toRValue(Ctx, EvalResult.getSourceType())) {
     EvalResult.takeValue(std::move(*APV));
     return true;
   }
diff --git a/clang/lib/AST/ByteCode/Function.h b/clang/lib/AST/ByteCode/Function.h
index 862b0b4a0d746..d9a286937cadd 100644
--- a/clang/lib/AST/ByteCode/Function.h
+++ b/clang/lib/AST/ByteCode/Function.h
@@ -148,7 +148,7 @@ class Function final {
   }
 
   /// Returns a parameter descriptor.
-  ParamDescriptor getParamDescriptor(unsigned Index) const {
+  const ParamDescriptor &getParamDescriptor(unsigned Index) const {
     return ParamDescriptors[Index];
   }
 
diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp b/clang/lib/AST/ByteCode/InterpFrame.cpp
index 9c9318fe0e55a..34d77acb6f045 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.cpp
+++ b/clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -121,19 +121,19 @@ void InterpFrame::destroy(unsigned Idx) {
 }
 
 template <typename T>
-static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx,
+static void print(llvm::raw_ostream &OS, const T &V, const Context &Ctx,
                   QualType Ty) {
   if constexpr (std::is_same_v<Pointer, T>) {
     if (Ty->isPointerOrReferenceType())
-      V.toAPValue(ASTCtx).printPretty(OS, ASTCtx, Ty);
+      V.toAPValue(Ctx.getASTContext()).printPretty(OS, Ctx.getASTContext(), Ty);
     else {
-      if (std::optional<APValue> RValue = V.toRValue(ASTCtx, Ty))
-        RValue->printPretty(OS, ASTCtx, Ty);
+      if (std::optional<APValue> RValue = V.toRValue(Ctx, Ty))
+        RValue->printPretty(OS, Ctx.getASTContext(), Ty);
       else
         OS << "...";
     }
   } else {
-    V.toAPValue(ASTCtx).printPretty(OS, ASTCtx, Ty);
+    V.toAPValue(Ctx.getASTContext()).printPretty(OS, Ctx.getASTContext(), Ty);
   }
 }
 
@@ -159,9 +159,10 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
   if (shouldSkipInBacktrace(Func))
     return;
 
+  const ASTContext &ASTCtx = S.getASTContext();
   const Expr *CallExpr = Caller->getExpr(getRetPC());
   const FunctionDecl *F = getCallee();
-  auto PrintingPolicy = S.getASTContext().getPrintingPolicy();
+  auto PrintingPolicy = ASTCtx.getPrintingPolicy();
   PrintingPolicy.SuppressLambdaBody = true;
 
   bool IsMemberCall = false;
@@ -180,39 +181,38 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
       if (Object->getType()->isPointerType())
         OS << "->";
       else
-        OS << ".";
+        OS << '.';
     } else if (const auto *OCE =
                    dyn_cast_if_present<CXXOperatorCallExpr>(CallExpr)) {
       OCE->getArg(0)->printPretty(OS, /*Helper=*/nullptr,
                                   PrintingPolicy,
                                   /*Indentation=*/0);
-      OS << ".";
+      OS << '.';
     } else if (const auto *M = dyn_cast<CXXMethodDecl>(F)) {
-      print(OS, getThis(), S.getASTContext(),
-            S.getASTContext().getLValueReferenceType(
-                S.getASTContext().getCanonicalTagType(M->getParent())));
-      OS << ".";
+      print(OS, getThis(), S.getContext(),
+            ASTCtx.getLValueReferenceType(
+                ASTCtx.getCanonicalTagType(M->getParent())));
+      OS << '.';
     }
   }
 
-  F->getNameForDiagnostic(OS, PrintingPolicy,
-                          /*Qualified=*/false);
+  F->getNameForDiagnostic(OS, PrintingPolicy, /*Qualified=*/false);
   OS << '(';
   unsigned Off = 0;
-
+  unsigned ParamIndex = 0;
   Off += Func->hasRVO() ? primSize(PT_Ptr) : 0;
   Off += Func->hasThisPointer() ? primSize(PT_Ptr) : 0;
   llvm::ListSeparator Comma;
   for (const ParmVarDecl *Param :
        F->parameters().slice(ExplicitInstanceParam)) {
     OS << Comma;
-    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));
-    Off += align(primSize(PrimTy));
+    PrimType PrimT = Func->getParamDescriptor(ParamIndex).T;
+    TYPE_SWITCH(PrimT,
+                print(OS, stackRef<T>(Off), S.getContext(), Param->getType()));
+    Off += align(primSize(PrimT));
+    ++ParamIndex;
   }
-  OS << ")";
+  OS << ')';
 }
 
 SourceRange InterpFrame::getCallRange() const {

Instead of `classify()`ing the parameter types here, just use the saved
`PrimType` in the `ParamDescriptor`.

This also fixed an oddity with `interp::Context`: `Pointer::toRValue()`
takes an `interp::Context`, but some call sites passed an `ASTContext`
instead, which worked because of the implicit constructor. Make it
explicit.
@tbaederr tbaederr merged commit edfcac6 into llvm:main Jun 9, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:bytecode Issues for the clang bytecode constexpr interpreter clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant