clang 23.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 * 8);
208 } else {
209 // Multi dim arrays, position to the next dimension.
210 size_t Stride = ElemCount / N;
211 uintptr_t Offset = ((uintptr_t)V.getPtr()) + Idx * Stride * ElemSize;
212 InnerV.setPtr((void *)Offset);
213 }
214
215 Result += ValueDataToString(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 else if (Ty->isVoidType()) {
428 // Do we need to still run `E`?
429 }
430
432 }
433
434 InterfaceKind VisitEnumType(const EnumType *Ty) {
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(),
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->IgnoreImpCasts()->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 [[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
569 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
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)
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:226
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:798
const LangOptions & getLangOpts() const
Definition ASTContext.h:952
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:851
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:3214
Kind getKind() const
Definition TypeBase.h:3262
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:1408
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3679
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:3810
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1462
decl_range noload_decls() const
noload_decls_begin/end - Iterate over the declarations stored in this context that are currently load...
Definition DeclBase.h:2394
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1273
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:3070
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:2015
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3201
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4553
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:98
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:3703
This represents a decl that may have a name.
Definition Decl.h:274
std::string getQualifiedNameAsString() const
Definition Decl.cpp:1681
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3378
A (possibly-)qualified type.
Definition TypeBase.h:937
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8520
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition TypeBase.h:1302
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8431
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8471
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:8616
QualType getCanonicalType() const
Definition TypeBase.h:8483
void * getAsOpaquePtr() const
Definition TypeBase.h:984
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1338
std::string getAsString() const
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3623
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9415
ASTContext & getASTContext() const
Definition Sema.h:939
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:8743
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:4652
A container of type source information.
Definition TypeBase.h:8402
QualType getType() const
Return the type wrapped by this type source info.
Definition TypeBase.h:8413
An operation on a type.
Definition TypeVisitor.h:64
The base class of the type hierarchy.
Definition TypeBase.h:1866
bool isVoidType() const
Definition TypeBase.h:9034
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:2158
QualType getLocallyUnqualifiedSingleStepDesugaredType() const
Pull a single level of sugar off of this locally-unqualified type.
Definition Type.cpp:523
bool isFunctionPointerType() const
Definition TypeBase.h:8735
bool isPointerType() const
Definition TypeBase.h:8668
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9328
bool isReferenceType() const
Definition TypeBase.h:8692
bool isEnumeralType() const
Definition TypeBase.h:8799
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:754
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9156
bool isBuiltinType() const
Helper methods to distinguish type categories.
Definition TypeBase.h:8791
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Definition TypeBase.h:9214
bool isMemberPointerType() const
Definition TypeBase.h:8749
bool isFunctionProtoType() const
Definition TypeBase.h:2649
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
bool isFunctionType() const
Definition TypeBase.h:8664
bool isFloatingType() const
Definition Type.cpp:2342
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9261
bool isNullPtrType() const
Definition TypeBase.h:9071
bool isRecordType() const
Definition TypeBase.h:8795
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:5961
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)