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->getOriginalDecl());
70
71 if (const auto *TRy = dyn_cast<RecordType>(NonRefTy))
72 return DeclTypeToString(NonRefTy, TRy->getOriginalDecl());
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())
133 if (isa<TopLevelStmtDecl>(D))
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
388 return Visit(Ty.getTypePtr());
389 }
390
393 }
394
397 }
398
401 }
402
404 HandlePtrType(Ty);
406 }
407
409 HandlePtrType(Ty);
411 }
412
414 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E);
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 else if (Ty->isVoidType()) {
428 // Do we need to still run `E`?
429 }
430
432 }
433
435 HandleIntegralOrEnumType(Ty);
437 }
438
439private:
440 // Force cast these types to the uint that fits the register size. That way we
441 // reduce the number of overloads of `__clang_Interpreter_SetValueNoAlloc`.
442 void HandleIntegralOrEnumType(const Type *Ty) {
443 ASTContext &Ctx = S.getASTContext();
444 uint64_t PtrBits = Ctx.getTypeSize(Ctx.VoidPtrTy);
445 QualType UIntTy = Ctx.getBitIntType(/*Unsigned=*/true, PtrBits);
446 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(UIntTy);
447 ExprResult CastedExpr =
449 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
450 Args.push_back(CastedExpr.get());
451 }
452
453 void HandlePtrType(const Type *Ty) {
454 ASTContext &Ctx = S.getASTContext();
456 ExprResult CastedExpr =
458 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
459 Args.push_back(CastedExpr.get());
460 }
461};
462
463static constexpr llvm::StringRef VPName[] = {
464 "__clang_Interpreter_SetValueNoAlloc",
465 "__clang_Interpreter_SetValueWithAlloc",
466 "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
467
468// This synthesizes a call expression to a speciall
469// function that is responsible for generating the Value.
470// In general, we transform c++:
471// clang-repl> x
472// To:
473// // 1. If x is a built-in type like int, float.
474// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
475// // 2. If x is a struct, and a lvalue.
476// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
477// &x);
478// // 3. If x is a struct, but a rvalue.
479// new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
480// xQualType)) (x);
481llvm::Expected<Expr *> Interpreter::convertExprToValue(Expr *E) {
483 ASTContext &Ctx = S.getASTContext();
484
485 // Find the value printing builtins.
486 if (!ValuePrintingInfo[0]) {
487 assert(llvm::all_of(ValuePrintingInfo, [](Expr *E) { return !E; }));
488
489 auto LookupInterface = [&](Expr *&Interface,
490 llvm::StringRef Name) -> llvm::Error {
491 LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
493 RedeclarationKind::ForVisibleRedeclaration);
495 if (R.empty())
496 return llvm::make_error<llvm::StringError>(
497 Name + " not found!", llvm::inconvertibleErrorCode());
498
499 CXXScopeSpec CSS;
500 Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
501 return llvm::Error::success();
502 };
503 if (llvm::Error Err =
504 LookupInterface(ValuePrintingInfo[NoAlloc], VPName[NoAlloc]))
505 return std::move(Err);
506
507 if (llvm::Error Err =
508 LookupInterface(ValuePrintingInfo[CopyArray], VPName[CopyArray]))
509 return std::move(Err);
510
511 if (llvm::Error Err =
512 LookupInterface(ValuePrintingInfo[WithAlloc], VPName[WithAlloc]))
513 return std::move(Err);
514
515 if (Ctx.getLangOpts().CPlusPlus) {
516 if (llvm::Error Err =
517 LookupInterface(ValuePrintingInfo[NewTag], VPName[NewTag]))
518 return std::move(Err);
519 }
520 }
521
522 llvm::SmallVector<Expr *, 4> AdjustedArgs;
523 // Create parameter `ThisInterp`.
524 AdjustedArgs.push_back(CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this));
525
526 // Create parameter `OutVal`.
527 AdjustedArgs.push_back(
528 CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue));
529
530 // Build `__clang_Interpreter_SetValue*` call.
531
532 // Get rid of ExprWithCleanups.
533 if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
534 E = EWC->getSubExpr();
535
536 QualType Ty = E->IgnoreImpCasts()->getType();
537 QualType DesugaredTy = Ty.getDesugaredType(Ctx);
538
539 // For lvalue struct, we treat it as a reference.
540 if (DesugaredTy->isRecordType() && E->isLValue()) {
541 DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy);
542 Ty = Ctx.getLValueReferenceType(Ty);
543 }
544
545 Expr *TypeArg =
547 // The QualType parameter `OpaqueType`, represented as `void*`.
548 AdjustedArgs.push_back(TypeArg);
549
550 // We push the last parameter based on the type of the Expr. Note we need
551 // special care for rvalue struct.
552 InterfaceKindVisitor V(S, E, AdjustedArgs);
553 Scope *Scope = nullptr;
554 ExprResult SetValueE;
555 InterfaceKind Kind = V.computeInterfaceKind(DesugaredTy);
556 switch (Kind) {
558 LLVM_FALLTHROUGH;
560 // __clang_Interpreter_SetValueWithAlloc.
561 ExprResult AllocCall =
562 S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::WithAlloc],
563 E->getBeginLoc(), AdjustedArgs, E->getEndLoc());
564 if (AllocCall.isInvalid())
565 return llvm::make_error<llvm::StringError>(
566 "Cannot call to " + VPName[WithAlloc],
567 llvm::inconvertibleErrorCode());
568
570
571 // Force CodeGen to emit destructor.
572 if (auto *RD = Ty->getAsCXXRecordDecl()) {
573 auto *Dtor = S.LookupDestructor(RD);
574 Dtor->addAttr(UsedAttr::CreateImplicit(Ctx));
576 DeclGroupRef(Dtor));
577 }
578
579 // __clang_Interpreter_SetValueCopyArr.
580 if (Kind == InterfaceKind::CopyArray) {
581 const auto *CATy = cast<ConstantArrayType>(DesugaredTy.getTypePtr());
582 size_t ArrSize = Ctx.getConstantArrayElementCount(CATy);
583
584 if (!Ctx.getLangOpts().CPlusPlus)
585 ArrSize *= Ctx.getTypeSizeInChars(CATy->getBaseElementTypeUnsafe())
586 .getQuantity();
587
588 Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize);
589 Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
590 SetValueE =
591 S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::CopyArray],
592 SourceLocation(), Args, SourceLocation());
593 if (SetValueE.isInvalid())
594 return llvm::make_error<llvm::StringError>(
595 "Cannot call to " + VPName[CopyArray],
596 llvm::inconvertibleErrorCode());
597 break;
598 }
599 Expr *Args[] = {AllocCall.get(), ValuePrintingInfo[InterfaceKind::NewTag]};
600 ExprResult CXXNewCall = S.BuildCXXNew(
601 E->getSourceRange(),
602 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
603 /*PlacementRParen=*/SourceLocation(),
604 /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
605 E->getSourceRange(), E);
606
607 if (CXXNewCall.isInvalid())
608 return llvm::make_error<llvm::StringError>(
609 "Cannot build a call to placement new",
610 llvm::inconvertibleErrorCode());
611
612 SetValueE = S.ActOnFinishFullExpr(CXXNewCall.get(),
613 /*DiscardedValue=*/false);
614 break;
615 }
616 // __clang_Interpreter_SetValueNoAlloc.
618 SetValueE =
619 S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::NoAlloc],
620 E->getBeginLoc(), AdjustedArgs, E->getEndLoc());
621 break;
622 }
623 default:
624 llvm_unreachable("Unhandled InterfaceKind");
625 }
626
627 // It could fail, like printing an array type in C. (not supported)
628 if (SetValueE.isInvalid())
629 return E;
630
631 return SetValueE.get();
632}
633
634} // namespace clang
635
636using namespace clang;
637
638// Temporary rvalue struct that need special care.
639extern "C" {
642 void *OpaqueType) {
643 Value &VRef = *(Value *)OutVal;
644 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
645 return VRef.getPtr();
646}
647
649__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
650 ...) {
651 Value &VRef = *(Value *)OutVal;
652 Interpreter *I = static_cast<Interpreter *>(This);
653 VRef = Value(I, OpaqueType);
654 if (VRef.isVoid())
655 return;
656
657 va_list args;
658 va_start(args, /*last named param*/ OpaqueType);
659
660 QualType QT = VRef.getType();
661 if (VRef.getKind() == Value::K_PtrOrObj) {
662 VRef.setPtr(va_arg(args, void *));
663 } else {
664 if (const auto *ED = QT->getAsEnumDecl())
665 QT = ED->getIntegerType();
666 switch (QT->castAs<BuiltinType>()->getKind()) {
667 default:
668 llvm_unreachable("unknown type kind!");
669 break;
670 // Types shorter than int are resolved as int, else va_arg has UB.
671 case BuiltinType::Bool:
672 VRef.setBool(va_arg(args, int));
673 break;
674 case BuiltinType::Char_S:
675 VRef.setChar_S(va_arg(args, int));
676 break;
677 case BuiltinType::SChar:
678 VRef.setSChar(va_arg(args, int));
679 break;
680 case BuiltinType::Char_U:
681 VRef.setChar_U(va_arg(args, unsigned));
682 break;
683 case BuiltinType::UChar:
684 VRef.setUChar(va_arg(args, unsigned));
685 break;
686 case BuiltinType::Short:
687 VRef.setShort(va_arg(args, int));
688 break;
689 case BuiltinType::UShort:
690 VRef.setUShort(va_arg(args, unsigned));
691 break;
692 case BuiltinType::Int:
693 VRef.setInt(va_arg(args, int));
694 break;
695 case BuiltinType::UInt:
696 VRef.setUInt(va_arg(args, unsigned));
697 break;
698 case BuiltinType::Long:
699 VRef.setLong(va_arg(args, long));
700 break;
701 case BuiltinType::ULong:
702 VRef.setULong(va_arg(args, unsigned long));
703 break;
704 case BuiltinType::LongLong:
705 VRef.setLongLong(va_arg(args, long long));
706 break;
707 case BuiltinType::ULongLong:
708 VRef.setULongLong(va_arg(args, unsigned long long));
709 break;
710 // Types shorter than double are resolved as double, else va_arg has UB.
711 case BuiltinType::Float:
712 VRef.setFloat(va_arg(args, double));
713 break;
714 case BuiltinType::Double:
715 VRef.setDouble(va_arg(args, double));
716 break;
717 case BuiltinType::LongDouble:
718 VRef.setLongDouble(va_arg(args, long double));
719 break;
720 // See REPL_BUILTIN_TYPES.
721 }
722 }
723 va_end(args);
724}
725}
726
727// A trampoline to work around the fact that operator placement new cannot
728// really be forward declared due to libc++ and libstdc++ declaration mismatch.
729// FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
730// definition in the interpreter runtime. We should move it in a runtime header
731// which gets included by the interpreter and here.
734operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
735 // Just forward to the standard operator placement new.
736 return operator new(__sz, __p);
737}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3597
const Decl * D
Expr * E
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:145
#define REPL_EXTERNAL_VISIBILITY
Definition: Value.h:74
Defines the clang::Preprocessor interface.
const char * Data
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.
Definition: ASTConsumer.cpp:18
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1201
const ConstantArrayType * getAsConstantArrayType(QualType T) const
Definition: ASTContext.h:3056
CanQualType VoidPtrTy
Definition: ASTContext.h:1249
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:740
const LangOptions & getLangOpts() const
Definition: ASTContext.h:894
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:793
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
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.
Definition: ASTContext.h:3310
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
void setPrintingPolicy(const clang::PrintingPolicy &Policy)
Definition: ASTContext.h:797
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:3182
Kind getKind() const
Definition: TypeBase.h:3230
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2869
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
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:73
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3612
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:3776
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:1272
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
void addAttr(Attr *A)
Definition: DeclBase.cpp:1022
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: TypeBase.h:6522
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:3053
QualType getType() const
Definition: Expr.h:144
Represents a function declaration or definition.
Definition: Decl.h:1999
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:4478
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:57
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:86
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(GlobalDecl GD) const
const CompilerInstance * getCompilerInstance() const
Represents the results of name lookup.
Definition: Lookup.h:147
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: TypeBase.h:3669
This represents a decl that may have a name.
Definition: Decl.h:273
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: TypeBase.h:3346
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: TypeBase.h:8432
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:8343
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: TypeBase.h:8383
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:8528
QualType getCanonicalType() const
Definition: TypeBase.h:8395
void * getAsOpaquePtr() const
Definition: TypeBase.h:984
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: TypeBase.h:1332
std::string getAsString() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: TypeBase.h:6502
Base for LValueReferenceType and RValueReferenceType.
Definition: TypeBase.h:3589
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15759
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:9281
ASTContext & getASTContext() const
Definition: Sema.h:918
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)
Definition: SemaCast.cpp:3441
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
Definition: SemaExpr.cpp:3230
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.
Definition: SemaExpr.cpp:6520
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition: Sema.h:8599
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:358
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
A declaration that models statements at global scope.
Definition: Decl.h:4597
A container of type source information.
Definition: TypeBase.h:8314
QualType getType() const
Return the type wrapped by this type source info.
Definition: TypeBase.h:8325
An operation on a type.
Definition: TypeVisitor.h:64
InterfaceKind Visit(const Type *T)
Performs the operation associated with this visitor object.
Definition: TypeVisitor.h:68
The base class of the type hierarchy.
Definition: TypeBase.h:1833
bool isVoidType() const
Definition: TypeBase.h:8936
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:2136
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:8647
bool isPointerType() const
Definition: TypeBase.h:8580
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
bool isReferenceType() const
Definition: TypeBase.h:8604
bool isEnumeralType() const
Definition: TypeBase.h:8711
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:9054
bool isBuiltinType() const
Helper methods to distinguish type categories.
Definition: TypeBase.h:8703
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Definition: TypeBase.h:9109
bool isMemberPointerType() const
Definition: TypeBase.h:8661
bool isFunctionProtoType() const
Definition: TypeBase.h:2619
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition: Type.h:53
bool isFunctionType() const
Definition: TypeBase.h:8576
bool isFloatingType() const
Definition: Type.cpp:2308
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool isNullPtrType() const
Definition: TypeBase.h:8973
bool isRecordType() const
Definition: TypeBase.h:8707
QualType getType() const
Definition: Value.cpp:237
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
@ K_PtrOrObj
Definition: Value.h:111
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.
std::string GetFullTypeName(ASTContext &Ctx, QualType QT)
@ Result
The result type of a method or function.
IntegerLiteral * IntegerLiteralExpr(ASTContext &C, uint64_t Val)
@ Dtor_Base
Base object dtor.
Definition: ABI.h:36
Expr * CStyleCastPtrExpr(Sema &S, QualType Ty, Expr *E)
static constexpr llvm::StringRef VPName[]
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
long int64_t
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:34
__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.
Definition: PrettyPrinter.h:57
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)