Skip to content

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

Open
tbaederr wants to merge 1 commit into
llvm:mainfrom
tbaederr:param-print
Open

[clang][bytecode] Refactor backtrace param printing#202325
tbaederr wants to merge 1 commit into
llvm:mainfrom
tbaederr:param-print

Conversation

@tbaederr
Copy link
Copy Markdown
Contributor

@tbaederr tbaederr commented Jun 8, 2026

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.
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