1//===--- InterpreterValuePrinter.cpp - Value printing utils -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements routines for in-process value printing in clang-repl.
10//
11//===----------------------------------------------------------------------===//
12
13#include "IncrementalAction.h"
14#include "InterpreterUtils.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/PrettyPrinter.h"
17#include "clang/AST/Type.h"
18#include "clang/Frontend/CompilerInstance.h"
19#include "clang/Interpreter/Interpreter.h"
20#include "clang/Interpreter/Value.h"
21#include "clang/Lex/Preprocessor.h"
22#include "clang/Sema/Lookup.h"
23#include "clang/Sema/Sema.h"
24
25#include "llvm/Support/Error.h"
26#include "llvm/Support/raw_ostream.h"
27
28#include <cassert>
29#include <cmath>
30#include <cstdarg>
31#include <sstream>
32#include <string>
33
34#define DEBUG_TYPE "interp-value"
35
36using namespace clang;
37
38static std::string DeclTypeToString(const QualType &QT, NamedDecl *D) {
39 std::string Str;
40 llvm::raw_string_ostream SS(Str);
41 if (QT.hasQualifiers())
42 SS << QT.getQualifiers().getAsString() << " ";
43 SS << D->getQualifiedNameAsString();
44 return Str;
45}
46
47static std::string QualTypeToString(ASTContext &Ctx, QualType QT) {
48 PrintingPolicy Policy(Ctx.getPrintingPolicy());
49 // Print the Allocator in STL containers, for instance.
50 Policy.SuppressDefaultTemplateArgs = false;
51 Policy.SuppressUnwrittenScope = true;
52 // Print 'a<b<c> >' rather than 'a<b<c>>'.
53 Policy.SplitTemplateClosers = true;
54
55 struct LocalPrintingPolicyRAII {
56 ASTContext &Context;
57 PrintingPolicy Policy;
58
59 LocalPrintingPolicyRAII(ASTContext &Ctx, PrintingPolicy &PP)
60 : Context(Ctx), Policy(Ctx.getPrintingPolicy()) {
61 Context.setPrintingPolicy(PP);
62 }
63 ~LocalPrintingPolicyRAII() { Context.setPrintingPolicy(Policy); }
64 } X(Ctx, Policy);
65
66 const QualType NonRefTy = QT.getNonReferenceType();
67
68 if (const auto *TTy = llvm::dyn_cast<TagType>(Val: NonRefTy))
69 return DeclTypeToString(QT: NonRefTy, D: TTy->getDecl());
70
71 if (const auto *TRy = dyn_cast<RecordType>(Val: NonRefTy))
72 return DeclTypeToString(QT: NonRefTy, D: TRy->getDecl());
73
74 const QualType Canon = NonRefTy.getCanonicalType();
75
76 // FIXME: How a builtin type can be a function pointer type?
77 if (Canon->isBuiltinType() && !NonRefTy->isFunctionPointerType() &&
78 !NonRefTy->isMemberPointerType())
79 return Canon.getAsString(Policy: Ctx.getPrintingPolicy());
80
81 if (const auto *TDTy = dyn_cast<TypedefType>(Val: Canon)) {
82 // FIXME: TemplateSpecializationType & SubstTemplateTypeParmType checks
83 // are predominately to get STL containers to print nicer and might be
84 // better handled in GetFullyQualifiedName.
85 //
86 // std::vector<Type>::iterator is a TemplateSpecializationType
87 // std::vector<Type>::value_type is a SubstTemplateTypeParmType
88 //
89 QualType SSDesugar = TDTy->getLocallyUnqualifiedSingleStepDesugaredType();
90 if (llvm::isa<SubstTemplateTypeParmType>(Val: SSDesugar) ||
91 llvm::isa<TemplateSpecializationType>(Val: SSDesugar))
92 return GetFullTypeName(Ctx, QT: Canon);
93 return DeclTypeToString(QT: Canon, D: TDTy->getDecl());
94 }
95 return GetFullTypeName(Ctx, QT: Canon);
96}
97
98static std::string EnumToString(const Value &V) {
99 std::string Str;
100 llvm::raw_string_ostream SS(Str);
101 ASTContext &Ctx = const_cast<ASTContext &>(V.getASTContext());
102
103 uint64_t Data = V.convertTo<uint64_t>();
104 bool IsFirst = true;
105 llvm::APSInt AP = Ctx.MakeIntValue(Value: Data, Type: V.getType());
106
107 auto *ED = V.getType()->castAsEnumDecl();
108 for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; ++I) {
109 if (I->getInitVal() == AP) {
110 if (!IsFirst)
111 SS << " ? ";
112 SS << "(" + I->getQualifiedNameAsString() << ")";
113 IsFirst = false;
114 }
115 }
116 llvm::SmallString<64> APStr;
117 AP.toString(Str&: APStr, /*Radix=*/10);
118 SS << " : " << QualTypeToString(Ctx, QT: ED->getIntegerType()) << " " << APStr;
119 return Str;
120}
121
122static std::string FunctionToString(const Value &V, const void *Ptr) {
123 std::string Str;
124 llvm::raw_string_ostream SS(Str);
125 SS << "Function @" << Ptr;
126
127 const DeclContext *PTU = V.getASTContext().getTranslationUnitDecl();
128 // Find the last top-level-stmt-decl. This is a forward iterator but the
129 // partial translation unit should not be large.
130 const TopLevelStmtDecl *TLSD = nullptr;
131 for (const Decl *D : PTU->noload_decls())
132 if (isa<TopLevelStmtDecl>(Val: D))
133 TLSD = cast<TopLevelStmtDecl>(Val: D);
134
135 // Get __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void
136 // *OpaqueType, void *Val);
137 const FunctionDecl *FD = nullptr;
138 if (auto *InterfaceCall = llvm::dyn_cast<CallExpr>(Val: TLSD->getStmt())) {
139 const auto *Arg = InterfaceCall->getArg(/*Val*/ Arg: 3);
140 // Get rid of cast nodes.
141 while (const CastExpr *CastE = llvm::dyn_cast<CastExpr>(Val: Arg))
142 Arg = CastE->getSubExpr();
143 if (const DeclRefExpr *DeclRefExp = llvm::dyn_cast<DeclRefExpr>(Val: Arg))
144 FD = llvm::dyn_cast<FunctionDecl>(Val: DeclRefExp->getDecl());
145
146 if (FD) {
147 SS << '\n';
148 const clang::FunctionDecl *FDef;
149 if (FD->hasBody(Definition&: FDef))
150 FDef->print(Out&: SS);
151 }
152 }
153 return Str;
154}
155
156static std::string VoidPtrToString(const void *Ptr) {
157 std::string Str;
158 llvm::raw_string_ostream SS(Str);
159 SS << Ptr;
160 return Str;
161}
162
163static std::string CharPtrToString(const char *Ptr) {
164 if (!Ptr)
165 return "0";
166
167 std::string Result = "\"";
168 Result += Ptr;
169 Result += '"';
170 return Result;
171}
172
173namespace clang {
174
175struct ValueRef : public Value {
176 ValueRef(const Interpreter *In, void *Ty) : Value(In, Ty) {
177 // Tell the base class to not try to deallocate if it manages the value.
178 IsManuallyAlloc = false;
179 }
180};
181
182std::string Interpreter::ValueDataToString(const Value &V) const {
183 Sema &S = getCompilerInstance()->getSema();
184 ASTContext &Ctx = S.getASTContext();
185
186 QualType QT = V.getType();
187
188 if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(T: QT)) {
189 QualType ElemTy = CAT->getElementType();
190 size_t ElemCount = Ctx.getConstantArrayElementCount(CA: CAT);
191 const Type *BaseTy = CAT->getBaseElementTypeUnsafe();
192 size_t ElemSize = Ctx.getTypeSizeInChars(T: BaseTy).getQuantity();
193
194 // Treat null terminated char arrays as strings basically.
195 if (ElemTy->isCharType()) {
196 char last = *(char *)(((uintptr_t)V.getPtr()) + ElemCount * ElemSize - 1);
197 if (last == '\0')
198 return CharPtrToString(Ptr: (char *)V.getPtr());
199 }
200
201 std::string Result = "{ ";
202 for (unsigned Idx = 0, N = CAT->getZExtSize(); Idx < N; ++Idx) {
203 ValueRef InnerV = ValueRef(this, ElemTy.getAsOpaquePtr());
204 if (ElemTy->isBuiltinType()) {
205 // Single dim arrays, advancing.
206 uintptr_t Offset = (uintptr_t)V.getPtr() + Idx * ElemSize;
207 InnerV.setRawBits(Ptr: (void *)Offset, NBits: ElemSize * 8);
208 } else {
209 // Multi dim arrays, position to the next dimension.
210 size_t Stride = ElemCount / N;
211 uintptr_t Offset = ((uintptr_t)V.getPtr()) + Idx * Stride * ElemSize;
212 InnerV.setPtr((void *)Offset);
213 }
214
215 Result += ValueDataToString(V: InnerV);
216
217 // Skip the \0 if the char types
218 if (Idx < N - 1)
219 Result += ", ";
220 }
221 Result += " }";
222 return Result;
223 }
224
225 QualType DesugaredTy = QT.getDesugaredType(Context: Ctx);
226 QualType NonRefTy = DesugaredTy.getNonReferenceType();
227
228 // FIXME: Add support for user defined printers.
229 // LookupResult R = LookupUserDefined(S, QT);
230 // if (!R.empty())
231 // return CallUserSpecifiedPrinter(R, V);
232
233 // If it is a builtin type dispatch to the builtin overloads.
234 if (auto *BT = DesugaredTy.getCanonicalType()->getAs<BuiltinType>()) {
235
236 auto formatFloating = [](auto Val, char Suffix = '\0') -> std::string {
237 std::string Out;
238 llvm::raw_string_ostream SS(Out);
239
240 if (std::isnan(Val) || std::isinf(Val)) {
241 SS << llvm::format("%g", Val);
242 return SS.str();
243 }
244 if (Val == static_cast<decltype(Val)>(static_cast<int64_t>(Val)))
245 SS << llvm::format("%.1f", Val);
246 else if (std::abs(Val) < 1e-4 || std::abs(Val) > 1e6 || Suffix == 'f')
247 SS << llvm::format("%#.6g", Val);
248 else if (Suffix == 'L')
249 SS << llvm::format("%#.12Lg", Val);
250 else
251 SS << llvm::format("%#.8g", Val);
252
253 if (Suffix != '\0')
254 SS << Suffix;
255 return SS.str();
256 };
257
258 std::string Str;
259 llvm::raw_string_ostream SS(Str);
260 switch (BT->getKind()) {
261 default:
262 return "{ error: unknown builtin type '" + std::to_string(val: BT->getKind()) +
263 " '}";
264 case clang::BuiltinType::Bool:
265 SS << ((V.getBool()) ? "true" : "false");
266 return Str;
267 case clang::BuiltinType::Char_S:
268 SS << '\'' << V.getChar_S() << '\'';
269 return Str;
270 case clang::BuiltinType::SChar:
271 SS << '\'' << V.getSChar() << '\'';
272 return Str;
273 case clang::BuiltinType::Char_U:
274 SS << '\'' << V.getChar_U() << '\'';
275 return Str;
276 case clang::BuiltinType::UChar:
277 SS << '\'' << V.getUChar() << '\'';
278 return Str;
279 case clang::BuiltinType::Short:
280 SS << V.getShort();
281 return Str;
282 case clang::BuiltinType::UShort:
283 SS << V.getUShort();
284 return Str;
285 case clang::BuiltinType::Int:
286 SS << V.getInt();
287 return Str;
288 case clang::BuiltinType::UInt:
289 SS << V.getUInt();
290 return Str;
291 case clang::BuiltinType::Long:
292 SS << V.getLong();
293 return Str;
294 case clang::BuiltinType::ULong:
295 SS << V.getULong();
296 return Str;
297 case clang::BuiltinType::LongLong:
298 SS << V.getLongLong();
299 return Str;
300 case clang::BuiltinType::ULongLong:
301 SS << V.getULongLong();
302 return Str;
303 case clang::BuiltinType::Float:
304 return formatFloating(V.getFloat(), /*suffix=*/'f');
305
306 case clang::BuiltinType::Double:
307 return formatFloating(V.getDouble());
308
309 case clang::BuiltinType::LongDouble:
310 return formatFloating(V.getLongDouble(), /*suffix=*/'L');
311 }
312 }
313
314 if ((NonRefTy->isPointerType() || NonRefTy->isMemberPointerType()) &&
315 NonRefTy->getPointeeType()->isFunctionProtoType())
316 return FunctionToString(V, Ptr: V.getPtr());
317
318 if (NonRefTy->isFunctionType())
319 return FunctionToString(V, Ptr: &V);
320
321 if (NonRefTy->isEnumeralType())
322 return EnumToString(V);
323
324 if (NonRefTy->isNullPtrType())
325 return "nullptr\n";
326
327 // FIXME: Add support for custom printers in C.
328 if (NonRefTy->isPointerType()) {
329 if (NonRefTy->getPointeeType()->isCharType())
330 return CharPtrToString(Ptr: (char *)V.getPtr());
331
332 return VoidPtrToString(Ptr: V.getPtr());
333 }
334
335 // Fall back to printing just the address of the unknown object.
336 return "@" + VoidPtrToString(Ptr: V.getPtr());
337}
338
339std::string Interpreter::ValueTypeToString(const Value &V) const {
340 ASTContext &Ctx = const_cast<ASTContext &>(V.getASTContext());
341 QualType QT = V.getType();
342
343 std::string QTStr = QualTypeToString(Ctx, QT);
344
345 if (QT->isReferenceType())
346 QTStr += " &";
347
348 return QTStr;
349}
350
351llvm::Expected<llvm::orc::ExecutorAddr>
352Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) const {
353 assert(CXXRD && "Cannot compile a destructor for a nullptr");
354 if (auto Dtor = Dtors.find(Val: CXXRD); Dtor != Dtors.end())
355 return Dtor->getSecond();
356
357 if (CXXRD->hasIrrelevantDestructor())
358 return llvm::orc::ExecutorAddr{};
359
360 CXXDestructorDecl *DtorRD =
361 getCompilerInstance()->getSema().LookupDestructor(Class: CXXRD);
362
363 llvm::StringRef Name =
364 Act->getCodeGen()->GetMangledName(GD: GlobalDecl(DtorRD, Dtor_Base));
365 auto AddrOrErr = getSymbolAddress(IRName: Name);
366 if (!AddrOrErr)
367 return AddrOrErr.takeError();
368
369 Dtors[CXXRD] = *AddrOrErr;
370 return AddrOrErr;
371}
372
373enum InterfaceKind { NoAlloc, WithAlloc, CopyArray, NewTag };
374
375class InterfaceKindVisitor
376 : public TypeVisitor<InterfaceKindVisitor, InterfaceKind> {
377
378 Sema &S;
379 Expr *E;
380 llvm::SmallVectorImpl<Expr *> &Args;
381
382public:
383 InterfaceKindVisitor(Sema &S, Expr *E, llvm::SmallVectorImpl<Expr *> &Args)
384 : S(S), E(E), Args(Args) {}
385
386 InterfaceKind computeInterfaceKind(QualType Ty) {
387 return Visit(T: Ty.getTypePtr());
388 }
389
390 InterfaceKind VisitRecordType(const RecordType *Ty) {
391 return InterfaceKind::WithAlloc;
392 }
393
394 InterfaceKind VisitMemberPointerType(const MemberPointerType *Ty) {
395 return InterfaceKind::WithAlloc;
396 }
397
398 InterfaceKind VisitConstantArrayType(const ConstantArrayType *Ty) {
399 return InterfaceKind::CopyArray;
400 }
401
402 InterfaceKind VisitFunctionType(const FunctionType *Ty) {
403 HandlePtrType(Ty);
404 return InterfaceKind::NoAlloc;
405 }
406
407 InterfaceKind VisitPointerType(const PointerType *Ty) {
408 HandlePtrType(Ty);
409 return InterfaceKind::NoAlloc;
410 }
411
412 InterfaceKind VisitReferenceType(const ReferenceType *Ty) {
413 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(OpLoc: SourceLocation(), Opc: UO_AddrOf,
414 InputExpr: E->IgnoreImpCasts());
415 assert(!AddrOfE.isInvalid() && "Can not create unary expression");
416 Args.push_back(Elt: AddrOfE.get());
417 return InterfaceKind::NoAlloc;
418 }
419
420 InterfaceKind VisitBuiltinType(const BuiltinType *Ty) {
421 if (Ty->isNullPtrType())
422 Args.push_back(Elt: E);
423 else if (Ty->isFloatingType())
424 Args.push_back(Elt: E);
425 else if (Ty->isIntegralOrEnumerationType())
426 HandleIntegralOrEnumType(Ty);
427 else if (Ty->isVoidType()) {
428 // Do we need to still run `E`?
429 }
430
431 return InterfaceKind::NoAlloc;
432 }
433
434 InterfaceKind VisitEnumType(const EnumType *Ty) {
435 HandleIntegralOrEnumType(Ty);
436 return InterfaceKind::NoAlloc;
437 }
438
439private:
440 // Force cast these types to the uint that fits the register size. That way we
441 // reduce the number of overloads of `__clang_Interpreter_SetValueNoAlloc`.
442 void HandleIntegralOrEnumType(const Type *Ty) {
443 ASTContext &Ctx = S.getASTContext();
444 uint64_t PtrBits = Ctx.getTypeSize(T: Ctx.VoidPtrTy);
445 QualType UIntTy = Ctx.getBitIntType(/*Unsigned=*/true, NumBits: PtrBits);
446 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(T: UIntTy);
447 ExprResult CastedExpr =
448 S.BuildCStyleCastExpr(LParenLoc: SourceLocation(), Ty: TSI, RParenLoc: SourceLocation(), Op: E);
449 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
450 Args.push_back(Elt: CastedExpr.get());
451 }
452
453 void HandlePtrType(const Type *Ty) {
454 ASTContext &Ctx = S.getASTContext();
455 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(T: Ctx.VoidPtrTy);
456 ExprResult CastedExpr =
457 S.BuildCStyleCastExpr(LParenLoc: SourceLocation(), Ty: TSI, RParenLoc: SourceLocation(), Op: E);
458 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
459 Args.push_back(Elt: CastedExpr.get());
460 }
461};
462
463static constexpr llvm::StringRef VPName[] = {
464 "__clang_Interpreter_SetValueNoAlloc",
465 "__clang_Interpreter_SetValueWithAlloc",
466 "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
467
468// This synthesizes a call expression to a speciall
469// function that is responsible for generating the Value.
470// In general, we transform c++:
471// clang-repl> x
472// To:
473// // 1. If x is a built-in type like int, float.
474// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
475// // 2. If x is a struct, and a lvalue.
476// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
477// &x);
478// // 3. If x is a struct, but a rvalue.
479// new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
480// xQualType)) (x);
481llvm::Expected<Expr *> Interpreter::convertExprToValue(Expr *E) {
482 Sema &S = getCompilerInstance()->getSema();
483 ASTContext &Ctx = S.getASTContext();
484
485 // Find the value printing builtins.
486 if (!ValuePrintingInfo[0]) {
487 assert(llvm::all_of(ValuePrintingInfo, [](Expr *E) { return !E; }));
488
489 auto LookupInterface = [&](Expr *&Interface,
490 llvm::StringRef Name) -> llvm::Error {
491 LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
492 Sema::LookupOrdinaryName,
493 RedeclarationKind::ForVisibleRedeclaration);
494 S.LookupQualifiedName(R, LookupCtx: Ctx.getTranslationUnitDecl());
495 if (R.empty())
496 return llvm::make_error<llvm::StringError>(
497 Args: Name + " not found!", Args: llvm::inconvertibleErrorCode());
498
499 CXXScopeSpec CSS;
500 Interface = S.BuildDeclarationNameExpr(SS: CSS, R, /*ADL=*/NeedsADL: false).get();
501 return llvm::Error::success();
502 };
503 if (llvm::Error Err =
504 LookupInterface(ValuePrintingInfo[NoAlloc], VPName[NoAlloc]))
505 return std::move(Err);
506
507 if (llvm::Error Err =
508 LookupInterface(ValuePrintingInfo[CopyArray], VPName[CopyArray]))
509 return std::move(Err);
510
511 if (llvm::Error Err =
512 LookupInterface(ValuePrintingInfo[WithAlloc], VPName[WithAlloc]))
513 return std::move(Err);
514
515 if (Ctx.getLangOpts().CPlusPlus) {
516 if (llvm::Error Err =
517 LookupInterface(ValuePrintingInfo[NewTag], VPName[NewTag]))
518 return std::move(Err);
519 }
520 }
521
522 llvm::SmallVector<Expr *, 4> AdjustedArgs;
523 // Create parameter `ThisInterp`.
524 AdjustedArgs.push_back(Elt: CStyleCastPtrExpr(S, Ty: Ctx.VoidPtrTy, Ptr: (uintptr_t)this));
525
526 // Create parameter `OutVal`.
527 AdjustedArgs.push_back(
528 Elt: CStyleCastPtrExpr(S, Ty: Ctx.VoidPtrTy, Ptr: (uintptr_t)&LastValue));
529
530 // Build `__clang_Interpreter_SetValue*` call.
531
532 // Get rid of ExprWithCleanups.
533 if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(Val: E))
534 E = EWC->getSubExpr();
535
536 QualType Ty = E->IgnoreImpCasts()->getType();
537 QualType DesugaredTy = Ty.getDesugaredType(Context: Ctx);
538
539 // For lvalue struct, we treat it as a reference.
540 if (DesugaredTy->isRecordType() && E->IgnoreImpCasts()->isLValue()) {
541 DesugaredTy = Ctx.getLValueReferenceType(T: DesugaredTy);
542 Ty = Ctx.getLValueReferenceType(T: Ty);
543 }
544
545 Expr *TypeArg =
546 CStyleCastPtrExpr(S, Ty: Ctx.VoidPtrTy, Ptr: (uintptr_t)Ty.getAsOpaquePtr());
547 // The QualType parameter `OpaqueType`, represented as `void*`.
548 AdjustedArgs.push_back(Elt: TypeArg);
549
550 // We push the last parameter based on the type of the Expr. Note we need
551 // special care for rvalue struct.
552 InterfaceKindVisitor V(S, E, AdjustedArgs);
553 Scope *Scope = nullptr;
554 ExprResult SetValueE;
555 InterfaceKind Kind = V.computeInterfaceKind(Ty: DesugaredTy);
556 switch (Kind) {
557 case InterfaceKind::WithAlloc:
558 [[fallthrough]];
559 case InterfaceKind::CopyArray: {
560 // __clang_Interpreter_SetValueWithAlloc.
561 ExprResult AllocCall =
562 S.ActOnCallExpr(S: Scope, Fn: ValuePrintingInfo[InterfaceKind::WithAlloc],
563 LParenLoc: E->getBeginLoc(), ArgExprs: AdjustedArgs, RParenLoc: E->getEndLoc());
564 if (AllocCall.isInvalid())
565 return llvm::make_error<llvm::StringError>(
566 Args: "Cannot call to " + VPName[WithAlloc],
567 Args: llvm::inconvertibleErrorCode());
568
569 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(T: Ty, Loc: SourceLocation());
570
571 // Force CodeGen to emit destructor.
572 if (auto *RD = Ty->getAsCXXRecordDecl()) {
573 auto *Dtor = S.LookupDestructor(Class: RD);
574 Dtor->addAttr(A: UsedAttr::CreateImplicit(Ctx));
575 getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
576 D: DeclGroupRef(Dtor));
577 }
578
579 // __clang_Interpreter_SetValueCopyArr.
580 if (Kind == InterfaceKind::CopyArray) {
581 const auto *CATy = cast<ConstantArrayType>(Val: DesugaredTy.getTypePtr());
582 size_t ArrSize = Ctx.getConstantArrayElementCount(CA: CATy);
583
584 if (!Ctx.getLangOpts().CPlusPlus)
585 ArrSize *= Ctx.getTypeSizeInChars(T: CATy->getBaseElementTypeUnsafe())
586 .getQuantity();
587
588 Expr *ArrSizeExpr = IntegerLiteralExpr(C&: Ctx, Val: ArrSize);
589 Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
590 SetValueE =
591 S.ActOnCallExpr(S: Scope, Fn: ValuePrintingInfo[InterfaceKind::CopyArray],
592 LParenLoc: SourceLocation(), ArgExprs: Args, RParenLoc: SourceLocation());
593 if (SetValueE.isInvalid())
594 return llvm::make_error<llvm::StringError>(
595 Args: "Cannot call to " + VPName[CopyArray],
596 Args: llvm::inconvertibleErrorCode());
597 break;
598 }
599 Expr *Args[] = {AllocCall.get(), ValuePrintingInfo[InterfaceKind::NewTag]};
600 ExprResult CXXNewCall = S.BuildCXXNew(
601 Range: E->getSourceRange(),
602 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), PlacementArgs: Args,
603 /*PlacementRParen=*/SourceLocation(),
604 /*TypeIdParens=*/SourceRange(), AllocType: TSI->getType(), AllocTypeInfo: TSI, ArraySize: std::nullopt,
605 DirectInitRange: E->getSourceRange(), Initializer: E);
606
607 if (CXXNewCall.isInvalid())
608 return llvm::make_error<llvm::StringError>(
609 Args: "Cannot build a call to placement new",
610 Args: llvm::inconvertibleErrorCode());
611
612 SetValueE = S.ActOnFinishFullExpr(Expr: CXXNewCall.get(),
613 /*DiscardedValue=*/false);
614 break;
615 }
616 // __clang_Interpreter_SetValueNoAlloc.
617 case InterfaceKind::NoAlloc: {
618 SetValueE =
619 S.ActOnCallExpr(S: Scope, Fn: ValuePrintingInfo[InterfaceKind::NoAlloc],
620 LParenLoc: E->getBeginLoc(), ArgExprs: AdjustedArgs, RParenLoc: E->getEndLoc());
621 break;
622 }
623 default:
624 llvm_unreachable("Unhandled InterfaceKind");
625 }
626
627 // It could fail, like printing an array type in C. (not supported)
628 if (SetValueE.isInvalid())
629 return E;
630
631 return SetValueE.get();
632}
633
634} // namespace clang
635
636using namespace clang;
637
638// Temporary rvalue struct that need special care.
639extern "C" {
640REPL_EXTERNAL_VISIBILITY void *
641__clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal,
642 void *OpaqueType) {
643 Value &VRef = *(Value *)OutVal;
644 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
645 return VRef.getPtr();
646}
647
648REPL_EXTERNAL_VISIBILITY void
649__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
650 ...) {
651 Value &VRef = *(Value *)OutVal;
652 Interpreter *I = static_cast<Interpreter *>(This);
653 VRef = Value(I, OpaqueType);
654 if (VRef.isVoid())
655 return;
656
657 va_list args;
658 va_start(args, /*last named param*/ OpaqueType);
659
660 QualType QT = VRef.getType();
661 if (VRef.getKind() == Value::K_PtrOrObj) {
662 VRef.setPtr(va_arg(args, void *));
663 } else {
664 if (const auto *ED = QT->getAsEnumDecl())
665 QT = ED->getIntegerType();
666 switch (QT->castAs<BuiltinType>()->getKind()) {
667 default:
668 llvm_unreachable("unknown type kind!");
669 break;
670 // Types shorter than int are resolved as int, else va_arg has UB.
671 case BuiltinType::Bool:
672 VRef.setBool(va_arg(args, int));
673 break;
674 case BuiltinType::Char_S:
675 VRef.setChar_S(va_arg(args, int));
676 break;
677 case BuiltinType::SChar:
678 VRef.setSChar(va_arg(args, int));
679 break;
680 case BuiltinType::Char_U:
681 VRef.setChar_U(va_arg(args, unsigned));
682 break;
683 case BuiltinType::UChar:
684 VRef.setUChar(va_arg(args, unsigned));
685 break;
686 case BuiltinType::Short:
687 VRef.setShort(va_arg(args, int));
688 break;
689 case BuiltinType::UShort:
690 VRef.setUShort(va_arg(args, unsigned));
691 break;
692 case BuiltinType::Int:
693 VRef.setInt(va_arg(args, int));
694 break;
695 case BuiltinType::UInt:
696 VRef.setUInt(va_arg(args, unsigned));
697 break;
698 case BuiltinType::Long:
699 VRef.setLong(va_arg(args, long));
700 break;
701 case BuiltinType::ULong:
702 VRef.setULong(va_arg(args, unsigned long));
703 break;
704 case BuiltinType::LongLong:
705 VRef.setLongLong(va_arg(args, long long));
706 break;
707 case BuiltinType::ULongLong:
708 VRef.setULongLong(va_arg(args, unsigned long long));
709 break;
710 // Types shorter than double are resolved as double, else va_arg has UB.
711 case BuiltinType::Float:
712 VRef.setFloat(va_arg(args, double));
713 break;
714 case BuiltinType::Double:
715 VRef.setDouble(va_arg(args, double));
716 break;
717 case BuiltinType::LongDouble:
718 VRef.setLongDouble(va_arg(args, long double));
719 break;
720 // See REPL_BUILTIN_TYPES.
721 }
722 }
723 va_end(args);
724}
725}
726
727// A trampoline to work around the fact that operator placement new cannot
728// really be forward declared due to libc++ and libstdc++ declaration mismatch.
729// FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
730// definition in the interpreter runtime. We should move it in a runtime header
731// which gets included by the interpreter and here.
732struct __clang_Interpreter_NewTag {};
733REPL_EXTERNAL_VISIBILITY void *
734operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
735 // Just forward to the standard operator placement new.
736 return operator new(__sz, __p);
737}
738