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