clang 24.0.0git
InterpreterValuePrinter.cpp
Go to the documentation of this file.
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"
17#include "clang/AST/Type.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) {
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>(NonRefTy))
69 return DeclTypeToString(NonRefTy, TTy->getDecl());
70
71 if (const auto *TRy = dyn_cast<RecordType>(NonRefTy))
72 return DeclTypeToString(NonRefTy, 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(Ctx.getPrintingPolicy());
80
81 if (const auto *TDTy = dyn_cast<TypedefType>(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 //
90 if (llvm::isa<SubstTemplateTypeParmType>(SSDesugar) ||
91 llvm::isa<TemplateSpecializationType>(SSDesugar))
92 return GetFullTypeName(Ctx, Canon);
93 return DeclTypeToString(Canon, TDTy->getDecl());
94 }
95 return GetFullTypeName(Ctx, 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(Data, 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 }
117 AP.toString(APStr, /*Radix=*/10);
118 SS << " : " << QualTypeToString(Ctx, 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())
133 TLSD = cast<TopLevelStmtDecl>(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>(TLSD->getStmt())) {
139 const auto *Arg = InterfaceCall->getArg(/*Val*/ 3);
140 // Get rid of cast nodes.
141 while (const CastExpr *CastE = llvm::dyn_cast<CastExpr>(Arg))
142 Arg = CastE->getSubExpr();
143 if (const DeclRefExpr *DeclRefExp = llvm::dyn_cast<DeclRefExpr>(Arg))
144 FD = llvm::dyn_cast<FunctionDecl>(DeclRefExp->getDecl());
145
146 if (FD) {
147 SS << '\n';
148 const clang::FunctionDecl *FDef;
149 if (FD->hasBody(FDef))
150 FDef->print(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 {
184 ASTContext &Ctx = S.getASTContext();
185
186 QualType QT = V.getType();
187
188 if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(QT)) {
189 QualType ElemTy = CAT->getElementType();
190 size_t ElemCount = Ctx.getConstantArrayElementCount(CAT);
191 const Type *BaseTy = CAT->getBaseElementTypeUnsafe();
192 size_t ElemSize = Ctx.getTypeSizeInChars(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((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((void *)Offset, ElemSize);
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(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(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(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, V.getPtr());
317
318 if (NonRefTy->isFunctionType())
319 return FunctionToString(V, &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((char *)V.getPtr());
331
332 return VoidPtrToString(V.getPtr());
333 }
334
335 // Fall back to printing just the address of the unknown object.
336 return "@" + VoidPtrToString(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
352Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) const {
353 assert(CXXRD && "Cannot compile a destructor for a nullptr");
354 if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
355 return Dtor->getSecond();
356
357 if (CXXRD->hasIrrelevantDestructor())
358 return llvm::orc::ExecutorAddr{};
359
360 CXXDestructorDecl *DtorRD =
362
363 llvm::StringRef Name =
364 Act->getCodeGen()->GetMangledName(GlobalDecl(DtorRD, Dtor_Base));
365 auto AddrOrErr = getSymbolAddress(Name);
366 if (!AddrOrErr)
367 return AddrOrErr.takeError();
368
369 Dtors[CXXRD] = *AddrOrErr;
370 return AddrOrErr;
371}
372
374
376 : public TypeVisitor<InterfaceKindVisitor, InterfaceKind> {
377
378 Sema &S;
379 Expr *E;
381
382public:
384 : S(S), E(E), Args(Args) {}
385
389
390 InterfaceKind VisitRecordType(const RecordType *Ty) {
392 }
393
397
401
403 HandlePtrType(Ty);
405 }
406
408 HandlePtrType(Ty);
410 }
411
413 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf,
414 E->IgnoreImpCasts());
415 assert(!AddrOfE.isInvalid() && "Can not create unary expression");
416 Args.push_back(AddrOfE.get());
418 }
419
421 if (Ty->isNullPtrType())
422 Args.push_back(E);
423 else if (Ty->isFloatingType())
424 Args.push_back(E);
425 else if (Ty->isIntegralOrEnumerationType())
426 HandleIntegralOrEnumType(Ty);
427 // A void expression is not an argument of the call; convertExprToValue
428 // evaluates it before the call instead.
429
431 }
432
433 InterfaceKind VisitEnumType(const EnumType *Ty) {
434 HandleIntegralOrEnumType(Ty);
436 }
437
438private:
439 // Force cast these types to the uint that fits the register size. That way we
440 // reduce the number of overloads of `__clang_Interpreter_SetValueNoAlloc`.
441 void HandleIntegralOrEnumType(const Type *Ty) {
442 ASTContext &Ctx = S.getASTContext();
443 uint64_t PtrBits = Ctx.getTypeSize(Ctx.VoidPtrTy);
444 QualType UIntTy = Ctx.getBitIntType(/*Unsigned=*/true, PtrBits);
445 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(UIntTy);
446 ExprResult CastedExpr =
448 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
449 Args.push_back(CastedExpr.get());
450 }
451
452 void HandlePtrType(const Type *Ty) {
453 ASTContext &Ctx = S.getASTContext();
455 ExprResult CastedExpr =
457 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
458 Args.push_back(CastedExpr.get());
459 }
460};
461
462static constexpr llvm::StringRef VPName[] = {
463 "__clang_Interpreter_SetValueNoAlloc",
464 "__clang_Interpreter_SetValueWithAlloc",
465 "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
466
467// This synthesizes a call expression to a speciall
468// function that is responsible for generating the Value.
469// In general, we transform c++:
470// clang-repl> x
471// To:
472// // 1. If x is a built-in type like int, float.
473// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
474// // 2. If x is a struct, and a lvalue.
475// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
476// &x);
477// // 3. If x is a struct, but a rvalue.
478// new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
479// xQualType)) (x);
480llvm::Expected<Expr *> Interpreter::convertExprToValue(Expr *E) {
482 ASTContext &Ctx = S.getASTContext();
483
484 // Find the value printing builtins.
485 if (!ValuePrintingInfo[0]) {
486 assert(llvm::all_of(ValuePrintingInfo, [](Expr *E) { return !E; }));
487
488 auto LookupInterface = [&](Expr *&Interface,
489 llvm::StringRef Name) -> llvm::Error {
490 LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
494 if (R.empty())
495 return llvm::make_error<llvm::StringError>(
496 Name + " not found!", llvm::inconvertibleErrorCode());
497
498 CXXScopeSpec CSS;
499 Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
500 return llvm::Error::success();
501 };
502 if (llvm::Error Err =
503 LookupInterface(ValuePrintingInfo[NoAlloc], VPName[NoAlloc]))
504 return std::move(Err);
505
506 if (llvm::Error Err =
507 LookupInterface(ValuePrintingInfo[CopyArray], VPName[CopyArray]))
508 return std::move(Err);
509
510 if (llvm::Error Err =
511 LookupInterface(ValuePrintingInfo[WithAlloc], VPName[WithAlloc]))
512 return std::move(Err);
513
514 if (Ctx.getLangOpts().CPlusPlus) {
515 if (llvm::Error Err =
516 LookupInterface(ValuePrintingInfo[NewTag], VPName[NewTag]))
517 return std::move(Err);
518 }
519 }
520
521 llvm::SmallVector<Expr *, 4> AdjustedArgs;
522 // Create parameter `ThisInterp`.
523 AdjustedArgs.push_back(CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this));
524
525 // Create parameter `OutVal`.
526 AdjustedArgs.push_back(
527 CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue));
528
529 // Build `__clang_Interpreter_SetValue*` call.
530
531 // Get rid of ExprWithCleanups; it is put back around the result below.
532 Expr *FullExpr = E;
533 auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E);
534 if (EWC)
535 E = EWC->getSubExpr();
536
537 QualType Ty = E->IgnoreImpCasts()->getType();
538 QualType DesugaredTy = Ty.getDesugaredType(Ctx);
539
540 // For lvalue struct, we treat it as a reference.
541 if (DesugaredTy->isRecordType() && E->IgnoreImpCasts()->isLValue()) {
542 DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy);
543 Ty = Ctx.getLValueReferenceType(Ty);
544 }
545
546 Expr *TypeArg =
548 // The QualType parameter `OpaqueType`, represented as `void*`.
549 AdjustedArgs.push_back(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(DesugaredTy);
557 switch (Kind) {
559 [[fallthrough]];
561 // __clang_Interpreter_SetValueWithAlloc.
562 ExprResult AllocCall =
563 S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::WithAlloc],
564 E->getBeginLoc(), AdjustedArgs, E->getEndLoc());
565 if (AllocCall.isInvalid())
566 return llvm::make_error<llvm::StringError>(
567 "Cannot call to " + VPName[WithAlloc],
568 llvm::inconvertibleErrorCode());
569
570 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
571
572 // Force CodeGen to emit destructor.
573 if (auto *RD = Ty->getAsCXXRecordDecl()) {
574 auto *Dtor = S.LookupDestructor(RD);
575 Dtor->addAttr(UsedAttr::CreateImplicit(Ctx));
577 DeclGroupRef(Dtor));
578 }
579
580 // __clang_Interpreter_SetValueCopyArr.
581 if (Kind == InterfaceKind::CopyArray) {
582 const auto *CATy = cast<ConstantArrayType>(DesugaredTy.getTypePtr());
583 size_t ArrSize = Ctx.getConstantArrayElementCount(CATy);
584
585 if (!Ctx.getLangOpts().CPlusPlus)
586 ArrSize *= Ctx.getTypeSizeInChars(CATy->getBaseElementTypeUnsafe())
587 .getQuantity();
588
589 Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize);
590 Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
591 SetValueE =
592 S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::CopyArray],
593 SourceLocation(), Args, SourceLocation());
594 if (SetValueE.isInvalid())
595 return llvm::make_error<llvm::StringError>(
596 "Cannot call to " + VPName[CopyArray],
597 llvm::inconvertibleErrorCode());
598 break;
599 }
600 Expr *Args[] = {AllocCall.get(), ValuePrintingInfo[InterfaceKind::NewTag]};
601 ExprResult CXXNewCall = S.BuildCXXNew(
602 E->getSourceRange(),
603 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
604 /*PlacementRParen=*/SourceLocation(),
605 /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
606 E->getSourceRange(), E);
607
608 if (CXXNewCall.isInvalid())
609 return llvm::make_error<llvm::StringError>(
610 "Cannot build a call to placement new",
611 llvm::inconvertibleErrorCode());
612
613 SetValueE = S.ActOnFinishFullExpr(CXXNewCall.get(),
614 /*DiscardedValue=*/false);
615 break;
616 }
617 // __clang_Interpreter_SetValueNoAlloc.
619 SetValueE =
620 S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::NoAlloc],
621 E->getBeginLoc(), AdjustedArgs, E->getEndLoc());
622 // A void expression must still be evaluated:
623 // `(E, __clang_Interpreter_SetValueNoAlloc(...))`.
624 if (DesugaredTy->isVoidType() && !SetValueE.isInvalid())
625 SetValueE =
626 S.CreateBuiltinBinOp(E->getEndLoc(), BO_Comma, E, SetValueE.get());
627 break;
628 }
629 default:
630 llvm_unreachable("Unhandled InterfaceKind");
631 }
632
633 // It could fail, like printing an array type in C. (not supported)
634 if (SetValueE.isInvalid())
635 return FullExpr;
636
637 // The temporaries of E must be destroyed at the end of the statement.
638 // Without the cleanups, CodeGen destroys them at the end of the function
639 // running the top-level statements, which it finishes after emitting the
640 // deferred declarations: their destructors would not be emitted.
641 Expr *Result = SetValueE.get();
642 if (EWC && !isa<ExprWithCleanups>(Result))
644 Ctx, Result, EWC->cleanupsHaveSideEffects(), EWC->getObjects());
645 return Result;
646}
647
648} // namespace clang
649
650using namespace clang;
651
652// Temporary rvalue struct that need special care.
653extern "C" {
656 void *OpaqueType) {
657 Value &VRef = *(Value *)OutVal;
658 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
659 return VRef.getPtr();
660}
661
663__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
664 ...) {
665 Value &VRef = *(Value *)OutVal;
666 Interpreter *I = static_cast<Interpreter *>(This);
667 VRef = Value(I, OpaqueType);
668 if (VRef.isVoid())
669 return;
670
671 va_list args;
672 va_start(args, /*last named param*/ OpaqueType);
673
674 QualType QT = VRef.getType();
675 if (VRef.getKind() == Value::K_PtrOrObj) {
676 VRef.setPtr(va_arg(args, void *));
677 } else {
678 if (const auto *ED = QT->getAsEnumDecl())
679 QT = ED->getIntegerType();
680 switch (QT->castAs<BuiltinType>()->getKind()) {
681 default:
682 llvm_unreachable("unknown type kind!");
683 break;
684 // Types shorter than int are resolved as int, else va_arg has UB.
685 case BuiltinType::Bool:
686 VRef.setBool(va_arg(args, int));
687 break;
688 case BuiltinType::Char_S:
689 VRef.setChar_S(va_arg(args, int));
690 break;
691 case BuiltinType::SChar:
692 VRef.setSChar(va_arg(args, int));
693 break;
694 case BuiltinType::Char_U:
695 VRef.setChar_U(va_arg(args, unsigned));
696 break;
697 case BuiltinType::UChar:
698 VRef.setUChar(va_arg(args, unsigned));
699 break;
700 case BuiltinType::Short:
701 VRef.setShort(va_arg(args, int));
702 break;
703 case BuiltinType::UShort:
704 VRef.setUShort(va_arg(args, unsigned));
705 break;
706 case BuiltinType::Int:
707 VRef.setInt(va_arg(args, int));
708 break;
709 case BuiltinType::UInt:
710 VRef.setUInt(va_arg(args, unsigned));
711 break;
712 case BuiltinType::Long:
713 VRef.setLong(va_arg(args, long));
714 break;
715 case BuiltinType::ULong:
716 VRef.setULong(va_arg(args, unsigned long));
717 break;
718 case BuiltinType::LongLong:
719 VRef.setLongLong(va_arg(args, long long));
720 break;
721 case BuiltinType::ULongLong:
722 VRef.setULongLong(va_arg(args, unsigned long long));
723 break;
724 // Types shorter than double are resolved as double, else va_arg has UB.
725 case BuiltinType::Float:
726 VRef.setFloat(va_arg(args, double));
727 break;
728 case BuiltinType::Double:
729 VRef.setDouble(va_arg(args, double));
730 break;
731 case BuiltinType::LongDouble:
732 VRef.setLongDouble(va_arg(args, long double));
733 break;
734 // See REPL_BUILTIN_TYPES.
735 }
736 }
737 va_end(args);
738}
739}
740
741// A trampoline to work around the fact that operator placement new cannot
742// really be forward declared due to libc++ and libstdc++ declaration mismatch.
743// FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
744// definition in the interpreter runtime. We should move it in a runtime header
745// which gets included by the interpreter and here.
748operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
749 // Just forward to the standard operator placement new.
750 return operator new(__sz, __p);
751}
Defines the clang::ASTContext interface.
#define V(N, I)
unsigned IsFirst
Indicates that this is the first token of the file.
Result
Implement __builtin_bit_cast and related operations.
static std::string EnumToString(const Value &V)
static std::string QualTypeToString(ASTContext &Ctx, QualType QT)
REPL_EXTERNAL_VISIBILITY void * __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, void *OpaqueType)
static std::string FunctionToString(const Value &V, const void *Ptr)
static std::string VoidPtrToString(const void *Ptr)
REPL_EXTERNAL_VISIBILITY void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,...)
static std::string DeclTypeToString(const QualType &QT, NamedDecl *D)
static std::string CharPtrToString(const char *Ptr)
#define X(type, name)
Definition Value.h:97
#define REPL_EXTERNAL_VISIBILITY
Definition Value.h:74
Defines the clang::Preprocessor interface.
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
C Language Family Type Representation.
#define va_arg(ap, type)
#define va_start(ap, param)
#define va_end(ap)
__builtin_va_list va_list
static __inline__ uint32_t volatile uint32_t * __p
Definition arm_acle.h:57
a trap message and trap category.
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
TranslationUnitDecl * getTranslationUnitDecl() const
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CanQualType VoidPtrTy
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
IdentifierTable & Idents
Definition ASTContext.h:856
const LangOptions & getLangOpts() const
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
const clang::PrintingPolicy & getPrintingPolicy() const
Definition ASTContext.h:909
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const
Make an APSInt of the appropriate width and signedness for the given Value and integer Type.
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) constant array elements.
QualType getBitIntType(bool Unsigned, unsigned NumBits) const
Return a bit-precise integer type with the specified signedness and bit count.
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
This class is used for builtin types like 'int'.
Definition TypeBase.h:3245
Kind getKind() const
Definition TypeBase.h:3299
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool hasIrrelevantDestructor() const
Determine whether this class has a destructor which has no semantic effect.
Definition DeclCXX.h:1418
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3724
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Definition CharUnits.h:155
ASTConsumer & getASTConsumer() const
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3858
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
decl_range noload_decls() const
noload_decls_begin/end - Iterate over the declarations stored in this context that are currently load...
Definition DeclBase.h:2425
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1294
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
static ExprWithCleanups * Create(const ASTContext &C, EmptyShell empty, unsigned numObjects)
Definition ExprCXX.cpp:1496
This represents one expression.
Definition Expr.h:113
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:285
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3109
QualType getType() const
Definition Expr.h:145
Represents a function declaration or definition.
Definition Decl.h:2059
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3191
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4612
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
InterfaceKind VisitConstantArrayType(const ConstantArrayType *Ty)
InterfaceKind computeInterfaceKind(QualType Ty)
InterfaceKind VisitReferenceType(const ReferenceType *Ty)
InterfaceKind VisitPointerType(const PointerType *Ty)
InterfaceKind VisitEnumType(const EnumType *Ty)
InterfaceKind VisitBuiltinType(const BuiltinType *Ty)
InterfaceKind VisitFunctionType(const FunctionType *Ty)
InterfaceKind VisitRecordType(const RecordType *Ty)
InterfaceKind VisitMemberPointerType(const MemberPointerType *Ty)
InterfaceKindVisitor(Sema &S, Expr *E, llvm::SmallVectorImpl< Expr * > &Args)
Provides top-level interfaces for incremental compilation and execution.
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(GlobalDecl GD) const
const CompilerInstance * getCompilerInstance() const
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3751
This represents a decl that may have a name.
Definition Decl.h:275
std::string getQualifiedNameAsString() const
Definition Decl.cpp:1682
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3403
A (possibly-)qualified type.
Definition TypeBase.h:938
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8535
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition TypeBase.h:1312
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8446
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8486
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8631
QualType getCanonicalType() const
Definition TypeBase.h:8498
void * getAsOpaquePtr() const
Definition TypeBase.h:985
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1348
std::string getAsString() const
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3678
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:863
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9494
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
ASTContext & getASTContext() const
Definition Sema.h:935
CXXDestructorDecl * LookupDestructor(CXXRecordDecl *Class)
Look for the destructor of the given class.
ExprResult BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, QualType AllocType, TypeSourceInfo *AllocTypeInfo, std::optional< Expr * > ArraySize, SourceRange DirectInitRange, Expr *Initializer)
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr)
ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8812
Encodes a location in the source.
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:367
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
A declaration that models statements at global scope.
Definition Decl.h:4774
A container of type source information.
Definition TypeBase.h:8417
QualType getType() const
Return the type wrapped by this type source info.
Definition TypeBase.h:8428
An operation on a type.
Definition TypeVisitor.h:64
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isVoidType() const
Definition TypeBase.h:9068
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isCharType() const
Definition Type.cpp:2319
QualType getLocallyUnqualifiedSingleStepDesugaredType() const
Pull a single level of sugar off of this locally-unqualified type.
Definition Type.cpp:645
bool isFunctionPointerType() const
Definition TypeBase.h:8750
bool isPointerType() const
Definition TypeBase.h:8683
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9366
bool isReferenceType() const
Definition TypeBase.h:8707
bool isEnumeralType() const
Definition TypeBase.h:8814
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9194
bool isBuiltinType() const
Helper methods to distinguish type categories.
Definition TypeBase.h:8806
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Definition TypeBase.h:9252
bool isMemberPointerType() const
Definition TypeBase.h:8764
bool isFunctionProtoType() const
Definition TypeBase.h:2665
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
bool isFunctionType() const
Definition TypeBase.h:8679
bool isFloatingType() const
Definition Type.cpp:2517
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
bool isNullPtrType() const
Definition TypeBase.h:9109
bool isRecordType() const
Definition TypeBase.h:8810
QualType getType() const
Definition Value.cpp:238
void setRawBits(void *Ptr, unsigned NBytes=sizeof(Storage))
Copy NBytes bytes from Ptr into the raw storage.
Definition Value.cpp:233
Value()=default
void * getPtr() const
Definition Value.cpp:228
bool IsManuallyAlloc
Definition Value.h:204
void setPtr(void *Ptr)
Definition Value.h:142
Kind getKind() const
Definition Value.h:137
bool isVoid() const
Definition Value.h:134
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
std::string GetFullTypeName(ASTContext &Ctx, QualType QT)
@ Result
The result type of a method or function.
Definition TypeBase.h:906
IntegerLiteral * IntegerLiteralExpr(ASTContext &C, uint64_t Val)
@ Dtor_Base
Base object dtor.
Definition ABI.h:37
Expr * CStyleCastPtrExpr(Sema &S, QualType Ty, Expr *E)
U cast(CodeGen::Address addr)
Definition Address.h:327
static constexpr llvm::StringRef VPName[]
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
Definition TypeBase.h:6019
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
long int64_t
__DEVICE__ bool isnan(float __x)
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
__DEVICE__ bool isinf(float __x)
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
Describes how types, statements, expressions, and declarations should be printed.
unsigned SuppressUnwrittenScope
Suppress printing parts of scope specifiers that are never written, e.g., for anonymous namespaces.
unsigned SuppressDefaultTemplateArgs
When true, attempt to suppress template arguments that match the default argument for the parameter.
unsigned SplitTemplateClosers
Whether nested templates must be closed like 'a<b<c> >' rather than 'a<b<c>>'.
ValueRef(const Interpreter *In, void *Ty)