1//===- StmtPrinter.cpp - Printing implementation for Stmt ASTs ------------===//
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 the Stmt::dumpPretty/Stmt::printPretty methods, which
10// pretty print the AST back out to C code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/Attr.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclBase.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/DeclOpenACC.h"
21#include "clang/AST/DeclOpenMP.h"
22#include "clang/AST/DeclTemplate.h"
23#include "clang/AST/Expr.h"
24#include "clang/AST/ExprCXX.h"
25#include "clang/AST/ExprObjC.h"
26#include "clang/AST/ExprOpenMP.h"
27#include "clang/AST/NestedNameSpecifier.h"
28#include "clang/AST/OpenMPClause.h"
29#include "clang/AST/PrettyPrinter.h"
30#include "clang/AST/Stmt.h"
31#include "clang/AST/StmtCXX.h"
32#include "clang/AST/StmtObjC.h"
33#include "clang/AST/StmtOpenMP.h"
34#include "clang/AST/StmtSYCL.h"
35#include "clang/AST/StmtVisitor.h"
36#include "clang/AST/TemplateBase.h"
37#include "clang/AST/Type.h"
38#include "clang/Basic/BuiltinTraits.h"
39#include "clang/Basic/IdentifierTable.h"
40#include "clang/Basic/JsonSupport.h"
41#include "clang/Basic/LLVM.h"
42#include "clang/Basic/Lambda.h"
43#include "clang/Basic/OpenMPKinds.h"
44#include "clang/Basic/OperatorKinds.h"
45#include "clang/Basic/SourceLocation.h"
46#include "clang/Lex/Lexer.h"
47#include "llvm/ADT/ArrayRef.h"
48#include "llvm/ADT/STLExtras.h"
49#include "llvm/ADT/StringExtras.h"
50#include "llvm/ADT/StringRef.h"
51#include "llvm/Support/Compiler.h"
52#include "llvm/Support/ErrorHandling.h"
53#include "llvm/Support/raw_ostream.h"
54#include <cassert>
55#include <optional>
56#include <string>
57
58using namespace clang;
59
60//===----------------------------------------------------------------------===//
61// StmtPrinter Visitor
62//===----------------------------------------------------------------------===//
63
64namespace {
65
66 class StmtPrinter : public StmtVisitor<StmtPrinter> {
67 raw_ostream &OS;
68 unsigned IndentLevel;
69 PrinterHelper* Helper;
70 PrintingPolicy Policy;
71 std::string NL;
72 const ASTContext *Context;
73
74 public:
75 StmtPrinter(raw_ostream &os, PrinterHelper *helper,
76 const PrintingPolicy &Policy, unsigned Indentation = 0,
77 StringRef NL = "\n", const ASTContext *Context = nullptr)
78 : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy),
79 NL(NL), Context(Context) {}
80
81 void PrintStmt(Stmt *S) { PrintStmt(S, SubIndent: Policy.Indentation); }
82
83 void PrintStmt(Stmt *S, int SubIndent) {
84 IndentLevel += SubIndent;
85 if (isa_and_nonnull<Expr>(Val: S)) {
86 // If this is an expr used in a stmt context, indent and newline it.
87 Indent();
88 Visit(S);
89 OS << ";" << NL;
90 } else if (S) {
91 Visit(S);
92 } else {
93 Indent() << "<<<NULL STATEMENT>>>" << NL;
94 }
95 IndentLevel -= SubIndent;
96 }
97
98 void PrintInitStmt(Stmt *S, unsigned PrefixWidth) {
99 // FIXME: Cope better with odd prefix widths.
100 IndentLevel += (PrefixWidth + 1) / 2;
101 if (auto *DS = dyn_cast<DeclStmt>(Val: S))
102 PrintRawDeclStmt(S: DS);
103 else
104 PrintExpr(E: cast<Expr>(Val: S));
105 OS << "; ";
106 IndentLevel -= (PrefixWidth + 1) / 2;
107 }
108
109 void PrintControlledStmt(Stmt *S) {
110 if (auto *CS = dyn_cast<CompoundStmt>(Val: S)) {
111 OS << " ";
112 PrintRawCompoundStmt(S: CS);
113 OS << NL;
114 } else {
115 OS << NL;
116 PrintStmt(S);
117 }
118 }
119
120 void PrintRawCompoundStmt(CompoundStmt *S);
121 void PrintRawDecl(Decl *D);
122 void PrintRawDeclStmt(const DeclStmt *S);
123 void PrintRawIfStmt(IfStmt *If);
124 void PrintRawCXXCatchStmt(CXXCatchStmt *Catch);
125 void PrintCallArgs(CallExpr *E);
126 void PrintRawSEHExceptHandler(SEHExceptStmt *S);
127 void PrintRawSEHFinallyStmt(SEHFinallyStmt *S);
128 void PrintOMPExecutableDirective(OMPExecutableDirective *S,
129 bool ForceNoStmt = false);
130 void PrintFPPragmas(CompoundStmt *S);
131 void PrintOpenACCClauseList(OpenACCConstructStmt *S);
132 void PrintOpenACCConstruct(OpenACCConstructStmt *S);
133
134 void PrintExpr(Expr *E) {
135 if (E)
136 Visit(S: E);
137 else
138 OS << "<null expr>";
139 }
140
141 raw_ostream &Indent(int Delta = 0) {
142 for (int i = 0, e = IndentLevel+Delta; i < e; ++i)
143 OS << " ";
144 return OS;
145 }
146
147 void Visit(Stmt* S) {
148 if (Helper && Helper->handledStmt(E: S,OS))
149 return;
150 else StmtVisitor<StmtPrinter>::Visit(S);
151 }
152
153 [[maybe_unused]] void VisitStmt(Stmt *Node) {
154 Indent() << "<<unknown stmt type>>" << NL;
155 }
156
157 [[maybe_unused]] void VisitExpr(Expr *Node) {
158 OS << "<<unknown expr type>>";
159 }
160
161 void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
162
163 void VisitBinComma(BinaryOperator *Node);
164
165#define ABSTRACT_STMT(CLASS)
166#define STMT(CLASS, PARENT) \
167 void Visit##CLASS(CLASS *Node);
168#include "clang/AST/StmtNodes.inc"
169 };
170
171} // namespace
172
173//===----------------------------------------------------------------------===//
174// Stmt printing methods.
175//===----------------------------------------------------------------------===//
176
177/// PrintRawCompoundStmt - Print a compound stmt without indenting the {, and
178/// with no newline after the }.
179void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) {
180 assert(Node && "Compound statement cannot be null");
181 OS << "{" << NL;
182 PrintFPPragmas(S: Node);
183 for (auto *I : Node->body())
184 PrintStmt(S: I);
185
186 Indent() << "}";
187}
188
189void StmtPrinter::PrintFPPragmas(CompoundStmt *S) {
190 if (!S->hasStoredFPFeatures())
191 return;
192 FPOptionsOverride FPO = S->getStoredFPFeatures();
193 bool FEnvAccess = false;
194 if (FPO.hasAllowFEnvAccessOverride()) {
195 FEnvAccess = FPO.getAllowFEnvAccessOverride();
196 Indent() << "#pragma STDC FENV_ACCESS " << (FEnvAccess ? "ON" : "OFF")
197 << NL;
198 }
199 if (FPO.hasSpecifiedExceptionModeOverride()) {
200 LangOptions::FPExceptionModeKind EM =
201 FPO.getSpecifiedExceptionModeOverride();
202 if (!FEnvAccess || EM != LangOptions::FPE_Strict) {
203 Indent() << "#pragma clang fp exceptions(";
204 switch (FPO.getSpecifiedExceptionModeOverride()) {
205 default:
206 break;
207 case LangOptions::FPE_Ignore:
208 OS << "ignore";
209 break;
210 case LangOptions::FPE_MayTrap:
211 OS << "maytrap";
212 break;
213 case LangOptions::FPE_Strict:
214 OS << "strict";
215 break;
216 }
217 OS << ")\n";
218 }
219 }
220 if (FPO.hasConstRoundingModeOverride()) {
221 LangOptions::RoundingMode RM = FPO.getConstRoundingModeOverride();
222 Indent() << "#pragma STDC FENV_ROUND ";
223 switch (RM) {
224 case llvm::RoundingMode::TowardZero:
225 OS << "FE_TOWARDZERO";
226 break;
227 case llvm::RoundingMode::NearestTiesToEven:
228 OS << "FE_TONEAREST";
229 break;
230 case llvm::RoundingMode::TowardPositive:
231 OS << "FE_UPWARD";
232 break;
233 case llvm::RoundingMode::TowardNegative:
234 OS << "FE_DOWNWARD";
235 break;
236 case llvm::RoundingMode::NearestTiesToAway:
237 OS << "FE_TONEARESTFROMZERO";
238 break;
239 case llvm::RoundingMode::Dynamic:
240 OS << "FE_DYNAMIC";
241 break;
242 default:
243 llvm_unreachable("Invalid rounding mode");
244 }
245 OS << NL;
246 }
247}
248
249void StmtPrinter::PrintRawDecl(Decl *D) {
250 D->print(Out&: OS, Policy, Indentation: IndentLevel);
251}
252
253void StmtPrinter::PrintRawDeclStmt(const DeclStmt *S) {
254 SmallVector<Decl *, 2> Decls(S->decls());
255 Decl::printGroup(Begin: Decls.data(), NumDecls: Decls.size(), Out&: OS, Policy, Indentation: IndentLevel);
256}
257
258void StmtPrinter::VisitNullStmt(NullStmt *Node) {
259 Indent() << ";" << NL;
260}
261
262void StmtPrinter::VisitDeclStmt(DeclStmt *Node) {
263 Indent();
264 PrintRawDeclStmt(S: Node);
265 // Certain pragma declarations shouldn't have a semi-colon after them.
266 if (!Node->isSingleDecl() ||
267 !isa<CXXExpansionStmtDecl, OpenACCDeclareDecl, OpenACCRoutineDecl>(
268 Val: Node->getSingleDecl()))
269 OS << ";";
270 OS << NL;
271}
272
273void StmtPrinter::VisitCompoundStmt(CompoundStmt *Node) {
274 Indent();
275 PrintRawCompoundStmt(Node);
276 OS << "" << NL;
277}
278
279void StmtPrinter::VisitCaseStmt(CaseStmt *Node) {
280 Indent(Delta: -1) << "case ";
281 PrintExpr(E: Node->getLHS());
282 if (Node->getRHS()) {
283 OS << " ... ";
284 PrintExpr(E: Node->getRHS());
285 }
286 OS << ":" << NL;
287
288 PrintStmt(S: Node->getSubStmt(), SubIndent: 0);
289}
290
291void StmtPrinter::VisitDefaultStmt(DefaultStmt *Node) {
292 Indent(Delta: -1) << "default:" << NL;
293 PrintStmt(S: Node->getSubStmt(), SubIndent: 0);
294}
295
296void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
297 Indent(Delta: -1) << Node->getName() << ":" << NL;
298 PrintStmt(S: Node->getSubStmt(), SubIndent: 0);
299}
300
301void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
302 ArrayRef<const Attr *> Attrs = Node->getAttrs();
303 for (const auto *Attr : Attrs) {
304 Attr->printPretty(OS, Policy);
305 if (Attr != Attrs.back())
306 OS << ' ';
307 }
308
309 PrintStmt(S: Node->getSubStmt(), SubIndent: 0);
310}
311
312void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
313 if (If->isConsteval()) {
314 OS << "if ";
315 if (If->isNegatedConsteval())
316 OS << "!";
317 OS << "consteval";
318 OS << NL;
319 PrintStmt(S: If->getThen());
320 if (Stmt *Else = If->getElse()) {
321 Indent();
322 OS << "else";
323 PrintStmt(S: Else);
324 OS << NL;
325 }
326 return;
327 }
328
329 OS << "if (";
330 if (If->getInit())
331 PrintInitStmt(S: If->getInit(), PrefixWidth: 4);
332 if (const DeclStmt *DS = If->getConditionVariableDeclStmt())
333 PrintRawDeclStmt(S: DS);
334 else
335 PrintExpr(E: If->getCond());
336 OS << ')';
337
338 if (auto *CS = dyn_cast<CompoundStmt>(Val: If->getThen())) {
339 OS << ' ';
340 PrintRawCompoundStmt(Node: CS);
341 OS << (If->getElse() ? " " : NL);
342 } else {
343 OS << NL;
344 PrintStmt(S: If->getThen());
345 if (If->getElse()) Indent();
346 }
347
348 if (Stmt *Else = If->getElse()) {
349 OS << "else";
350
351 if (auto *CS = dyn_cast<CompoundStmt>(Val: Else)) {
352 OS << ' ';
353 PrintRawCompoundStmt(Node: CS);
354 OS << NL;
355 } else if (auto *ElseIf = dyn_cast<IfStmt>(Val: Else)) {
356 OS << ' ';
357 PrintRawIfStmt(If: ElseIf);
358 } else {
359 OS << NL;
360 PrintStmt(S: If->getElse());
361 }
362 }
363}
364
365void StmtPrinter::VisitIfStmt(IfStmt *If) {
366 Indent();
367 PrintRawIfStmt(If);
368}
369
370void StmtPrinter::VisitSwitchStmt(SwitchStmt *Node) {
371 Indent() << "switch (";
372 if (Node->getInit())
373 PrintInitStmt(S: Node->getInit(), PrefixWidth: 8);
374 if (const DeclStmt *DS = Node->getConditionVariableDeclStmt())
375 PrintRawDeclStmt(S: DS);
376 else
377 PrintExpr(E: Node->getCond());
378 OS << ")";
379 PrintControlledStmt(S: Node->getBody());
380}
381
382void StmtPrinter::VisitWhileStmt(WhileStmt *Node) {
383 Indent() << "while (";
384 if (const DeclStmt *DS = Node->getConditionVariableDeclStmt())
385 PrintRawDeclStmt(S: DS);
386 else
387 PrintExpr(E: Node->getCond());
388 OS << ")" << NL;
389 PrintStmt(S: Node->getBody());
390}
391
392void StmtPrinter::VisitDoStmt(DoStmt *Node) {
393 Indent() << "do ";
394 if (auto *CS = dyn_cast<CompoundStmt>(Val: Node->getBody())) {
395 PrintRawCompoundStmt(Node: CS);
396 OS << " ";
397 } else {
398 OS << NL;
399 PrintStmt(S: Node->getBody());
400 Indent();
401 }
402
403 OS << "while (";
404 PrintExpr(E: Node->getCond());
405 OS << ");" << NL;
406}
407
408void StmtPrinter::VisitForStmt(ForStmt *Node) {
409 Indent() << "for (";
410 if (Node->getInit())
411 PrintInitStmt(S: Node->getInit(), PrefixWidth: 5);
412 else
413 OS << (Node->getCond() ? "; " : ";");
414 if (const DeclStmt *DS = Node->getConditionVariableDeclStmt())
415 PrintRawDeclStmt(S: DS);
416 else if (Node->getCond())
417 PrintExpr(E: Node->getCond());
418 OS << ";";
419 if (Node->getInc()) {
420 OS << " ";
421 PrintExpr(E: Node->getInc());
422 }
423 OS << ")";
424 PrintControlledStmt(S: Node->getBody());
425}
426
427void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) {
428 Indent() << "for (";
429 if (auto *DS = dyn_cast<DeclStmt>(Val: Node->getElement()))
430 PrintRawDeclStmt(S: DS);
431 else
432 PrintExpr(E: cast<Expr>(Val: Node->getElement()));
433 OS << " in ";
434 PrintExpr(E: Node->getCollection());
435 OS << ")";
436 PrintControlledStmt(S: Node->getBody());
437}
438
439void StmtPrinter::VisitCXXForRangeStmt(CXXForRangeStmt *Node) {
440 Indent() << "for (";
441 if (Node->getInit())
442 PrintInitStmt(S: Node->getInit(), PrefixWidth: 5);
443 PrintingPolicy SubPolicy(Policy);
444 SubPolicy.SuppressInitializers = true;
445 Node->getLoopVariable()->print(Out&: OS, Policy: SubPolicy, Indentation: IndentLevel);
446 OS << " : ";
447 PrintExpr(E: Node->getRangeInit());
448 OS << ")";
449 PrintControlledStmt(S: Node->getBody());
450}
451
452void StmtPrinter::VisitCXXExpansionStmtPattern(CXXExpansionStmtPattern *Node) {
453 OS << "template for (";
454 if (Node->getInit())
455 PrintInitStmt(S: Node->getInit(), PrefixWidth: 14);
456 PrintingPolicy SubPolicy(Policy);
457 SubPolicy.SuppressInitializers = true;
458 Node->getExpansionVariable()->print(Out&: OS, Policy: SubPolicy, Indentation: IndentLevel);
459 OS << " : ";
460
461 if (Node->isIterating())
462 PrintExpr(E: Node->getRangeVar()->getInit());
463 else if (Node->isDependent())
464 PrintExpr(E: Node->getExpansionInitializer());
465 else if (Node->isDestructuring())
466 PrintExpr(E: Node->getDecompositionDecl()->getInit());
467 else
468 PrintExpr(E: Node->getExpansionVariable()->getInit());
469
470 OS << ")";
471 PrintControlledStmt(S: Node->getBody());
472}
473
474void StmtPrinter::VisitCXXExpansionStmtInstantiation(
475 CXXExpansionStmtInstantiation *) {
476 llvm_unreachable("should never be printed");
477}
478
479void StmtPrinter::VisitCXXExpansionSelectExpr(CXXExpansionSelectExpr *Node) {
480 PrintExpr(E: Node->getRangeExpr());
481}
482
483void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) {
484 Indent();
485 if (Node->isIfExists())
486 OS << "__if_exists (";
487 else
488 OS << "__if_not_exists (";
489
490 Node->getQualifierLoc().getNestedNameSpecifier().print(OS, Policy);
491 OS << Node->getNameInfo() << ") ";
492
493 PrintRawCompoundStmt(Node: Node->getSubStmt());
494}
495
496void StmtPrinter::VisitGotoStmt(GotoStmt *Node) {
497 Indent() << "goto " << Node->getLabel()->getName() << ";";
498 if (Policy.IncludeNewlines) OS << NL;
499}
500
501void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) {
502 Indent() << "goto *";
503 PrintExpr(E: Node->getTarget());
504 OS << ";";
505 if (Policy.IncludeNewlines) OS << NL;
506}
507
508void StmtPrinter::VisitContinueStmt(ContinueStmt *Node) {
509 Indent();
510 if (Node->hasLabelTarget())
511 OS << "continue " << Node->getLabelDecl()->getIdentifier()->getName()
512 << ';';
513 else
514 OS << "continue;";
515 if (Policy.IncludeNewlines) OS << NL;
516}
517
518void StmtPrinter::VisitBreakStmt(BreakStmt *Node) {
519 Indent();
520 if (Node->hasLabelTarget())
521 OS << "break " << Node->getLabelDecl()->getIdentifier()->getName() << ';';
522 else
523 OS << "break;";
524 if (Policy.IncludeNewlines) OS << NL;
525}
526
527void StmtPrinter::VisitDeferStmt(DeferStmt *Node) {
528 Indent() << "_Defer";
529 PrintControlledStmt(S: Node->getBody());
530}
531
532void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) {
533 Indent() << "return";
534 if (Node->getRetValue()) {
535 OS << " ";
536 PrintExpr(E: Node->getRetValue());
537 }
538 OS << ";";
539 if (Policy.IncludeNewlines) OS << NL;
540}
541
542void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
543 Indent() << "asm ";
544
545 if (Node->isVolatile())
546 OS << "volatile ";
547
548 if (Node->isAsmGoto())
549 OS << "goto ";
550
551 OS << "(";
552 Visit(S: Node->getAsmStringExpr());
553
554 // Outputs
555 if (Node->getNumOutputs() != 0 || Node->getNumInputs() != 0 ||
556 Node->getNumClobbers() != 0 || Node->getNumLabels() != 0)
557 OS << " : ";
558
559 for (unsigned i = 0, e = Node->getNumOutputs(); i != e; ++i) {
560 if (i != 0)
561 OS << ", ";
562
563 if (!Node->getOutputName(i).empty()) {
564 OS << '[';
565 OS << Node->getOutputName(i);
566 OS << "] ";
567 }
568
569 Visit(S: Node->getOutputConstraintExpr(i));
570 OS << " (";
571 Visit(S: Node->getOutputExpr(i));
572 OS << ")";
573 }
574
575 // Inputs
576 if (Node->getNumInputs() != 0 || Node->getNumClobbers() != 0 ||
577 Node->getNumLabels() != 0)
578 OS << " : ";
579
580 for (unsigned i = 0, e = Node->getNumInputs(); i != e; ++i) {
581 if (i != 0)
582 OS << ", ";
583
584 if (!Node->getInputName(i).empty()) {
585 OS << '[';
586 OS << Node->getInputName(i);
587 OS << "] ";
588 }
589
590 Visit(S: Node->getInputConstraintExpr(i));
591 OS << " (";
592 Visit(S: Node->getInputExpr(i));
593 OS << ")";
594 }
595
596 // Clobbers
597 if (Node->getNumClobbers() != 0 || Node->getNumLabels())
598 OS << " : ";
599
600 for (unsigned i = 0, e = Node->getNumClobbers(); i != e; ++i) {
601 if (i != 0)
602 OS << ", ";
603
604 Visit(S: Node->getClobberExpr(i));
605 }
606
607 // Labels
608 if (Node->getNumLabels() != 0)
609 OS << " : ";
610
611 for (unsigned i = 0, e = Node->getNumLabels(); i != e; ++i) {
612 if (i != 0)
613 OS << ", ";
614 OS << Node->getLabelName(i);
615 }
616
617 OS << ");";
618 if (Policy.IncludeNewlines) OS << NL;
619}
620
621void StmtPrinter::VisitMSAsmStmt(MSAsmStmt *Node) {
622 // FIXME: Implement MS style inline asm statement printer.
623 Indent() << "__asm ";
624 if (Node->hasBraces())
625 OS << "{" << NL;
626 OS << Node->getAsmString() << NL;
627 if (Node->hasBraces())
628 Indent() << "}" << NL;
629}
630
631void StmtPrinter::VisitCapturedStmt(CapturedStmt *Node) {
632 PrintStmt(S: Node->getCapturedDecl()->getBody());
633}
634
635void StmtPrinter::VisitSYCLKernelCallStmt(SYCLKernelCallStmt *Node) {
636 PrintStmt(S: Node->getOriginalStmt());
637}
638
639void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
640 Indent() << "@try";
641 if (auto *TS = dyn_cast<CompoundStmt>(Val: Node->getTryBody())) {
642 PrintRawCompoundStmt(Node: TS);
643 OS << NL;
644 }
645
646 for (ObjCAtCatchStmt *catchStmt : Node->catch_stmts()) {
647 Indent() << "@catch(";
648 if (Decl *DS = catchStmt->getCatchParamDecl())
649 PrintRawDecl(D: DS);
650 OS << ")";
651 if (auto *CS = dyn_cast<CompoundStmt>(Val: catchStmt->getCatchBody())) {
652 PrintRawCompoundStmt(Node: CS);
653 OS << NL;
654 }
655 }
656
657 if (ObjCAtFinallyStmt *FS = Node->getFinallyStmt()) {
658 Indent() << "@finally";
659 if (auto *CS = dyn_cast<CompoundStmt>(Val: FS->getFinallyBody())) {
660 PrintRawCompoundStmt(Node: CS);
661 OS << NL;
662 }
663 }
664}
665
666void StmtPrinter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Node) {
667}
668
669void StmtPrinter::VisitObjCAtCatchStmt (ObjCAtCatchStmt *Node) {
670 Indent() << "@catch (...) { /* todo */ } " << NL;
671}
672
673void StmtPrinter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *Node) {
674 Indent() << "@throw";
675 if (Node->getThrowExpr()) {
676 OS << " ";
677 PrintExpr(E: Node->getThrowExpr());
678 }
679 OS << ";" << NL;
680}
681
682void StmtPrinter::VisitObjCAvailabilityCheckExpr(
683 ObjCAvailabilityCheckExpr *Node) {
684 OS << "@available(...)";
685}
686
687void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) {
688 Indent() << "@synchronized (";
689 PrintExpr(E: Node->getSynchExpr());
690 OS << ")";
691 PrintRawCompoundStmt(Node: Node->getSynchBody());
692 OS << NL;
693}
694
695void StmtPrinter::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *Node) {
696 Indent() << "@autoreleasepool";
697 PrintRawCompoundStmt(Node: cast<CompoundStmt>(Val: Node->getSubStmt()));
698 OS << NL;
699}
700
701void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) {
702 OS << "catch (";
703 if (Decl *ExDecl = Node->getExceptionDecl())
704 PrintRawDecl(D: ExDecl);
705 else
706 OS << "...";
707 OS << ") ";
708 PrintRawCompoundStmt(Node: cast<CompoundStmt>(Val: Node->getHandlerBlock()));
709}
710
711void StmtPrinter::VisitCXXCatchStmt(CXXCatchStmt *Node) {
712 Indent();
713 PrintRawCXXCatchStmt(Node);
714 OS << NL;
715}
716
717void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) {
718 Indent() << "try ";
719 PrintRawCompoundStmt(Node: Node->getTryBlock());
720 for (unsigned i = 0, e = Node->getNumHandlers(); i < e; ++i) {
721 OS << " ";
722 PrintRawCXXCatchStmt(Node: Node->getHandler(i));
723 }
724 OS << NL;
725}
726
727void StmtPrinter::VisitSEHTryStmt(SEHTryStmt *Node) {
728 Indent() << (Node->getIsCXXTry() ? "try " : "__try ");
729 PrintRawCompoundStmt(Node: Node->getTryBlock());
730 SEHExceptStmt *E = Node->getExceptHandler();
731 SEHFinallyStmt *F = Node->getFinallyHandler();
732 if(E)
733 PrintRawSEHExceptHandler(S: E);
734 else {
735 assert(F && "Must have a finally block...");
736 PrintRawSEHFinallyStmt(S: F);
737 }
738 OS << NL;
739}
740
741void StmtPrinter::PrintRawSEHFinallyStmt(SEHFinallyStmt *Node) {
742 OS << "__finally ";
743 PrintRawCompoundStmt(Node: Node->getBlock());
744 OS << NL;
745}
746
747void StmtPrinter::PrintRawSEHExceptHandler(SEHExceptStmt *Node) {
748 OS << "__except (";
749 VisitExpr(Node: Node->getFilterExpr());
750 OS << ")" << NL;
751 PrintRawCompoundStmt(Node: Node->getBlock());
752 OS << NL;
753}
754
755void StmtPrinter::VisitSEHExceptStmt(SEHExceptStmt *Node) {
756 Indent();
757 PrintRawSEHExceptHandler(Node);
758 OS << NL;
759}
760
761void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) {
762 Indent();
763 PrintRawSEHFinallyStmt(Node);
764 OS << NL;
765}
766
767void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) {
768 Indent() << "__leave;";
769 if (Policy.IncludeNewlines) OS << NL;
770}
771
772//===----------------------------------------------------------------------===//
773// OpenMP directives printing methods
774//===----------------------------------------------------------------------===//
775
776void StmtPrinter::VisitOMPCanonicalLoop(OMPCanonicalLoop *Node) {
777 PrintStmt(S: Node->getLoopStmt());
778}
779
780void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S,
781 bool ForceNoStmt) {
782 llvm::omp::Version OpenMPVersion =
783 Context ? Context->getLangOpts().getOpenMPVersion()
784 : llvm::omp::FallbackVersion;
785 OMPClausePrinter Printer(OS, Policy, OpenMPVersion);
786 ArrayRef<OMPClause *> Clauses = S->clauses();
787 for (auto *Clause : Clauses)
788 if (Clause && !Clause->isImplicit()) {
789 OS << ' ';
790 Printer.Visit(S: Clause);
791 }
792 OS << NL;
793 if (!ForceNoStmt && S->hasAssociatedStmt())
794 PrintStmt(S: S->getRawStmt());
795}
796
797void StmtPrinter::VisitOMPMetaDirective(OMPMetaDirective *Node) {
798 Indent() << "#pragma omp metadirective";
799 PrintOMPExecutableDirective(S: Node);
800}
801
802void StmtPrinter::VisitOMPParallelDirective(OMPParallelDirective *Node) {
803 Indent() << "#pragma omp parallel";
804 PrintOMPExecutableDirective(S: Node);
805}
806
807void StmtPrinter::VisitOMPSimdDirective(OMPSimdDirective *Node) {
808 Indent() << "#pragma omp simd";
809 PrintOMPExecutableDirective(S: Node);
810}
811
812void StmtPrinter::VisitOMPTileDirective(OMPTileDirective *Node) {
813 Indent() << "#pragma omp tile";
814 PrintOMPExecutableDirective(S: Node);
815}
816
817void StmtPrinter::VisitOMPStripeDirective(OMPStripeDirective *Node) {
818 Indent() << "#pragma omp stripe";
819 PrintOMPExecutableDirective(S: Node);
820}
821
822void StmtPrinter::VisitOMPUnrollDirective(OMPUnrollDirective *Node) {
823 Indent() << "#pragma omp unroll";
824 PrintOMPExecutableDirective(S: Node);
825}
826
827void StmtPrinter::VisitOMPReverseDirective(OMPReverseDirective *Node) {
828 Indent() << "#pragma omp reverse";
829 PrintOMPExecutableDirective(S: Node);
830}
831
832void StmtPrinter::VisitOMPInterchangeDirective(OMPInterchangeDirective *Node) {
833 Indent() << "#pragma omp interchange";
834 PrintOMPExecutableDirective(S: Node);
835}
836
837void StmtPrinter::VisitOMPSplitDirective(OMPSplitDirective *Node) {
838 Indent() << "#pragma omp split";
839 PrintOMPExecutableDirective(S: Node);
840}
841
842void StmtPrinter::VisitOMPFuseDirective(OMPFuseDirective *Node) {
843 Indent() << "#pragma omp fuse";
844 PrintOMPExecutableDirective(S: Node);
845}
846
847void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) {
848 Indent() << "#pragma omp for";
849 PrintOMPExecutableDirective(S: Node);
850}
851
852void StmtPrinter::VisitOMPForSimdDirective(OMPForSimdDirective *Node) {
853 Indent() << "#pragma omp for simd";
854 PrintOMPExecutableDirective(S: Node);
855}
856
857void StmtPrinter::VisitOMPSectionsDirective(OMPSectionsDirective *Node) {
858 Indent() << "#pragma omp sections";
859 PrintOMPExecutableDirective(S: Node);
860}
861
862void StmtPrinter::VisitOMPSectionDirective(OMPSectionDirective *Node) {
863 Indent() << "#pragma omp section";
864 PrintOMPExecutableDirective(S: Node);
865}
866
867void StmtPrinter::VisitOMPScopeDirective(OMPScopeDirective *Node) {
868 Indent() << "#pragma omp scope";
869 PrintOMPExecutableDirective(S: Node);
870}
871
872void StmtPrinter::VisitOMPSingleDirective(OMPSingleDirective *Node) {
873 Indent() << "#pragma omp single";
874 PrintOMPExecutableDirective(S: Node);
875}
876
877void StmtPrinter::VisitOMPMasterDirective(OMPMasterDirective *Node) {
878 Indent() << "#pragma omp master";
879 PrintOMPExecutableDirective(S: Node);
880}
881
882void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) {
883 Indent() << "#pragma omp critical";
884 if (Node->getDirectiveName().getName()) {
885 OS << " (";
886 Node->getDirectiveName().printName(OS, Policy);
887 OS << ")";
888 }
889 PrintOMPExecutableDirective(S: Node);
890}
891
892void StmtPrinter::VisitOMPParallelForDirective(OMPParallelForDirective *Node) {
893 Indent() << "#pragma omp parallel for";
894 PrintOMPExecutableDirective(S: Node);
895}
896
897void StmtPrinter::VisitOMPParallelForSimdDirective(
898 OMPParallelForSimdDirective *Node) {
899 Indent() << "#pragma omp parallel for simd";
900 PrintOMPExecutableDirective(S: Node);
901}
902
903void StmtPrinter::VisitOMPParallelMasterDirective(
904 OMPParallelMasterDirective *Node) {
905 Indent() << "#pragma omp parallel master";
906 PrintOMPExecutableDirective(S: Node);
907}
908
909void StmtPrinter::VisitOMPParallelMaskedDirective(
910 OMPParallelMaskedDirective *Node) {
911 Indent() << "#pragma omp parallel masked";
912 PrintOMPExecutableDirective(S: Node);
913}
914
915void StmtPrinter::VisitOMPParallelSectionsDirective(
916 OMPParallelSectionsDirective *Node) {
917 Indent() << "#pragma omp parallel sections";
918 PrintOMPExecutableDirective(S: Node);
919}
920
921void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) {
922 Indent() << "#pragma omp task";
923 PrintOMPExecutableDirective(S: Node);
924}
925
926void StmtPrinter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *Node) {
927 Indent() << "#pragma omp taskyield";
928 PrintOMPExecutableDirective(S: Node);
929}
930
931void StmtPrinter::VisitOMPBarrierDirective(OMPBarrierDirective *Node) {
932 Indent() << "#pragma omp barrier";
933 PrintOMPExecutableDirective(S: Node);
934}
935
936void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) {
937 Indent() << "#pragma omp taskwait";
938 PrintOMPExecutableDirective(S: Node);
939}
940
941void StmtPrinter::VisitOMPAssumeDirective(OMPAssumeDirective *Node) {
942 Indent() << "#pragma omp assume";
943 PrintOMPExecutableDirective(S: Node);
944}
945
946void StmtPrinter::VisitOMPErrorDirective(OMPErrorDirective *Node) {
947 Indent() << "#pragma omp error";
948 PrintOMPExecutableDirective(S: Node);
949}
950
951void StmtPrinter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *Node) {
952 Indent() << "#pragma omp taskgroup";
953 PrintOMPExecutableDirective(S: Node);
954}
955
956void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) {
957 Indent() << "#pragma omp flush";
958 PrintOMPExecutableDirective(S: Node);
959}
960
961void StmtPrinter::VisitOMPDepobjDirective(OMPDepobjDirective *Node) {
962 Indent() << "#pragma omp depobj";
963 PrintOMPExecutableDirective(S: Node);
964}
965
966void StmtPrinter::VisitOMPScanDirective(OMPScanDirective *Node) {
967 Indent() << "#pragma omp scan";
968 PrintOMPExecutableDirective(S: Node);
969}
970
971void StmtPrinter::VisitOMPOrderedStandaloneDirective(
972 OMPOrderedStandaloneDirective *Node) {
973 Indent() << "#pragma omp ordered";
974 PrintOMPExecutableDirective(S: Node, ForceNoStmt: true);
975}
976
977void StmtPrinter::VisitOMPOrderedBlockAssocDirective(
978 OMPOrderedBlockAssocDirective *Node) {
979 Indent() << "#pragma omp ordered";
980 PrintOMPExecutableDirective(S: Node);
981}
982
983void StmtPrinter::VisitOMPAtomicDirective(OMPAtomicDirective *Node) {
984 Indent() << "#pragma omp atomic";
985 PrintOMPExecutableDirective(S: Node);
986}
987
988void StmtPrinter::VisitOMPTargetDirective(OMPTargetDirective *Node) {
989 Indent() << "#pragma omp target";
990 PrintOMPExecutableDirective(S: Node);
991}
992
993void StmtPrinter::VisitOMPTargetDataDirective(OMPTargetDataDirective *Node) {
994 Indent() << "#pragma omp target data";
995 PrintOMPExecutableDirective(S: Node);
996}
997
998void StmtPrinter::VisitOMPTargetEnterDataDirective(
999 OMPTargetEnterDataDirective *Node) {
1000 Indent() << "#pragma omp target enter data";
1001 PrintOMPExecutableDirective(S: Node, /*ForceNoStmt=*/true);
1002}
1003
1004void StmtPrinter::VisitOMPTargetExitDataDirective(
1005 OMPTargetExitDataDirective *Node) {
1006 Indent() << "#pragma omp target exit data";
1007 PrintOMPExecutableDirective(S: Node, /*ForceNoStmt=*/true);
1008}
1009
1010void StmtPrinter::VisitOMPTargetParallelDirective(
1011 OMPTargetParallelDirective *Node) {
1012 Indent() << "#pragma omp target parallel";
1013 PrintOMPExecutableDirective(S: Node);
1014}
1015
1016void StmtPrinter::VisitOMPTargetParallelForDirective(
1017 OMPTargetParallelForDirective *Node) {
1018 Indent() << "#pragma omp target parallel for";
1019 PrintOMPExecutableDirective(S: Node);
1020}
1021
1022void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
1023 Indent() << "#pragma omp teams";
1024 PrintOMPExecutableDirective(S: Node);
1025}
1026
1027void StmtPrinter::VisitOMPCancellationPointDirective(
1028 OMPCancellationPointDirective *Node) {
1029 llvm::omp::Version OpenMPVersion =
1030 Context ? Context->getLangOpts().getOpenMPVersion()
1031 : llvm::omp::FallbackVersion;
1032 Indent() << "#pragma omp cancellation point "
1033 << getOpenMPDirectiveName(D: Node->getCancelRegion(), V: OpenMPVersion);
1034 PrintOMPExecutableDirective(S: Node);
1035}
1036
1037void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) {
1038 llvm::omp::Version OpenMPVersion =
1039 Context ? Context->getLangOpts().getOpenMPVersion()
1040 : llvm::omp::FallbackVersion;
1041 Indent() << "#pragma omp cancel "
1042 << getOpenMPDirectiveName(D: Node->getCancelRegion(), V: OpenMPVersion);
1043 PrintOMPExecutableDirective(S: Node);
1044}
1045
1046void StmtPrinter::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *Node) {
1047 Indent() << "#pragma omp taskloop";
1048 PrintOMPExecutableDirective(S: Node);
1049}
1050
1051void StmtPrinter::VisitOMPTaskLoopSimdDirective(
1052 OMPTaskLoopSimdDirective *Node) {
1053 Indent() << "#pragma omp taskloop simd";
1054 PrintOMPExecutableDirective(S: Node);
1055}
1056
1057void StmtPrinter::VisitOMPMasterTaskLoopDirective(
1058 OMPMasterTaskLoopDirective *Node) {
1059 Indent() << "#pragma omp master taskloop";
1060 PrintOMPExecutableDirective(S: Node);
1061}
1062
1063void StmtPrinter::VisitOMPMaskedTaskLoopDirective(
1064 OMPMaskedTaskLoopDirective *Node) {
1065 Indent() << "#pragma omp masked taskloop";
1066 PrintOMPExecutableDirective(S: Node);
1067}
1068
1069void StmtPrinter::VisitOMPMasterTaskLoopSimdDirective(
1070 OMPMasterTaskLoopSimdDirective *Node) {
1071 Indent() << "#pragma omp master taskloop simd";
1072 PrintOMPExecutableDirective(S: Node);
1073}
1074
1075void StmtPrinter::VisitOMPMaskedTaskLoopSimdDirective(
1076 OMPMaskedTaskLoopSimdDirective *Node) {
1077 Indent() << "#pragma omp masked taskloop simd";
1078 PrintOMPExecutableDirective(S: Node);
1079}
1080
1081void StmtPrinter::VisitOMPParallelMasterTaskLoopDirective(
1082 OMPParallelMasterTaskLoopDirective *Node) {
1083 Indent() << "#pragma omp parallel master taskloop";
1084 PrintOMPExecutableDirective(S: Node);
1085}
1086
1087void StmtPrinter::VisitOMPParallelMaskedTaskLoopDirective(
1088 OMPParallelMaskedTaskLoopDirective *Node) {
1089 Indent() << "#pragma omp parallel masked taskloop";
1090 PrintOMPExecutableDirective(S: Node);
1091}
1092
1093void StmtPrinter::VisitOMPParallelMasterTaskLoopSimdDirective(
1094 OMPParallelMasterTaskLoopSimdDirective *Node) {
1095 Indent() << "#pragma omp parallel master taskloop simd";
1096 PrintOMPExecutableDirective(S: Node);
1097}
1098
1099void StmtPrinter::VisitOMPParallelMaskedTaskLoopSimdDirective(
1100 OMPParallelMaskedTaskLoopSimdDirective *Node) {
1101 Indent() << "#pragma omp parallel masked taskloop simd";
1102 PrintOMPExecutableDirective(S: Node);
1103}
1104
1105void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) {
1106 Indent() << "#pragma omp distribute";
1107 PrintOMPExecutableDirective(S: Node);
1108}
1109
1110void StmtPrinter::VisitOMPTargetUpdateDirective(
1111 OMPTargetUpdateDirective *Node) {
1112 Indent() << "#pragma omp target update";
1113 PrintOMPExecutableDirective(S: Node, /*ForceNoStmt=*/true);
1114}
1115
1116void StmtPrinter::VisitOMPDistributeParallelForDirective(
1117 OMPDistributeParallelForDirective *Node) {
1118 Indent() << "#pragma omp distribute parallel for";
1119 PrintOMPExecutableDirective(S: Node);
1120}
1121
1122void StmtPrinter::VisitOMPDistributeParallelForSimdDirective(
1123 OMPDistributeParallelForSimdDirective *Node) {
1124 Indent() << "#pragma omp distribute parallel for simd";
1125 PrintOMPExecutableDirective(S: Node);
1126}
1127
1128void StmtPrinter::VisitOMPDistributeSimdDirective(
1129 OMPDistributeSimdDirective *Node) {
1130 Indent() << "#pragma omp distribute simd";
1131 PrintOMPExecutableDirective(S: Node);
1132}
1133
1134void StmtPrinter::VisitOMPTargetParallelForSimdDirective(
1135 OMPTargetParallelForSimdDirective *Node) {
1136 Indent() << "#pragma omp target parallel for simd";
1137 PrintOMPExecutableDirective(S: Node);
1138}
1139
1140void StmtPrinter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *Node) {
1141 Indent() << "#pragma omp target simd";
1142 PrintOMPExecutableDirective(S: Node);
1143}
1144
1145void StmtPrinter::VisitOMPTeamsDistributeDirective(
1146 OMPTeamsDistributeDirective *Node) {
1147 Indent() << "#pragma omp teams distribute";
1148 PrintOMPExecutableDirective(S: Node);
1149}
1150
1151void StmtPrinter::VisitOMPTeamsDistributeSimdDirective(
1152 OMPTeamsDistributeSimdDirective *Node) {
1153 Indent() << "#pragma omp teams distribute simd";
1154 PrintOMPExecutableDirective(S: Node);
1155}
1156
1157void StmtPrinter::VisitOMPTeamsDistributeParallelForSimdDirective(
1158 OMPTeamsDistributeParallelForSimdDirective *Node) {
1159 Indent() << "#pragma omp teams distribute parallel for simd";
1160 PrintOMPExecutableDirective(S: Node);
1161}
1162
1163void StmtPrinter::VisitOMPTeamsDistributeParallelForDirective(
1164 OMPTeamsDistributeParallelForDirective *Node) {
1165 Indent() << "#pragma omp teams distribute parallel for";
1166 PrintOMPExecutableDirective(S: Node);
1167}
1168
1169void StmtPrinter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *Node) {
1170 Indent() << "#pragma omp target teams";
1171 PrintOMPExecutableDirective(S: Node);
1172}
1173
1174void StmtPrinter::VisitOMPTargetTeamsDistributeDirective(
1175 OMPTargetTeamsDistributeDirective *Node) {
1176 Indent() << "#pragma omp target teams distribute";
1177 PrintOMPExecutableDirective(S: Node);
1178}
1179
1180void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForDirective(
1181 OMPTargetTeamsDistributeParallelForDirective *Node) {
1182 Indent() << "#pragma omp target teams distribute parallel for";
1183 PrintOMPExecutableDirective(S: Node);
1184}
1185
1186void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForSimdDirective(
1187 OMPTargetTeamsDistributeParallelForSimdDirective *Node) {
1188 Indent() << "#pragma omp target teams distribute parallel for simd";
1189 PrintOMPExecutableDirective(S: Node);
1190}
1191
1192void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective(
1193 OMPTargetTeamsDistributeSimdDirective *Node) {
1194 Indent() << "#pragma omp target teams distribute simd";
1195 PrintOMPExecutableDirective(S: Node);
1196}
1197
1198void StmtPrinter::VisitOMPInteropDirective(OMPInteropDirective *Node) {
1199 Indent() << "#pragma omp interop";
1200 PrintOMPExecutableDirective(S: Node);
1201}
1202
1203void StmtPrinter::VisitOMPDispatchDirective(OMPDispatchDirective *Node) {
1204 Indent() << "#pragma omp dispatch";
1205 PrintOMPExecutableDirective(S: Node);
1206}
1207
1208void StmtPrinter::VisitOMPMaskedDirective(OMPMaskedDirective *Node) {
1209 Indent() << "#pragma omp masked";
1210 PrintOMPExecutableDirective(S: Node);
1211}
1212
1213void StmtPrinter::VisitOMPGenericLoopDirective(OMPGenericLoopDirective *Node) {
1214 Indent() << "#pragma omp loop";
1215 PrintOMPExecutableDirective(S: Node);
1216}
1217
1218void StmtPrinter::VisitOMPTeamsGenericLoopDirective(
1219 OMPTeamsGenericLoopDirective *Node) {
1220 Indent() << "#pragma omp teams loop";
1221 PrintOMPExecutableDirective(S: Node);
1222}
1223
1224void StmtPrinter::VisitOMPTargetTeamsGenericLoopDirective(
1225 OMPTargetTeamsGenericLoopDirective *Node) {
1226 Indent() << "#pragma omp target teams loop";
1227 PrintOMPExecutableDirective(S: Node);
1228}
1229
1230void StmtPrinter::VisitOMPParallelGenericLoopDirective(
1231 OMPParallelGenericLoopDirective *Node) {
1232 Indent() << "#pragma omp parallel loop";
1233 PrintOMPExecutableDirective(S: Node);
1234}
1235
1236void StmtPrinter::VisitOMPTargetParallelGenericLoopDirective(
1237 OMPTargetParallelGenericLoopDirective *Node) {
1238 Indent() << "#pragma omp target parallel loop";
1239 PrintOMPExecutableDirective(S: Node);
1240}
1241
1242//===----------------------------------------------------------------------===//
1243// OpenACC construct printing methods
1244//===----------------------------------------------------------------------===//
1245void StmtPrinter::PrintOpenACCClauseList(OpenACCConstructStmt *S) {
1246 if (!S->clauses().empty()) {
1247 OS << ' ';
1248 OpenACCClausePrinter Printer(OS, Policy);
1249 Printer.VisitClauseList(List: S->clauses());
1250 }
1251}
1252void StmtPrinter::PrintOpenACCConstruct(OpenACCConstructStmt *S) {
1253 Indent() << "#pragma acc " << S->getDirectiveKind();
1254 PrintOpenACCClauseList(S);
1255 OS << '\n';
1256}
1257void StmtPrinter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) {
1258 PrintOpenACCConstruct(S);
1259 PrintStmt(S: S->getStructuredBlock());
1260}
1261
1262void StmtPrinter::VisitOpenACCLoopConstruct(OpenACCLoopConstruct *S) {
1263 PrintOpenACCConstruct(S);
1264 PrintStmt(S: S->getLoop());
1265}
1266
1267void StmtPrinter::VisitOpenACCCombinedConstruct(OpenACCCombinedConstruct *S) {
1268 PrintOpenACCConstruct(S);
1269 PrintStmt(S: S->getLoop());
1270}
1271
1272void StmtPrinter::VisitOpenACCDataConstruct(OpenACCDataConstruct *S) {
1273 PrintOpenACCConstruct(S);
1274 PrintStmt(S: S->getStructuredBlock());
1275}
1276void StmtPrinter::VisitOpenACCHostDataConstruct(OpenACCHostDataConstruct *S) {
1277 PrintOpenACCConstruct(S);
1278 PrintStmt(S: S->getStructuredBlock());
1279}
1280void StmtPrinter::VisitOpenACCEnterDataConstruct(OpenACCEnterDataConstruct *S) {
1281 PrintOpenACCConstruct(S);
1282}
1283void StmtPrinter::VisitOpenACCExitDataConstruct(OpenACCExitDataConstruct *S) {
1284 PrintOpenACCConstruct(S);
1285}
1286void StmtPrinter::VisitOpenACCInitConstruct(OpenACCInitConstruct *S) {
1287 PrintOpenACCConstruct(S);
1288}
1289void StmtPrinter::VisitOpenACCShutdownConstruct(OpenACCShutdownConstruct *S) {
1290 PrintOpenACCConstruct(S);
1291}
1292void StmtPrinter::VisitOpenACCSetConstruct(OpenACCSetConstruct *S) {
1293 PrintOpenACCConstruct(S);
1294}
1295void StmtPrinter::VisitOpenACCUpdateConstruct(OpenACCUpdateConstruct *S) {
1296 PrintOpenACCConstruct(S);
1297}
1298
1299void StmtPrinter::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) {
1300 Indent() << "#pragma acc wait";
1301 if (!S->getLParenLoc().isInvalid()) {
1302 OS << "(";
1303 if (S->hasDevNumExpr()) {
1304 OS << "devnum: ";
1305 S->getDevNumExpr()->printPretty(OS, Helper: nullptr, Policy);
1306 OS << " : ";
1307 }
1308
1309 if (S->hasQueuesTag())
1310 OS << "queues: ";
1311
1312 llvm::interleaveComma(c: S->getQueueIdExprs(), os&: OS, each_fn: [&](const Expr *E) {
1313 E->printPretty(OS, Helper: nullptr, Policy);
1314 });
1315
1316 OS << ")";
1317 }
1318
1319 PrintOpenACCClauseList(S);
1320 OS << '\n';
1321}
1322
1323void StmtPrinter::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
1324 Indent() << "#pragma acc atomic";
1325
1326 if (S->getAtomicKind() != OpenACCAtomicKind::None)
1327 OS << " " << S->getAtomicKind();
1328
1329 PrintOpenACCClauseList(S);
1330 OS << '\n';
1331 PrintStmt(S: S->getAssociatedStmt());
1332}
1333
1334void StmtPrinter::VisitOpenACCCacheConstruct(OpenACCCacheConstruct *S) {
1335 Indent() << "#pragma acc cache(";
1336 if (S->hasReadOnly())
1337 OS << "readonly: ";
1338
1339 llvm::interleaveComma(c: S->getVarList(), os&: OS, each_fn: [&](const Expr *E) {
1340 E->printPretty(OS, Helper: nullptr, Policy);
1341 });
1342
1343 OS << ")\n";
1344}
1345
1346//===----------------------------------------------------------------------===//
1347// Expr printing methods.
1348//===----------------------------------------------------------------------===//
1349
1350void StmtPrinter::VisitSourceLocExpr(SourceLocExpr *Node) {
1351 OS << Node->getBuiltinStr() << "()";
1352}
1353
1354void StmtPrinter::VisitEmbedExpr(EmbedExpr *Node) {
1355 // FIXME: Embed parameters are not reflected in the AST, so there is no way to
1356 // print them yet.
1357 OS << "#embed ";
1358 OS << Node->getFileName();
1359 OS << NL;
1360}
1361
1362void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {
1363 PrintExpr(E: Node->getSubExpr());
1364}
1365
1366void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
1367 ValueDecl *VD = Node->getDecl();
1368 if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Val: VD)) {
1369 OCED->getInit()->IgnoreImpCasts()->printPretty(OS, Helper: nullptr, Policy);
1370 return;
1371 }
1372 if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(Val: VD)) {
1373 TPOD->printAsExpr(OS, Policy);
1374 return;
1375 }
1376 bool ForceAnonymous =
1377 Policy.PrintAsCanonical && VD->getKind() == Decl::NonTypeTemplateParm;
1378 bool CleanUglifiedParameter = Policy.CleanUglifiedParameters &&
1379 isa<ParmVarDecl, NonTypeTemplateParmDecl>(Val: VD);
1380
1381 if (Policy.FullyQualifiedName && !ForceAnonymous && !CleanUglifiedParameter &&
1382 !VD->isTemplateParameter()) {
1383 VD->printQualifiedName(OS, Policy);
1384 } else {
1385 Node->getQualifier().print(OS, Policy);
1386 if (Node->hasTemplateKeyword())
1387 OS << "template ";
1388
1389 DeclarationNameInfo NameInfo = Node->getNameInfo();
1390 if (IdentifierInfo *ID = NameInfo.getName().getAsIdentifierInfo();
1391 !ForceAnonymous && (ID || NameInfo.getName().getNameKind() !=
1392 DeclarationName::Identifier)) {
1393 if (CleanUglifiedParameter && ID)
1394 OS << ID->deuglifiedName();
1395 else
1396 NameInfo.printName(OS, Policy);
1397 } else {
1398 switch (VD->getKind()) {
1399 case Decl::NonTypeTemplateParm: {
1400 auto *TD = cast<NonTypeTemplateParmDecl>(Val: VD);
1401 OS << "value-parameter-" << TD->getDepth() << '-' << TD->getIndex()
1402 << "";
1403 break;
1404 }
1405 case Decl::ParmVar: {
1406 auto *PD = cast<ParmVarDecl>(Val: VD);
1407 OS << "function-parameter-" << PD->getFunctionScopeDepth() << '-'
1408 << PD->getFunctionScopeIndex();
1409 break;
1410 }
1411 case Decl::Decomposition:
1412 OS << "decomposition";
1413 for (const auto &I : cast<DecompositionDecl>(Val: VD)->bindings())
1414 OS << '-' << I->getName();
1415 break;
1416 default:
1417 OS << "unhandled-anonymous-" << VD->getDeclKindName();
1418 break;
1419 }
1420 }
1421 }
1422 if (Node->hasExplicitTemplateArgs()) {
1423 const TemplateParameterList *TPL = nullptr;
1424 if (!Node->hadMultipleCandidates())
1425 if (auto *TD = dyn_cast<TemplateDecl>(Val: VD))
1426 TPL = TD->getTemplateParameters();
1427 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy, TPL);
1428 }
1429}
1430
1431void StmtPrinter::VisitDependentScopeDeclRefExpr(
1432 DependentScopeDeclRefExpr *Node) {
1433 Node->getQualifier().print(OS, Policy);
1434 if (Node->hasTemplateKeyword())
1435 OS << "template ";
1436 OS << Node->getNameInfo();
1437 if (Node->hasExplicitTemplateArgs())
1438 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy);
1439}
1440
1441void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
1442 Node->getQualifier().print(OS, Policy);
1443 if (Node->hasTemplateKeyword())
1444 OS << "template ";
1445 OS << Node->getNameInfo();
1446 if (Node->hasExplicitTemplateArgs())
1447 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy);
1448}
1449
1450static bool isImplicitSelf(const Expr *E) {
1451 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
1452 if (const auto *PD = dyn_cast<ImplicitParamDecl>(Val: DRE->getDecl())) {
1453 if (PD->getParameterKind() == ImplicitParamKind::ObjCSelf &&
1454 DRE->getBeginLoc().isInvalid())
1455 return true;
1456 }
1457 }
1458 return false;
1459}
1460
1461void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
1462 if (Node->getBase()) {
1463 if (!Policy.SuppressImplicitBase ||
1464 !isImplicitSelf(E: Node->getBase()->IgnoreImpCasts())) {
1465 PrintExpr(E: Node->getBase());
1466 OS << (Node->isArrow() ? "->" : ".");
1467 }
1468 }
1469 OS << *Node->getDecl();
1470}
1471
1472void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
1473 if (Node->isSuperReceiver())
1474 OS << "super.";
1475 else if (Node->isObjectReceiver() && Node->getBase()) {
1476 PrintExpr(E: Node->getBase());
1477 OS << ".";
1478 } else if (Node->isClassReceiver() && Node->getClassReceiver()) {
1479 OS << Node->getClassReceiver()->getName() << ".";
1480 }
1481
1482 if (Node->isImplicitProperty()) {
1483 if (const auto *Getter = Node->getImplicitPropertyGetter())
1484 Getter->getSelector().print(OS);
1485 else
1486 OS << SelectorTable::getPropertyNameFromSetterSelector(
1487 Sel: Node->getImplicitPropertySetter()->getSelector());
1488 } else
1489 OS << Node->getExplicitProperty()->getName();
1490}
1491
1492void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
1493 PrintExpr(E: Node->getBaseExpr());
1494 OS << "[";
1495 PrintExpr(E: Node->getKeyExpr());
1496 OS << "]";
1497}
1498
1499void StmtPrinter::VisitSYCLUniqueStableNameExpr(
1500 SYCLUniqueStableNameExpr *Node) {
1501 OS << "__builtin_sycl_unique_stable_name(";
1502 Node->getTypeSourceInfo()->getType().print(OS, Policy);
1503 OS << ")";
1504}
1505
1506void StmtPrinter::VisitUnresolvedSYCLKernelCallStmt(
1507 UnresolvedSYCLKernelCallStmt *Node) {
1508 PrintStmt(S: Node->getOriginalStmt());
1509}
1510
1511void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
1512 OS << PredefinedExpr::getIdentKindName(IK: Node->getIdentKind());
1513}
1514
1515void StmtPrinter::VisitOpenACCAsteriskSizeExpr(OpenACCAsteriskSizeExpr *Node) {
1516 OS << '*';
1517}
1518
1519void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
1520 CharacterLiteral::print(val: Node->getValue(), Kind: Node->getKind(), OS);
1521}
1522
1523/// Prints the given expression using the original source text. Returns true on
1524/// success, false otherwise.
1525static bool printExprAsWritten(raw_ostream &OS, Expr *E,
1526 const ASTContext *Context) {
1527 if (!Context)
1528 return false;
1529 bool Invalid = false;
1530 StringRef Source = Lexer::getSourceText(
1531 Range: CharSourceRange::getTokenRange(R: E->getSourceRange()),
1532 SM: Context->getSourceManager(), LangOpts: Context->getLangOpts(), Invalid: &Invalid);
1533 if (!Invalid) {
1534 OS << Source;
1535 return true;
1536 }
1537 return false;
1538}
1539
1540void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
1541 if (Policy.ConstantsAsWritten && printExprAsWritten(OS, E: Node, Context))
1542 return;
1543 bool isSigned = Node->getType()->isSignedIntegerType();
1544 OS << toString(I: Node->getValue(), Radix: 10, Signed: isSigned);
1545
1546 if (isa<BitIntType>(Val: Node->getType())) {
1547 OS << (isSigned ? "wb" : "uwb");
1548 return;
1549 }
1550
1551 // Emit suffixes. Integer literals are always a builtin integer type.
1552 switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
1553 default: llvm_unreachable("Unexpected type for integer literal!");
1554 case BuiltinType::Char_S:
1555 case BuiltinType::Char_U: OS << "i8"; break;
1556 case BuiltinType::UChar: OS << "Ui8"; break;
1557 case BuiltinType::SChar: OS << "i8"; break;
1558 case BuiltinType::Short: OS << "i16"; break;
1559 case BuiltinType::UShort: OS << "Ui16"; break;
1560 case BuiltinType::Int: break; // no suffix.
1561 case BuiltinType::UInt: OS << 'U'; break;
1562 case BuiltinType::Long: OS << 'L'; break;
1563 case BuiltinType::ULong: OS << "UL"; break;
1564 case BuiltinType::LongLong: OS << "LL"; break;
1565 case BuiltinType::ULongLong: OS << "ULL"; break;
1566 case BuiltinType::Int128:
1567 break; // no suffix.
1568 case BuiltinType::UInt128:
1569 break; // no suffix.
1570 case BuiltinType::WChar_S:
1571 case BuiltinType::WChar_U:
1572 break; // no suffix
1573 }
1574}
1575
1576void StmtPrinter::VisitFixedPointLiteral(FixedPointLiteral *Node) {
1577 if (Policy.ConstantsAsWritten && printExprAsWritten(OS, E: Node, Context))
1578 return;
1579 OS << Node->getValueAsString(/*Radix=*/10);
1580
1581 switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
1582 default: llvm_unreachable("Unexpected type for fixed point literal!");
1583 case BuiltinType::ShortFract: OS << "hr"; break;
1584 case BuiltinType::ShortAccum: OS << "hk"; break;
1585 case BuiltinType::UShortFract: OS << "uhr"; break;
1586 case BuiltinType::UShortAccum: OS << "uhk"; break;
1587 case BuiltinType::Fract: OS << "r"; break;
1588 case BuiltinType::Accum: OS << "k"; break;
1589 case BuiltinType::UFract: OS << "ur"; break;
1590 case BuiltinType::UAccum: OS << "uk"; break;
1591 case BuiltinType::LongFract: OS << "lr"; break;
1592 case BuiltinType::LongAccum: OS << "lk"; break;
1593 case BuiltinType::ULongFract: OS << "ulr"; break;
1594 case BuiltinType::ULongAccum: OS << "ulk"; break;
1595 }
1596}
1597
1598static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
1599 bool PrintSuffix) {
1600 SmallString<16> Str;
1601 Node->getValue().toString(Str);
1602 OS << Str;
1603 if (Str.find_first_not_of(Chars: "-0123456789") == StringRef::npos)
1604 OS << '.'; // Trailing dot in order to separate from ints.
1605
1606 if (!PrintSuffix)
1607 return;
1608
1609 // Emit suffixes. Float literals are always a builtin float type.
1610 switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
1611 default: llvm_unreachable("Unexpected type for float literal!");
1612 case BuiltinType::Half: break; // FIXME: suffix?
1613 case BuiltinType::Ibm128: break; // FIXME: No suffix for ibm128 literal
1614 case BuiltinType::Double: break; // no suffix.
1615 case BuiltinType::Float16: OS << "F16"; break;
1616 case BuiltinType::Float: OS << 'F'; break;
1617 case BuiltinType::LongDouble: OS << 'L'; break;
1618 case BuiltinType::Float128: OS << 'Q'; break;
1619 }
1620}
1621
1622void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
1623 if (Policy.ConstantsAsWritten && printExprAsWritten(OS, E: Node, Context))
1624 return;
1625 PrintFloatingLiteral(OS, Node, /*PrintSuffix=*/true);
1626}
1627
1628void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) {
1629 PrintExpr(E: Node->getSubExpr());
1630 OS << "i";
1631}
1632
1633void StmtPrinter::VisitStringLiteral(StringLiteral *Str) {
1634 Str->outputString(OS);
1635}
1636
1637void StmtPrinter::VisitParenExpr(ParenExpr *Node) {
1638 OS << "(";
1639 PrintExpr(E: Node->getSubExpr());
1640 OS << ")";
1641}
1642
1643void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
1644 if (!Node->isPostfix()) {
1645 OS << UnaryOperator::getOpcodeStr(Op: Node->getOpcode());
1646
1647 // Print a space if this is an "identifier operator" like __real, or if
1648 // it might be concatenated incorrectly like '+'.
1649 switch (Node->getOpcode()) {
1650 default: break;
1651 case UO_Real:
1652 case UO_Imag:
1653 case UO_Extension:
1654 OS << ' ';
1655 break;
1656 case UO_Plus:
1657 case UO_Minus:
1658 if (isa<UnaryOperator>(Val: Node->getSubExpr()))
1659 OS << ' ';
1660 break;
1661 }
1662 }
1663 PrintExpr(E: Node->getSubExpr());
1664
1665 if (Node->isPostfix())
1666 OS << UnaryOperator::getOpcodeStr(Op: Node->getOpcode());
1667}
1668
1669void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
1670 OS << "__builtin_offsetof(";
1671 Node->getTypeSourceInfo()->getType().print(OS, Policy);
1672 OS << ", ";
1673 bool PrintedSomething = false;
1674 for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) {
1675 OffsetOfNode ON = Node->getComponent(Idx: i);
1676 if (ON.getKind() == OffsetOfNode::Array) {
1677 // Array node
1678 OS << "[";
1679 PrintExpr(E: Node->getIndexExpr(Idx: ON.getArrayExprIndex()));
1680 OS << "]";
1681 PrintedSomething = true;
1682 continue;
1683 }
1684
1685 // Skip implicit base indirections.
1686 if (ON.getKind() == OffsetOfNode::Base)
1687 continue;
1688
1689 // Field or identifier node.
1690 const IdentifierInfo *Id = ON.getFieldName();
1691 if (!Id)
1692 continue;
1693
1694 if (PrintedSomething)
1695 OS << ".";
1696 else
1697 PrintedSomething = true;
1698 OS << Id->getName();
1699 }
1700 OS << ")";
1701}
1702
1703void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(
1704 UnaryExprOrTypeTraitExpr *Node) {
1705 const char *Spelling = getTraitSpelling(T: Node->getKind());
1706 if (Node->getKind() == UETT_AlignOf) {
1707 if (Policy.Alignof)
1708 Spelling = "alignof";
1709 else if (Policy.UnderscoreAlignof)
1710 Spelling = "_Alignof";
1711 else
1712 Spelling = "__alignof";
1713 }
1714
1715 OS << Spelling;
1716
1717 if (Node->isArgumentType()) {
1718 OS << '(';
1719 Node->getArgumentType().print(OS, Policy);
1720 OS << ')';
1721 } else {
1722 OS << " ";
1723 PrintExpr(E: Node->getArgumentExpr());
1724 }
1725}
1726
1727void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) {
1728 OS << "_Generic(";
1729 if (Node->isExprPredicate())
1730 PrintExpr(E: Node->getControllingExpr());
1731 else
1732 Node->getControllingType()->getType().print(OS, Policy);
1733
1734 for (const GenericSelectionExpr::Association &Assoc : Node->associations()) {
1735 OS << ", ";
1736 QualType T = Assoc.getType();
1737 if (T.isNull())
1738 OS << "default";
1739 else
1740 T.print(OS, Policy);
1741 OS << ": ";
1742 PrintExpr(E: Assoc.getAssociationExpr());
1743 }
1744 OS << ")";
1745}
1746
1747void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) {
1748 PrintExpr(E: Node->getLHS());
1749 OS << "[";
1750 PrintExpr(E: Node->getRHS());
1751 OS << "]";
1752}
1753
1754void StmtPrinter::VisitMatrixSingleSubscriptExpr(
1755 MatrixSingleSubscriptExpr *Node) {
1756 PrintExpr(E: Node->getBase());
1757 OS << "[";
1758 PrintExpr(E: Node->getRowIdx());
1759 OS << "]";
1760}
1761
1762void StmtPrinter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *Node) {
1763 PrintExpr(E: Node->getBase());
1764 OS << "[";
1765 PrintExpr(E: Node->getRowIdx());
1766 OS << "]";
1767 OS << "[";
1768 PrintExpr(E: Node->getColumnIdx());
1769 OS << "]";
1770}
1771
1772void StmtPrinter::VisitArraySectionExpr(ArraySectionExpr *Node) {
1773 PrintExpr(E: Node->getBase());
1774 OS << "[";
1775 if (Node->getLowerBound())
1776 PrintExpr(E: Node->getLowerBound());
1777 if (Node->getColonLocFirst().isValid()) {
1778 OS << ":";
1779 if (Node->getLength())
1780 PrintExpr(E: Node->getLength());
1781 }
1782 if (Node->isOMPArraySection() && Node->getColonLocSecond().isValid()) {
1783 OS << ":";
1784 if (Node->getStride())
1785 PrintExpr(E: Node->getStride());
1786 }
1787 OS << "]";
1788}
1789
1790void StmtPrinter::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *Node) {
1791 OS << "(";
1792 for (Expr *E : Node->getDimensions()) {
1793 OS << "[";
1794 PrintExpr(E);
1795 OS << "]";
1796 }
1797 OS << ")";
1798 PrintExpr(E: Node->getBase());
1799}
1800
1801void StmtPrinter::VisitOMPIteratorExpr(OMPIteratorExpr *Node) {
1802 OS << "iterator(";
1803 for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
1804 auto *VD = cast<ValueDecl>(Val: Node->getIteratorDecl(I));
1805 VD->getType().print(OS, Policy);
1806 const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
1807 OS << " " << VD->getName() << " = ";
1808 PrintExpr(E: Range.Begin);
1809 OS << ":";
1810 PrintExpr(E: Range.End);
1811 if (Range.Step) {
1812 OS << ":";
1813 PrintExpr(E: Range.Step);
1814 }
1815 if (I < E - 1)
1816 OS << ", ";
1817 }
1818 OS << ")";
1819}
1820
1821void StmtPrinter::PrintCallArgs(CallExpr *Call) {
1822 for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) {
1823 if (isa<CXXDefaultArgExpr>(Val: Call->getArg(Arg: i))) {
1824 // Don't print any defaulted arguments
1825 break;
1826 }
1827
1828 if (i) OS << ", ";
1829 PrintExpr(E: Call->getArg(Arg: i));
1830 }
1831}
1832
1833void StmtPrinter::VisitCallExpr(CallExpr *Call) {
1834 PrintExpr(E: Call->getCallee());
1835 OS << "(";
1836 PrintCallArgs(Call);
1837 OS << ")";
1838}
1839
1840static bool isImplicitThis(const Expr *E) {
1841 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E))
1842 return TE->isImplicit();
1843 return false;
1844}
1845
1846void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
1847 if (!Policy.SuppressImplicitBase || !isImplicitThis(E: Node->getBase())) {
1848 PrintExpr(E: Node->getBase());
1849
1850 auto *ParentMember = dyn_cast<MemberExpr>(Val: Node->getBase());
1851 FieldDecl *ParentDecl =
1852 ParentMember ? dyn_cast<FieldDecl>(Val: ParentMember->getMemberDecl())
1853 : nullptr;
1854
1855 if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
1856 OS << (Node->isArrow() ? "->" : ".");
1857 }
1858
1859 if (auto *FD = dyn_cast<FieldDecl>(Val: Node->getMemberDecl()))
1860 if (FD->isAnonymousStructOrUnion())
1861 return;
1862
1863 Node->getQualifier().print(OS, Policy);
1864 if (Node->hasTemplateKeyword())
1865 OS << "template ";
1866 OS << Node->getMemberNameInfo();
1867 const TemplateParameterList *TPL = nullptr;
1868 if (auto *FD = dyn_cast<FunctionDecl>(Val: Node->getMemberDecl())) {
1869 if (!Node->hadMultipleCandidates())
1870 if (auto *FTD = FD->getPrimaryTemplate())
1871 TPL = FTD->getTemplateParameters();
1872 } else if (auto *VTSD =
1873 dyn_cast<VarTemplateSpecializationDecl>(Val: Node->getMemberDecl()))
1874 TPL = VTSD->getSpecializedTemplate()->getTemplateParameters();
1875 if (Node->hasExplicitTemplateArgs())
1876 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy, TPL);
1877}
1878
1879void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
1880 PrintExpr(E: Node->getBase());
1881 OS << (Node->isArrow() ? "->isa" : ".isa");
1882}
1883
1884void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
1885 PrintExpr(E: Node->getBase());
1886 OS << ".";
1887 OS << Node->getAccessor().getName();
1888}
1889
1890void StmtPrinter::VisitMatrixElementExpr(MatrixElementExpr *Node) {
1891 PrintExpr(E: Node->getBase());
1892 OS << ".";
1893 OS << Node->getAccessor().getName();
1894}
1895
1896void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
1897 if (QualType T = Node->getType(); Policy.PrettyEnums && T->isEnumeralType()) {
1898 // special case enums to avoid producing cast expressions when naming
1899 // an enumerator would suffice
1900
1901 const auto *IL = dyn_cast<IntegerLiteral>(Val: Node->getSubExpr());
1902 const auto *ED = T->getAsEnumDecl();
1903 if (IL && ED) {
1904 llvm::APInt Val = IL->getValue();
1905 const auto ECD =
1906 llvm::find_if(Range: ED->enumerators(), P: [&](const EnumConstantDecl *ECD) {
1907 return llvm::APInt::isSameValue(I1: ECD->getInitVal(), I2: Val);
1908 });
1909 if (ECD != ED->enumerator_end()) {
1910 ECD->printQualifiedName(OS, Policy);
1911 return;
1912 }
1913 }
1914 }
1915 OS << '(';
1916 Node->getTypeAsWritten().print(OS, Policy);
1917 OS << ')';
1918 PrintExpr(E: Node->getSubExpr());
1919}
1920
1921void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) {
1922 OS << '(';
1923 Node->getType().print(OS, Policy);
1924 OS << ')';
1925 PrintExpr(E: Node->getInitializer());
1926}
1927
1928void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
1929 // No need to print anything, simply forward to the subexpression.
1930 PrintExpr(E: Node->getSubExpr());
1931}
1932
1933void StmtPrinter::VisitBinComma(BinaryOperator *Node) {
1934 PrintExpr(E: Node->getLHS());
1935 OS << BinaryOperator::getOpcodeStr(Op: Node->getOpcode()) << " ";
1936 PrintExpr(E: Node->getRHS());
1937}
1938
1939void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) {
1940 PrintExpr(E: Node->getLHS());
1941 OS << " " << BinaryOperator::getOpcodeStr(Op: Node->getOpcode()) << " ";
1942 PrintExpr(E: Node->getRHS());
1943}
1944
1945void StmtPrinter::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
1946 PrintExpr(E: Node->getLHS());
1947 OS << " " << BinaryOperator::getOpcodeStr(Op: Node->getOpcode()) << " ";
1948 PrintExpr(E: Node->getRHS());
1949}
1950
1951void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) {
1952 PrintExpr(E: Node->getCond());
1953 OS << " ? ";
1954 PrintExpr(E: Node->getLHS());
1955 OS << " : ";
1956 PrintExpr(E: Node->getRHS());
1957}
1958
1959// GNU extensions.
1960
1961void
1962StmtPrinter::VisitBinaryConditionalOperator(BinaryConditionalOperator *Node) {
1963 PrintExpr(E: Node->getCommon());
1964 OS << " ?: ";
1965 PrintExpr(E: Node->getFalseExpr());
1966}
1967
1968void StmtPrinter::VisitAddrLabelExpr(AddrLabelExpr *Node) {
1969 OS << "&&" << Node->getLabel()->getName();
1970}
1971
1972void StmtPrinter::VisitStmtExpr(StmtExpr *E) {
1973 OS << "(";
1974 PrintRawCompoundStmt(Node: E->getSubStmt());
1975 OS << ")";
1976}
1977
1978void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) {
1979 OS << "__builtin_choose_expr(";
1980 PrintExpr(E: Node->getCond());
1981 OS << ", ";
1982 PrintExpr(E: Node->getLHS());
1983 OS << ", ";
1984 PrintExpr(E: Node->getRHS());
1985 OS << ")";
1986}
1987
1988void StmtPrinter::VisitGNUNullExpr(GNUNullExpr *) {
1989 OS << "__null";
1990}
1991
1992void StmtPrinter::VisitShuffleVectorExpr(ShuffleVectorExpr *Node) {
1993 OS << "__builtin_shufflevector(";
1994 for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) {
1995 if (i) OS << ", ";
1996 PrintExpr(E: Node->getExpr(Index: i));
1997 }
1998 OS << ")";
1999}
2000
2001void StmtPrinter::VisitConvertVectorExpr(ConvertVectorExpr *Node) {
2002 OS << "__builtin_convertvector(";
2003 PrintExpr(E: Node->getSrcExpr());
2004 OS << ", ";
2005 Node->getType().print(OS, Policy);
2006 OS << ")";
2007}
2008
2009void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
2010 if (Node->getSyntacticForm()) {
2011 Visit(S: Node->getSyntacticForm());
2012 return;
2013 }
2014
2015 OS << "{";
2016 for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) {
2017 if (i) OS << ", ";
2018 if (Node->getInit(Init: i))
2019 PrintExpr(E: Node->getInit(Init: i));
2020 else
2021 OS << "{}";
2022 }
2023 OS << "}";
2024}
2025
2026void StmtPrinter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *Node) {
2027 // There's no way to express this expression in any of our supported
2028 // languages, so just emit something terse and (hopefully) clear.
2029 OS << "{";
2030 PrintExpr(E: Node->getSubExpr());
2031 OS << "}";
2032}
2033
2034void StmtPrinter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *Node) {
2035 OS << "*";
2036}
2037
2038void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) {
2039 OS << "(";
2040 for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) {
2041 if (i) OS << ", ";
2042 PrintExpr(E: Node->getExpr(Init: i));
2043 }
2044 OS << ")";
2045}
2046
2047void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) {
2048 bool NeedsEquals = true;
2049 for (const DesignatedInitExpr::Designator &D : Node->designators()) {
2050 if (D.isFieldDesignator()) {
2051 if (D.getDotLoc().isInvalid()) {
2052 if (const IdentifierInfo *II = D.getFieldName()) {
2053 OS << II->getName() << ":";
2054 NeedsEquals = false;
2055 }
2056 } else {
2057 OS << "." << D.getFieldName()->getName();
2058 }
2059 } else {
2060 OS << "[";
2061 if (D.isArrayDesignator()) {
2062 PrintExpr(E: Node->getArrayIndex(D));
2063 } else {
2064 PrintExpr(E: Node->getArrayRangeStart(D));
2065 OS << " ... ";
2066 PrintExpr(E: Node->getArrayRangeEnd(D));
2067 }
2068 OS << "]";
2069 }
2070 }
2071
2072 if (NeedsEquals)
2073 OS << " = ";
2074 else
2075 OS << " ";
2076 PrintExpr(E: Node->getInit());
2077}
2078
2079void StmtPrinter::VisitDesignatedInitUpdateExpr(
2080 DesignatedInitUpdateExpr *Node) {
2081 OS << "{";
2082 OS << "/*base*/";
2083 PrintExpr(E: Node->getBase());
2084 OS << ", ";
2085
2086 OS << "/*updater*/";
2087 PrintExpr(E: Node->getUpdater());
2088 OS << "}";
2089}
2090
2091void StmtPrinter::VisitNoInitExpr(NoInitExpr *Node) {
2092 OS << "/*no init*/";
2093}
2094
2095void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) {
2096 if (Node->getType()->getAsCXXRecordDecl()) {
2097 OS << "/*implicit*/";
2098 Node->getType().print(OS, Policy);
2099 OS << "()";
2100 } else {
2101 OS << "/*implicit*/(";
2102 Node->getType().print(OS, Policy);
2103 OS << ')';
2104 if (Node->getType()->isRecordType())
2105 OS << "{}";
2106 else
2107 OS << 0;
2108 }
2109}
2110
2111void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {
2112 OS << "__builtin_va_arg(";
2113 PrintExpr(E: Node->getSubExpr());
2114 OS << ", ";
2115 Node->getType().print(OS, Policy);
2116 OS << ")";
2117}
2118
2119void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) {
2120 PrintExpr(E: Node->getSyntacticForm());
2121}
2122
2123void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
2124 const char *Name = nullptr;
2125 switch (Node->getOp()) {
2126#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
2127 case AtomicExpr::AO ## ID: \
2128 Name = #ID "("; \
2129 break;
2130#include "clang/Basic/Builtins.inc"
2131 }
2132 OS << Name;
2133
2134 // AtomicExpr stores its subexpressions in a permuted order.
2135 PrintExpr(E: Node->getPtr());
2136 if (Node->hasVal1Operand()) {
2137 OS << ", ";
2138 PrintExpr(E: Node->getVal1());
2139 }
2140 if (Node->getOp() == AtomicExpr::AO__atomic_exchange ||
2141 Node->isCmpXChg()) {
2142 OS << ", ";
2143 PrintExpr(E: Node->getVal2());
2144 }
2145 if (Node->getOp() == AtomicExpr::AO__atomic_compare_exchange ||
2146 Node->getOp() == AtomicExpr::AO__atomic_compare_exchange_n) {
2147 OS << ", ";
2148 PrintExpr(E: Node->getWeak());
2149 }
2150 if (Node->getOp() != AtomicExpr::AO__c11_atomic_init &&
2151 Node->getOp() != AtomicExpr::AO__opencl_atomic_init) {
2152 OS << ", ";
2153 PrintExpr(E: Node->getOrder());
2154 }
2155 if (Node->isCmpXChg()) {
2156 OS << ", ";
2157 PrintExpr(E: Node->getOrderFail());
2158 }
2159 OS << ")";
2160}
2161
2162// C++
2163void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
2164 OverloadedOperatorKind Kind = Node->getOperator();
2165 if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
2166 if (Node->getNumArgs() == 1) {
2167 OS << getOperatorSpelling(Operator: Kind) << ' ';
2168 PrintExpr(E: Node->getArg(Arg: 0));
2169 } else {
2170 PrintExpr(E: Node->getArg(Arg: 0));
2171 OS << ' ' << getOperatorSpelling(Operator: Kind);
2172 }
2173 } else if (Kind == OO_Arrow) {
2174 PrintExpr(E: Node->getArg(Arg: 0));
2175 } else if (Kind == OO_Call || Kind == OO_Subscript) {
2176 PrintExpr(E: Node->getArg(Arg: 0));
2177 OS << (Kind == OO_Call ? '(' : '[');
2178 for (unsigned ArgIdx = 1; ArgIdx < Node->getNumArgs(); ++ArgIdx) {
2179 if (ArgIdx > 1)
2180 OS << ", ";
2181 if (!isa<CXXDefaultArgExpr>(Val: Node->getArg(Arg: ArgIdx)))
2182 PrintExpr(E: Node->getArg(Arg: ArgIdx));
2183 }
2184 OS << (Kind == OO_Call ? ')' : ']');
2185 } else if (Node->getNumArgs() == 1) {
2186 OS << getOperatorSpelling(Operator: Kind) << ' ';
2187 PrintExpr(E: Node->getArg(Arg: 0));
2188 } else if (Node->getNumArgs() == 2) {
2189 PrintExpr(E: Node->getArg(Arg: 0));
2190 OS << ' ' << getOperatorSpelling(Operator: Kind) << ' ';
2191 PrintExpr(E: Node->getArg(Arg: 1));
2192 } else {
2193 llvm_unreachable("unknown overloaded operator");
2194 }
2195}
2196
2197void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {
2198 // If we have a conversion operator call only print the argument.
2199 CXXMethodDecl *MD = Node->getMethodDecl();
2200 if (isa_and_nonnull<CXXConversionDecl>(Val: MD)) {
2201 PrintExpr(E: Node->getImplicitObjectArgument());
2202 return;
2203 }
2204 VisitCallExpr(Call: cast<CallExpr>(Val: Node));
2205}
2206
2207void StmtPrinter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *Node) {
2208 PrintExpr(E: Node->getCallee());
2209 OS << "<<<";
2210 PrintCallArgs(Call: Node->getConfig());
2211 OS << ">>>(";
2212 PrintCallArgs(Call: Node);
2213 OS << ")";
2214}
2215
2216void StmtPrinter::VisitCXXRewrittenBinaryOperator(
2217 CXXRewrittenBinaryOperator *Node) {
2218 CXXRewrittenBinaryOperator::DecomposedForm Decomposed =
2219 Node->getDecomposedForm();
2220 PrintExpr(E: const_cast<Expr*>(Decomposed.LHS));
2221 OS << ' ' << BinaryOperator::getOpcodeStr(Op: Decomposed.Opcode) << ' ';
2222 PrintExpr(E: const_cast<Expr*>(Decomposed.RHS));
2223}
2224
2225void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
2226 OS << Node->getCastName() << '<';
2227 Node->getTypeAsWritten().print(OS, Policy);
2228 OS << ">(";
2229 PrintExpr(E: Node->getSubExpr());
2230 OS << ")";
2231}
2232
2233void StmtPrinter::VisitCXXStaticCastExpr(CXXStaticCastExpr *Node) {
2234 VisitCXXNamedCastExpr(Node);
2235}
2236
2237void StmtPrinter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *Node) {
2238 VisitCXXNamedCastExpr(Node);
2239}
2240
2241void StmtPrinter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *Node) {
2242 VisitCXXNamedCastExpr(Node);
2243}
2244
2245void StmtPrinter::VisitCXXConstCastExpr(CXXConstCastExpr *Node) {
2246 VisitCXXNamedCastExpr(Node);
2247}
2248
2249void StmtPrinter::VisitBuiltinBitCastExpr(BuiltinBitCastExpr *Node) {
2250 OS << "__builtin_bit_cast(";
2251 Node->getTypeInfoAsWritten()->getType().print(OS, Policy);
2252 OS << ", ";
2253 PrintExpr(E: Node->getSubExpr());
2254 OS << ")";
2255}
2256
2257void StmtPrinter::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *Node) {
2258 VisitCXXNamedCastExpr(Node);
2259}
2260
2261void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
2262 OS << "typeid(";
2263 if (Node->isTypeOperand()) {
2264 Node->getTypeOperandSourceInfo()->getType().print(OS, Policy);
2265 } else {
2266 PrintExpr(E: Node->getExprOperand());
2267 }
2268 OS << ")";
2269}
2270
2271void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) {
2272 OS << "__uuidof(";
2273 if (Node->isTypeOperand()) {
2274 Node->getTypeOperandSourceInfo()->getType().print(OS, Policy);
2275 } else {
2276 PrintExpr(E: Node->getExprOperand());
2277 }
2278 OS << ")";
2279}
2280
2281void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
2282 PrintExpr(E: Node->getBaseExpr());
2283 if (Node->isArrow())
2284 OS << "->";
2285 else
2286 OS << ".";
2287 Node->getQualifierLoc().getNestedNameSpecifier().print(OS, Policy);
2288 OS << Node->getPropertyDecl()->getDeclName();
2289}
2290
2291void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) {
2292 PrintExpr(E: Node->getBase());
2293 OS << "[";
2294 PrintExpr(E: Node->getIdx());
2295 OS << "]";
2296}
2297
2298void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
2299 switch (Node->getLiteralOperatorKind()) {
2300 case UserDefinedLiteral::LOK_Raw:
2301 OS << cast<StringLiteral>(Val: Node->getArg(Arg: 0)->IgnoreImpCasts())->getString();
2302 break;
2303 case UserDefinedLiteral::LOK_Template: {
2304 const auto *DRE = cast<DeclRefExpr>(Val: Node->getCallee()->IgnoreImpCasts());
2305 const TemplateArgumentList *Args =
2306 cast<FunctionDecl>(Val: DRE->getDecl())->getTemplateSpecializationArgs();
2307 assert(Args);
2308
2309 if (Args->size() != 1 || Args->get(Idx: 0).getKind() != TemplateArgument::Pack) {
2310 const TemplateParameterList *TPL = nullptr;
2311 if (!DRE->hadMultipleCandidates())
2312 if (const auto *TD = dyn_cast<TemplateDecl>(Val: DRE->getDecl()))
2313 TPL = TD->getTemplateParameters();
2314 OS << "operator\"\"" << Node->getUDSuffix()->getName();
2315 printTemplateArgumentList(OS, Args: Args->asArray(), Policy, TPL);
2316 OS << "()";
2317 return;
2318 }
2319
2320 const TemplateArgument &Pack = Args->get(Idx: 0);
2321 for (const auto &P : Pack.pack_elements()) {
2322 char C = (char)P.getAsIntegral().getZExtValue();
2323 OS << C;
2324 }
2325 break;
2326 }
2327 case UserDefinedLiteral::LOK_Integer: {
2328 // Print integer literal without suffix.
2329 const auto *Int = cast<IntegerLiteral>(Val: Node->getCookedLiteral());
2330 OS << toString(I: Int->getValue(), Radix: 10, /*isSigned*/Signed: false);
2331 break;
2332 }
2333 case UserDefinedLiteral::LOK_Floating: {
2334 // Print floating literal without suffix.
2335 auto *Float = cast<FloatingLiteral>(Val: Node->getCookedLiteral());
2336 PrintFloatingLiteral(OS, Node: Float, /*PrintSuffix=*/false);
2337 break;
2338 }
2339 case UserDefinedLiteral::LOK_String:
2340 case UserDefinedLiteral::LOK_Character:
2341 PrintExpr(E: Node->getCookedLiteral());
2342 break;
2343 }
2344 OS << Node->getUDSuffix()->getName();
2345}
2346
2347void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
2348 OS << (Node->getValue() ? "true" : "false");
2349}
2350
2351void StmtPrinter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *Node) {
2352 OS << "nullptr";
2353}
2354
2355void StmtPrinter::VisitCXXThisExpr(CXXThisExpr *Node) {
2356 OS << "this";
2357}
2358
2359void StmtPrinter::VisitCXXThrowExpr(CXXThrowExpr *Node) {
2360 if (!Node->getSubExpr())
2361 OS << "throw";
2362 else {
2363 OS << "throw ";
2364 PrintExpr(E: Node->getSubExpr());
2365 }
2366}
2367
2368void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) {
2369 // Nothing to print: we picked up the default argument.
2370}
2371
2372void StmtPrinter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Node) {
2373 // Nothing to print: we picked up the default initializer.
2374}
2375
2376void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
2377 auto TargetType = Node->getType();
2378 auto *Auto = TargetType->getContainedDeducedType();
2379 bool Bare = Auto && Auto->isDeduced();
2380
2381 // Parenthesize deduced casts.
2382 if (Bare)
2383 OS << '(';
2384 TargetType.print(OS, Policy);
2385 if (Bare)
2386 OS << ')';
2387
2388 // No extra braces surrounding the inner construct.
2389 if (!Node->isListInitialization())
2390 OS << '(';
2391 PrintExpr(E: Node->getSubExpr());
2392 if (!Node->isListInitialization())
2393 OS << ')';
2394}
2395
2396void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
2397 PrintExpr(E: Node->getSubExpr());
2398}
2399
2400void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
2401 Node->getType().print(OS, Policy);
2402 if (Node->isStdInitListInitialization())
2403 /* Nothing to do; braces are part of creating the std::initializer_list. */;
2404 else if (Node->isListInitialization())
2405 OS << "{";
2406 else
2407 OS << "(";
2408 for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(),
2409 ArgEnd = Node->arg_end();
2410 Arg != ArgEnd; ++Arg) {
2411 if ((*Arg)->isDefaultArgument())
2412 break;
2413 if (Arg != Node->arg_begin())
2414 OS << ", ";
2415 PrintExpr(E: *Arg);
2416 }
2417 if (Node->isStdInitListInitialization())
2418 /* See above. */;
2419 else if (Node->isListInitialization())
2420 OS << "}";
2421 else
2422 OS << ")";
2423}
2424
2425void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
2426 OS << '[';
2427 bool NeedComma = false;
2428 switch (Node->getCaptureDefault()) {
2429 case LCD_None:
2430 break;
2431
2432 case LCD_ByCopy:
2433 OS << '=';
2434 NeedComma = true;
2435 break;
2436
2437 case LCD_ByRef:
2438 OS << '&';
2439 NeedComma = true;
2440 break;
2441 }
2442 for (LambdaExpr::capture_iterator C = Node->explicit_capture_begin(),
2443 CEnd = Node->explicit_capture_end();
2444 C != CEnd;
2445 ++C) {
2446 if (C->capturesVLAType())
2447 continue;
2448
2449 if (NeedComma)
2450 OS << ", ";
2451 NeedComma = true;
2452
2453 switch (C->getCaptureKind()) {
2454 case LCK_This:
2455 OS << "this";
2456 break;
2457
2458 case LCK_StarThis:
2459 OS << "*this";
2460 break;
2461
2462 case LCK_ByRef:
2463 if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(Capture: C))
2464 OS << '&';
2465 OS << C->getCapturedVar()->getName();
2466 break;
2467
2468 case LCK_ByCopy:
2469 OS << C->getCapturedVar()->getName();
2470 break;
2471
2472 case LCK_VLAType:
2473 llvm_unreachable("VLA type in explicit captures.");
2474 }
2475
2476 if (C->isPackExpansion())
2477 OS << "...";
2478
2479 if (Node->isInitCapture(Capture: C)) {
2480 // Init captures are always VarDecl.
2481 auto *D = cast<VarDecl>(Val: C->getCapturedVar());
2482
2483 llvm::StringRef Pre;
2484 llvm::StringRef Post;
2485 if (D->getInitStyle() == VarDecl::CallInit &&
2486 !isa<ParenListExpr>(Val: D->getInit())) {
2487 Pre = "(";
2488 Post = ")";
2489 } else if (D->getInitStyle() == VarDecl::CInit) {
2490 Pre = " = ";
2491 }
2492
2493 OS << Pre;
2494 PrintExpr(E: D->getInit());
2495 OS << Post;
2496 }
2497 }
2498 OS << ']';
2499
2500 if (!Node->getExplicitTemplateParameters().empty()) {
2501 Node->getTemplateParameterList()->print(
2502 Out&: OS, Context: Node->getLambdaClass()->getASTContext(),
2503 /*OmitTemplateKW*/true);
2504 }
2505
2506 if (Node->hasExplicitParameters()) {
2507 OS << '(';
2508 CXXMethodDecl *Method = Node->getCallOperator();
2509 NeedComma = false;
2510 for (const auto *P : Method->parameters()) {
2511 if (NeedComma) {
2512 OS << ", ";
2513 } else {
2514 NeedComma = true;
2515 }
2516 std::string ParamStr =
2517 (Policy.CleanUglifiedParameters && P->getIdentifier())
2518 ? P->getIdentifier()->deuglifiedName().str()
2519 : P->getNameAsString();
2520 P->getOriginalType().print(OS, Policy, PlaceHolder: ParamStr);
2521 }
2522 if (Method->isVariadic()) {
2523 if (NeedComma)
2524 OS << ", ";
2525 OS << "...";
2526 }
2527 OS << ')';
2528
2529 if (Node->isMutable())
2530 OS << " mutable";
2531
2532 auto *Proto = Method->getType()->castAs<FunctionProtoType>();
2533 Proto->printExceptionSpecification(OS, Policy);
2534
2535 // FIXME: Attributes
2536
2537 // Print the trailing return type if it was specified in the source.
2538 if (Node->hasExplicitResultType()) {
2539 OS << " -> ";
2540 Proto->getReturnType().print(OS, Policy);
2541 }
2542 }
2543
2544 // Print the body.
2545 OS << ' ';
2546 if (Policy.TerseOutput || Policy.SuppressLambdaBody)
2547 OS << "{}";
2548 else
2549 PrintRawCompoundStmt(Node: Node->getCompoundStmtBody());
2550}
2551
2552void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) {
2553 if (TypeSourceInfo *TSInfo = Node->getTypeSourceInfo())
2554 TSInfo->getType().print(OS, Policy);
2555 else
2556 Node->getType().print(OS, Policy);
2557 OS << "()";
2558}
2559
2560void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
2561 if (E->isGlobalNew())
2562 OS << "::";
2563 OS << "new ";
2564 unsigned NumPlace = E->getNumPlacementArgs();
2565 if (NumPlace > 0 && !isa<CXXDefaultArgExpr>(Val: E->getPlacementArg(I: 0))) {
2566 OS << "(";
2567 PrintExpr(E: E->getPlacementArg(I: 0));
2568 for (unsigned i = 1; i < NumPlace; ++i) {
2569 if (isa<CXXDefaultArgExpr>(Val: E->getPlacementArg(I: i)))
2570 break;
2571 OS << ", ";
2572 PrintExpr(E: E->getPlacementArg(I: i));
2573 }
2574 OS << ") ";
2575 }
2576 if (E->isParenTypeId())
2577 OS << "(";
2578 std::string TypeS;
2579 if (E->isArray()) {
2580 llvm::raw_string_ostream s(TypeS);
2581 s << '[';
2582 if (std::optional<Expr *> Size = E->getArraySize())
2583 (*Size)->printPretty(OS&: s, Helper, Policy);
2584 s << ']';
2585 }
2586 E->getAllocatedType().print(OS, Policy, PlaceHolder: TypeS);
2587 if (E->isParenTypeId())
2588 OS << ")";
2589
2590 CXXNewInitializationStyle InitStyle = E->getInitializationStyle();
2591 if (InitStyle != CXXNewInitializationStyle::None) {
2592 bool Bare = InitStyle == CXXNewInitializationStyle::Parens &&
2593 !isa<ParenListExpr>(Val: E->getInitializer());
2594 if (Bare)
2595 OS << "(";
2596 PrintExpr(E: E->getInitializer());
2597 if (Bare)
2598 OS << ")";
2599 }
2600}
2601
2602void StmtPrinter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
2603 if (E->isGlobalDelete())
2604 OS << "::";
2605 OS << "delete ";
2606 if (E->isArrayForm())
2607 OS << "[] ";
2608 PrintExpr(E: E->getArgument());
2609}
2610
2611void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
2612 PrintExpr(E: E->getBase());
2613 if (E->isArrow())
2614 OS << "->";
2615 else
2616 OS << '.';
2617 E->getQualifier().print(OS, Policy);
2618 OS << "~";
2619
2620 if (const IdentifierInfo *II = E->getDestroyedTypeIdentifier())
2621 OS << II->getName();
2622 else
2623 E->getDestroyedType().print(OS, Policy);
2624}
2625
2626void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
2627 if (E->isListInitialization() && !E->isStdInitListInitialization())
2628 OS << "{";
2629
2630 for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
2631 if (isa<CXXDefaultArgExpr>(Val: E->getArg(Arg: i))) {
2632 // Don't print any defaulted arguments
2633 break;
2634 }
2635
2636 if (i) OS << ", ";
2637 PrintExpr(E: E->getArg(Arg: i));
2638 }
2639
2640 if (E->isListInitialization() && !E->isStdInitListInitialization())
2641 OS << "}";
2642}
2643
2644void StmtPrinter::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E) {
2645 // Parens are printed by the surrounding context.
2646 OS << "<forwarded>";
2647}
2648
2649void StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
2650 PrintExpr(E: E->getSubExpr());
2651}
2652
2653void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) {
2654 // Just forward to the subexpression.
2655 PrintExpr(E: E->getSubExpr());
2656}
2657
2658void StmtPrinter::VisitCXXUnresolvedConstructExpr(
2659 CXXUnresolvedConstructExpr *Node) {
2660 Node->getTypeAsWritten().print(OS, Policy);
2661 if (!Node->isListInitialization())
2662 OS << '(';
2663 for (auto Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); Arg != ArgEnd;
2664 ++Arg) {
2665 if (Arg != Node->arg_begin())
2666 OS << ", ";
2667 PrintExpr(E: *Arg);
2668 }
2669 if (!Node->isListInitialization())
2670 OS << ')';
2671}
2672
2673void StmtPrinter::VisitCXXReflectExpr(CXXReflectExpr *S) {
2674 // TODO(Reflection): Implement this.
2675 assert(false && "not implemented yet");
2676}
2677
2678void StmtPrinter::VisitDependentTemplateIdExpr(DependentTemplateIdExpr *Node) {
2679 Node->getTemplateName().print(OS, Policy, Qual: TemplateName::Qualified::None);
2680 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy,
2681 TPL: Node->getParameter()->getTemplateParameters());
2682}
2683
2684void StmtPrinter::VisitCXXDependentScopeMemberExpr(
2685 CXXDependentScopeMemberExpr *Node) {
2686 if (!Node->isImplicitAccess()) {
2687 PrintExpr(E: Node->getBase());
2688 OS << (Node->isArrow() ? "->" : ".");
2689 }
2690 Node->getQualifier().print(OS, Policy);
2691 if (Node->hasTemplateKeyword())
2692 OS << "template ";
2693 OS << Node->getMemberNameInfo();
2694 if (Node->hasExplicitTemplateArgs())
2695 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy);
2696}
2697
2698void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
2699 if (!Node->isImplicitAccess()) {
2700 PrintExpr(E: Node->getBase());
2701 OS << (Node->isArrow() ? "->" : ".");
2702 }
2703 Node->getQualifier().print(OS, Policy);
2704 if (Node->hasTemplateKeyword())
2705 OS << "template ";
2706 OS << Node->getMemberNameInfo();
2707 if (Node->hasExplicitTemplateArgs())
2708 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy);
2709}
2710
2711void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) {
2712 OS << getTraitSpelling(T: E->getTrait()) << "(";
2713 for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
2714 if (I > 0)
2715 OS << ", ";
2716 E->getArg(I)->getType().print(OS, Policy);
2717 }
2718 OS << ")";
2719}
2720
2721void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
2722 OS << getTraitSpelling(T: E->getTrait()) << '(';
2723 E->getQueriedType().print(OS, Policy);
2724 OS << ')';
2725}
2726
2727void StmtPrinter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
2728 OS << getTraitSpelling(T: E->getTrait()) << '(';
2729 PrintExpr(E: E->getQueriedExpression());
2730 OS << ')';
2731}
2732
2733void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
2734 OS << "noexcept(";
2735 PrintExpr(E: E->getOperand());
2736 OS << ")";
2737}
2738
2739void StmtPrinter::VisitPackExpansionExpr(PackExpansionExpr *E) {
2740 PrintExpr(E: E->getPattern());
2741 OS << "...";
2742}
2743
2744void StmtPrinter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
2745 OS << "sizeof...(" << *E->getPack() << ")";
2746}
2747
2748void StmtPrinter::VisitPackIndexingExpr(PackIndexingExpr *E) {
2749 PrintExpr(E: E->getPackIdExpression());
2750 OS << "...[";
2751 PrintExpr(E: E->getIndexExpr());
2752 OS << "]";
2753}
2754
2755void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr(
2756 SubstNonTypeTemplateParmPackExpr *Node) {
2757 OS << *Node->getParameterPack();
2758}
2759
2760void StmtPrinter::VisitSubstNonTypeTemplateParmExpr(
2761 SubstNonTypeTemplateParmExpr *Node) {
2762 Visit(S: Node->getReplacement());
2763}
2764
2765void StmtPrinter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
2766 OS << *E->getParameterPack();
2767}
2768
2769void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
2770 PrintExpr(E: Node->getSubExpr());
2771}
2772
2773void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) {
2774 OS << "(";
2775 if (E->getLHS()) {
2776 PrintExpr(E: E->getLHS());
2777 OS << " " << BinaryOperator::getOpcodeStr(Op: E->getOperator()) << " ";
2778 }
2779 OS << "...";
2780 if (E->getRHS()) {
2781 OS << " " << BinaryOperator::getOpcodeStr(Op: E->getOperator()) << " ";
2782 PrintExpr(E: E->getRHS());
2783 }
2784 OS << ")";
2785}
2786
2787void StmtPrinter::VisitCXXParenListInitExpr(CXXParenListInitExpr *Node) {
2788 llvm::interleaveComma(c: Node->getUserSpecifiedInitExprs(), os&: OS,
2789 each_fn: [&](Expr *E) { PrintExpr(E); });
2790}
2791
2792void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
2793 NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc();
2794 NNS.getNestedNameSpecifier().print(OS, Policy);
2795 if (E->getTemplateKWLoc().isValid())
2796 OS << "template ";
2797 OS << E->getFoundDecl()->getName();
2798 printTemplateArgumentList(OS, Args: E->getTemplateArgsAsWritten()->arguments(),
2799 Policy,
2800 TPL: E->getConceptDecl()->getTemplateParameters());
2801}
2802
2803void StmtPrinter::VisitRequiresExpr(RequiresExpr *E) {
2804 OS << "requires ";
2805 auto LocalParameters = E->getLocalParameters();
2806 if (!LocalParameters.empty()) {
2807 OS << "(";
2808 for (ParmVarDecl *LocalParam : LocalParameters) {
2809 PrintRawDecl(D: LocalParam);
2810 if (LocalParam != LocalParameters.back())
2811 OS << ", ";
2812 }
2813
2814 OS << ") ";
2815 }
2816 OS << "{ ";
2817 auto Requirements = E->getRequirements();
2818 for (concepts::Requirement *Req : Requirements) {
2819 if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Val: Req)) {
2820 if (TypeReq->isSubstitutionFailure())
2821 OS << "<<error-type>>";
2822 else
2823 TypeReq->getType()->getType().print(OS, Policy);
2824 } else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Val: Req)) {
2825 if (ExprReq->isCompound())
2826 OS << "{ ";
2827 if (ExprReq->isExprSubstitutionFailure())
2828 OS << "<<error-expression>>";
2829 else
2830 PrintExpr(E: ExprReq->getExpr());
2831 if (ExprReq->isCompound()) {
2832 OS << " }";
2833 if (ExprReq->getNoexceptLoc().isValid())
2834 OS << " noexcept";
2835 const auto &RetReq = ExprReq->getReturnTypeRequirement();
2836 if (!RetReq.isEmpty()) {
2837 OS << " -> ";
2838 if (RetReq.isSubstitutionFailure())
2839 OS << "<<error-type>>";
2840 else if (RetReq.isTypeConstraint())
2841 RetReq.getTypeConstraint()->print(OS, Policy);
2842 }
2843 }
2844 } else {
2845 auto *NestedReq = cast<concepts::NestedRequirement>(Val: Req);
2846 OS << "requires ";
2847 if (NestedReq->hasInvalidConstraint())
2848 OS << "<<error-expression>>";
2849 else
2850 PrintExpr(E: NestedReq->getConstraintExpr());
2851 }
2852 OS << "; ";
2853 }
2854 OS << "}";
2855}
2856
2857// C++ Coroutines
2858
2859void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
2860 Visit(S: S->getBody());
2861}
2862
2863void StmtPrinter::VisitCoreturnStmt(CoreturnStmt *S) {
2864 OS << "co_return";
2865 if (S->getOperand()) {
2866 OS << " ";
2867 Visit(S: S->getOperand());
2868 }
2869 OS << ";";
2870}
2871
2872void StmtPrinter::VisitCoawaitExpr(CoawaitExpr *S) {
2873 OS << "co_await ";
2874 PrintExpr(E: S->getOperand());
2875}
2876
2877void StmtPrinter::VisitDependentCoawaitExpr(DependentCoawaitExpr *S) {
2878 OS << "co_await ";
2879 PrintExpr(E: S->getOperand());
2880}
2881
2882void StmtPrinter::VisitCoyieldExpr(CoyieldExpr *S) {
2883 OS << "co_yield ";
2884 PrintExpr(E: S->getOperand());
2885}
2886
2887// Obj-C
2888
2889void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
2890 OS << "@";
2891 VisitStringLiteral(Str: Node->getString());
2892}
2893
2894void StmtPrinter::VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
2895 OS << "@";
2896 Visit(S: E->getSubExpr());
2897}
2898
2899void StmtPrinter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
2900 OS << "@[ ";
2901 ObjCArrayLiteral::child_range Ch = E->children();
2902 for (auto I = Ch.begin(), E = Ch.end(); I != E; ++I) {
2903 if (I != Ch.begin())
2904 OS << ", ";
2905 Visit(S: *I);
2906 }
2907 OS << " ]";
2908}
2909
2910void StmtPrinter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
2911 OS << "@{ ";
2912 for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
2913 if (I > 0)
2914 OS << ", ";
2915
2916 ObjCDictionaryElement Element = E->getKeyValueElement(Index: I);
2917 Visit(S: Element.Key);
2918 OS << " : ";
2919 Visit(S: Element.Value);
2920 if (Element.isPackExpansion())
2921 OS << "...";
2922 }
2923 OS << " }";
2924}
2925
2926void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
2927 OS << "@encode(";
2928 Node->getEncodedType().print(OS, Policy);
2929 OS << ')';
2930}
2931
2932void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
2933 OS << "@selector(";
2934 Node->getSelector().print(OS);
2935 OS << ')';
2936}
2937
2938void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
2939 OS << "@protocol(" << *Node->getProtocol() << ')';
2940}
2941
2942void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
2943 OS << "[";
2944 switch (Mess->getReceiverKind()) {
2945 case ObjCMessageExpr::Instance:
2946 PrintExpr(E: Mess->getInstanceReceiver());
2947 break;
2948
2949 case ObjCMessageExpr::Class:
2950 Mess->getClassReceiver().print(OS, Policy);
2951 break;
2952
2953 case ObjCMessageExpr::SuperInstance:
2954 case ObjCMessageExpr::SuperClass:
2955 OS << "Super";
2956 break;
2957 }
2958
2959 OS << ' ';
2960 Selector selector = Mess->getSelector();
2961 if (selector.isUnarySelector()) {
2962 OS << selector.getNameForSlot(argIndex: 0);
2963 } else {
2964 for (unsigned i = 0, e = Mess->getNumArgs(); i != e; ++i) {
2965 if (i < selector.getNumArgs()) {
2966 if (i > 0) OS << ' ';
2967 if (selector.getIdentifierInfoForSlot(argIndex: i))
2968 OS << selector.getIdentifierInfoForSlot(argIndex: i)->getName() << ':';
2969 else
2970 OS << ":";
2971 }
2972 else OS << ", "; // Handle variadic methods.
2973
2974 PrintExpr(E: Mess->getArg(Arg: i));
2975 }
2976 }
2977 OS << "]";
2978}
2979
2980void StmtPrinter::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) {
2981 OS << (Node->getValue() ? "__objc_yes" : "__objc_no");
2982}
2983
2984void
2985StmtPrinter::VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) {
2986 PrintExpr(E: E->getSubExpr());
2987}
2988
2989void
2990StmtPrinter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) {
2991 OS << '(' << E->getBridgeKindName();
2992 E->getType().print(OS, Policy);
2993 OS << ')';
2994 PrintExpr(E: E->getSubExpr());
2995}
2996
2997void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
2998 BlockDecl *BD = Node->getBlockDecl();
2999 OS << "^";
3000
3001 const FunctionType *AFT = Node->getFunctionType();
3002
3003 if (isa<FunctionNoProtoType>(Val: AFT)) {
3004 OS << "()";
3005 } else if (!BD->param_empty() || cast<FunctionProtoType>(Val: AFT)->isVariadic()) {
3006 OS << '(';
3007 for (BlockDecl::param_iterator AI = BD->param_begin(),
3008 E = BD->param_end(); AI != E; ++AI) {
3009 if (AI != BD->param_begin()) OS << ", ";
3010 std::string ParamStr = (*AI)->getNameAsString();
3011 (*AI)->getType().print(OS, Policy, PlaceHolder: ParamStr);
3012 }
3013
3014 const auto *FT = cast<FunctionProtoType>(Val: AFT);
3015 if (FT->isVariadic()) {
3016 if (!BD->param_empty()) OS << ", ";
3017 OS << "...";
3018 }
3019 OS << ')';
3020 }
3021 OS << "{ }";
3022}
3023
3024void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
3025 PrintExpr(E: Node->getSourceExpr());
3026}
3027
3028void StmtPrinter::VisitRecoveryExpr(RecoveryExpr *Node) {
3029 OS << "<recovery-expr>(";
3030 const char *Sep = "";
3031 for (Expr *E : Node->subExpressions()) {
3032 OS << Sep;
3033 PrintExpr(E);
3034 Sep = ", ";
3035 }
3036 OS << ')';
3037}
3038
3039void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) {
3040 OS << "__builtin_astype(";
3041 PrintExpr(E: Node->getSrcExpr());
3042 OS << ", ";
3043 Node->getType().print(OS, Policy);
3044 OS << ")";
3045}
3046
3047void StmtPrinter::VisitHLSLOutArgExpr(HLSLOutArgExpr *Node) {
3048 PrintExpr(E: Node->getArgLValue());
3049}
3050
3051//===----------------------------------------------------------------------===//
3052// Stmt method implementations
3053//===----------------------------------------------------------------------===//
3054
3055void Stmt::dumpPretty(const ASTContext &Context) const {
3056 printPretty(OS&: llvm::errs(), Helper: nullptr, Policy: PrintingPolicy(Context.getLangOpts()));
3057}
3058
3059void Stmt::printPretty(raw_ostream &Out, PrinterHelper *Helper,
3060 const PrintingPolicy &Policy, unsigned Indentation,
3061 StringRef NL, const ASTContext *Context) const {
3062 StmtPrinter P(Out, Helper, Policy, Indentation, NL, Context);
3063 P.Visit(S: const_cast<Stmt *>(this));
3064}
3065
3066void Stmt::printPrettyControlled(raw_ostream &Out, PrinterHelper *Helper,
3067 const PrintingPolicy &Policy,
3068 unsigned Indentation, StringRef NL,
3069 const ASTContext *Context) const {
3070 StmtPrinter P(Out, Helper, Policy, Indentation, NL, Context);
3071 P.PrintControlledStmt(S: const_cast<Stmt *>(this));
3072}
3073
3074void Stmt::printJson(raw_ostream &Out, PrinterHelper *Helper,
3075 const PrintingPolicy &Policy, bool AddQuotes) const {
3076 std::string Buf;
3077 llvm::raw_string_ostream TempOut(Buf);
3078
3079 printPretty(Out&: TempOut, Helper, Policy);
3080
3081 Out << JsonFormat(RawSR: TempOut.str(), AddQuotes);
3082}
3083
3084//===----------------------------------------------------------------------===//
3085// PrinterHelper
3086//===----------------------------------------------------------------------===//
3087
3088// Implement virtual destructor.
3089PrinterHelper::~PrinterHelper() = default;
3090