clang 22.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>(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 //
90 if (llvm::isa<SubstTemplateTypeParmType>(SSDesugar))
91 return GetFullTypeName(Ctx, Canon);
92 else if (llvm::isa<TemplateSpecializationType>(SSDesugar))
93 return GetFullTypeName(Ctx, NonRefTy);
94 return DeclTypeToString(NonRefTy, TDTy->getDecl());
95 }
96 return GetFullTypeName(Ctx, 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(Data, 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 }
118 AP.toString(APStr, /*Radix=*/10);
119 SS << " : " << QualTypeToString(Ctx, 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())
134 TLSD = cast<TopLevelStmtDecl>(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>(TLSD->getStmt())) {
140 const auto *Arg = InterfaceCall->getArg(/*Val*/ 3);
141 // Get rid of cast nodes.
142 while (const CastExpr *CastE = llvm::dyn_cast<CastExpr>(Arg))
143 Arg = CastE->getSubExpr();
144 if (const DeclRefExpr *DeclRefExp = llvm::dyn_cast<DeclRefExpr>(Arg))
145 FD = llvm::dyn_cast<FunctionDecl>(DeclRefExp->getDecl());
146
147 if (FD) {
148 SS << '\n';
149 const clang::FunctionDecl *FDef;
150 if (FD->hasBody(FDef))
151 FDef->print(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 {
185 ASTContext &Ctx = S.getASTContext();
186
187 QualType QT = V.getType();
188
189 if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(QT)) {
190 QualType ElemTy = CAT->getElementType();
191 size_t ElemCount = Ctx.getConstantArrayElementCount(CAT);
192 const Type *BaseTy = CAT->getBaseElementTypeUnsafe();
193 size_t ElemSize = Ctx.getTypeSizeInChars(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((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((void *)Offset, 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(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(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(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, V.getPtr());
318
319 if (NonRefTy->isFunctionType())
320 return FunctionToString(V, &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((char *)V.getPtr());
332
333 return VoidPtrToString(V.getPtr());
334 }
335
336 // Fall back to printing just the address of the unknown object.
337 return "@" + VoidPtrToString(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
353Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) const {
354 assert(CXXRD && "Cannot compile a destructor for a nullptr");
355 if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
356 return Dtor->getSecond();
357
358 if (CXXRD->hasIrrelevantDestructor())
359 return llvm::orc::ExecutorAddr{};
360
361 CXXDestructorDecl *DtorRD =
363
364 llvm::StringRef Name =
365 Act->getCodeGen()->GetMangledName(GlobalDecl(DtorRD, Dtor_Base));
366 auto AddrOrErr = getSymbolAddress(Name);
367 if (!AddrOrErr)
368 return AddrOrErr.takeError();
369
370 Dtors[CXXRD] = *AddrOrErr;
371 return AddrOrErr;
372}
373
375
377 : public TypeVisitor<InterfaceKindVisitor, InterfaceKind> {
378
379 Sema &S;
380 Expr *E;
382
383public:
385 : S(S), E(E), Args(Args) {}
386
390
391 InterfaceKind VisitRecordType(const RecordType *Ty) {
393 }
394
398
402
404 HandlePtrType(Ty);
406 }
407
409 HandlePtrType(Ty);
411 }
412
414 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf,
415 E->IgnoreImpCasts());
416 assert(!AddrOfE.isInvalid() && "Can not create unary expression");
417 Args.push_back(AddrOfE.get());
419 }
420
422 if (Ty->isNullPtrType())
423 Args.push_back(E);
424 else if (Ty->isFloatingType())
425 Args.push_back(E);
426 else if (Ty->isIntegralOrEnumerationType())
427 HandleIntegralOrEnumType(Ty);
428 else if (Ty->isVoidType()) {
429 // Do we need to still run `E`?
430 }
431
433 }
434
435 InterfaceKind VisitEnumType(const EnumType *Ty) {
436 HandleIntegralOrEnumType(Ty);
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(Ctx.VoidPtrTy);
446 QualType UIntTy = Ctx.getBitIntType(/*Unsigned=*/true, PtrBits);
447 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(UIntTy);
448 ExprResult CastedExpr =
450 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
451 Args.push_back(CastedExpr.get());
452 }
453
454 void HandlePtrType(const Type *Ty) {
455 ASTContext &Ctx = S.getASTContext();
457 ExprResult CastedExpr =
459 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
460 Args.push_back(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) {
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(),
496 if (R.empty())
497 return llvm::make_error<llvm::StringError>(
498 Name + " not found!", llvm::inconvertibleErrorCode());
499
500 CXXScopeSpec CSS;
501 Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/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(CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this));
526
527 // Create parameter `OutVal`.
528 AdjustedArgs.push_back(
529 CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (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>(E))
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 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" {
643 void *OpaqueType) {
644 Value &VRef = *(Value *)OutVal;
645 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
646 return VRef.getPtr();
647}
648
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.
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}
Defines the clang::ASTContext interface.
#define V(N, I)
unsigned IsFirst
Indicates that this is the first token of the file.
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:220
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:772
const LangOptions & getLangOpts() const
Definition ASTContext.h:926
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:825
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.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of 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:3164
Kind getKind() const
Definition TypeBase.h:3212
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:1402
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3610
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
ASTConsumer & getASTConsumer() const
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3760
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
decl_range noload_decls() const
noload_decls_begin/end - Iterate over the declarations stored in this context that are currently load...
Definition DeclBase.h:2381
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void addAttr(Attr *A)
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
This represents one expression.
Definition Expr.h:112
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:284
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3065
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:2000
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3188
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4450
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.
Definition Interpreter.h:91
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:3653
This represents a decl that may have a name.
Definition Decl.h:274
std::string getQualifiedNameAsString() const
Definition Decl.cpp:1680
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3328
A (possibly-)qualified type.
Definition TypeBase.h:937
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8367
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition TypeBase.h:1296
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8278
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8318
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:8463
QualType getCanonicalType() const
Definition TypeBase.h:8330
void * getAsOpaquePtr() const
Definition TypeBase.h:984
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1332
std::string getAsString() const
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3573
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9297
ASTContext & getASTContext() const
Definition Sema.h:925
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:8615
Encodes a location in the source.
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:362
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:350
A declaration that models statements at global scope.
Definition Decl.h:4617
A container of type source information.
Definition TypeBase.h:8249
QualType getType() const
Return the type wrapped by this type source info.
Definition TypeBase.h:8260
An operation on a type.
Definition TypeVisitor.h:64
The base class of the type hierarchy.
Definition TypeBase.h:1833
bool isVoidType() const
Definition TypeBase.h:8871
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:2132
QualType getLocallyUnqualifiedSingleStepDesugaredType() const
Pull a single level of sugar off of this locally-unqualified type.
Definition Type.cpp:521
bool isFunctionPointerType() const
Definition TypeBase.h:8582
bool isPointerType() const
Definition TypeBase.h:8515
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9158
bool isReferenceType() const
Definition TypeBase.h:8539
bool isEnumeralType() const
Definition TypeBase.h:8646
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:8989
bool isBuiltinType() const
Helper methods to distinguish type categories.
Definition TypeBase.h:8638
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Definition TypeBase.h:9044
bool isMemberPointerType() const
Definition TypeBase.h:8596
bool isFunctionProtoType() const
Definition TypeBase.h:2601
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
bool isFunctionType() const
Definition TypeBase.h:8511
bool isFloatingType() const
Definition Type.cpp:2304
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
bool isNullPtrType() const
Definition TypeBase.h:8908
bool isRecordType() const
Definition TypeBase.h:8642
QualType getType() const
Definition Value.cpp:237
Value()=default
void * getPtr() const
Definition Value.cpp:227
bool IsManuallyAlloc
Definition Value.h:201
void setRawBits(void *Ptr, unsigned NBits=sizeof(Storage))
Definition Value.cpp:232
void setPtr(void *Ptr)
Definition Value.h:142
Kind getKind() const
Definition Value.h:137
bool isVoid() const
Definition Value.h:134
The JSON file list parser is used to communicate input to InstallAPI.
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:905
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:5858
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)