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::VisitOMPFlattenDirective(OMPFlattenDirective *Node) {
838 Indent() << "#pragma omp flatten";
839 PrintOMPExecutableDirective(S: Node);
840}
841
842void StmtPrinter::VisitOMPSplitDirective(OMPSplitDirective *Node) {
843 Indent() << "#pragma omp split";
844 PrintOMPExecutableDirective(S: Node);
845}
846
847void StmtPrinter::VisitOMPFuseDirective(OMPFuseDirective *Node) {
848 Indent() << "#pragma omp fuse";
849 PrintOMPExecutableDirective(S: Node);
850}
851
852void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) {
853 Indent() << "#pragma omp for";
854 PrintOMPExecutableDirective(S: Node);
855}
856
857void StmtPrinter::VisitOMPForSimdDirective(OMPForSimdDirective *Node) {
858 Indent() << "#pragma omp for simd";
859 PrintOMPExecutableDirective(S: Node);
860}
861
862void StmtPrinter::VisitOMPSectionsDirective(OMPSectionsDirective *Node) {
863 Indent() << "#pragma omp sections";
864 PrintOMPExecutableDirective(S: Node);
865}
866
867void StmtPrinter::VisitOMPSectionDirective(OMPSectionDirective *Node) {
868 Indent() << "#pragma omp section";
869 PrintOMPExecutableDirective(S: Node);
870}
871
872void StmtPrinter::VisitOMPScopeDirective(OMPScopeDirective *Node) {
873 Indent() << "#pragma omp scope";
874 PrintOMPExecutableDirective(S: Node);
875}
876
877void StmtPrinter::VisitOMPSingleDirective(OMPSingleDirective *Node) {
878 Indent() << "#pragma omp single";
879 PrintOMPExecutableDirective(S: Node);
880}
881
882void StmtPrinter::VisitOMPMasterDirective(OMPMasterDirective *Node) {
883 Indent() << "#pragma omp master";
884 PrintOMPExecutableDirective(S: Node);
885}
886
887void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) {
888 Indent() << "#pragma omp critical";
889 if (Node->getDirectiveName().getName()) {
890 OS << " (";
891 Node->getDirectiveName().printName(OS, Policy);
892 OS << ")";
893 }
894 PrintOMPExecutableDirective(S: Node);
895}
896
897void StmtPrinter::VisitOMPParallelForDirective(OMPParallelForDirective *Node) {
898 Indent() << "#pragma omp parallel for";
899 PrintOMPExecutableDirective(S: Node);
900}
901
902void StmtPrinter::VisitOMPParallelForSimdDirective(
903 OMPParallelForSimdDirective *Node) {
904 Indent() << "#pragma omp parallel for simd";
905 PrintOMPExecutableDirective(S: Node);
906}
907
908void StmtPrinter::VisitOMPParallelMasterDirective(
909 OMPParallelMasterDirective *Node) {
910 Indent() << "#pragma omp parallel master";
911 PrintOMPExecutableDirective(S: Node);
912}
913
914void StmtPrinter::VisitOMPParallelMaskedDirective(
915 OMPParallelMaskedDirective *Node) {
916 Indent() << "#pragma omp parallel masked";
917 PrintOMPExecutableDirective(S: Node);
918}
919
920void StmtPrinter::VisitOMPParallelSectionsDirective(
921 OMPParallelSectionsDirective *Node) {
922 Indent() << "#pragma omp parallel sections";
923 PrintOMPExecutableDirective(S: Node);
924}
925
926void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) {
927 Indent() << "#pragma omp task";
928 PrintOMPExecutableDirective(S: Node);
929}
930
931void StmtPrinter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *Node) {
932 Indent() << "#pragma omp taskyield";
933 PrintOMPExecutableDirective(S: Node);
934}
935
936void StmtPrinter::VisitOMPBarrierDirective(OMPBarrierDirective *Node) {
937 Indent() << "#pragma omp barrier";
938 PrintOMPExecutableDirective(S: Node);
939}
940
941void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) {
942 Indent() << "#pragma omp taskwait";
943 PrintOMPExecutableDirective(S: Node);
944}
945
946void StmtPrinter::VisitOMPAssumeDirective(OMPAssumeDirective *Node) {
947 Indent() << "#pragma omp assume";
948 PrintOMPExecutableDirective(S: Node);
949}
950
951void StmtPrinter::VisitOMPErrorDirective(OMPErrorDirective *Node) {
952 Indent() << "#pragma omp error";
953 PrintOMPExecutableDirective(S: Node);
954}
955
956void StmtPrinter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *Node) {
957 Indent() << "#pragma omp taskgroup";
958 PrintOMPExecutableDirective(S: Node);
959}
960
961void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) {
962 Indent() << "#pragma omp flush";
963 PrintOMPExecutableDirective(S: Node);
964}
965
966void StmtPrinter::VisitOMPDepobjDirective(OMPDepobjDirective *Node) {
967 Indent() << "#pragma omp depobj";
968 PrintOMPExecutableDirective(S: Node);
969}
970
971void StmtPrinter::VisitOMPScanDirective(OMPScanDirective *Node) {
972 Indent() << "#pragma omp scan";
973 PrintOMPExecutableDirective(S: Node);
974}
975
976void StmtPrinter::VisitOMPOrderedStandaloneDirective(
977 OMPOrderedStandaloneDirective *Node) {
978 Indent() << "#pragma omp ordered";
979 PrintOMPExecutableDirective(S: Node, ForceNoStmt: true);
980}
981
982void StmtPrinter::VisitOMPOrderedBlockAssocDirective(
983 OMPOrderedBlockAssocDirective *Node) {
984 Indent() << "#pragma omp ordered";
985 PrintOMPExecutableDirective(S: Node);
986}
987
988void StmtPrinter::VisitOMPAtomicDirective(OMPAtomicDirective *Node) {
989 Indent() << "#pragma omp atomic";
990 PrintOMPExecutableDirective(S: Node);
991}
992
993void StmtPrinter::VisitOMPTargetDirective(OMPTargetDirective *Node) {
994 Indent() << "#pragma omp target";
995 PrintOMPExecutableDirective(S: Node);
996}
997
998void StmtPrinter::VisitOMPTargetDataDirective(OMPTargetDataDirective *Node) {
999 Indent() << "#pragma omp target data";
1000 PrintOMPExecutableDirective(S: Node);
1001}
1002
1003void StmtPrinter::VisitOMPTargetEnterDataDirective(
1004 OMPTargetEnterDataDirective *Node) {
1005 Indent() << "#pragma omp target enter data";
1006 PrintOMPExecutableDirective(S: Node, /*ForceNoStmt=*/true);
1007}
1008
1009void StmtPrinter::VisitOMPTargetExitDataDirective(
1010 OMPTargetExitDataDirective *Node) {
1011 Indent() << "#pragma omp target exit data";
1012 PrintOMPExecutableDirective(S: Node, /*ForceNoStmt=*/true);
1013}
1014
1015void StmtPrinter::VisitOMPTargetParallelDirective(
1016 OMPTargetParallelDirective *Node) {
1017 Indent() << "#pragma omp target parallel";
1018 PrintOMPExecutableDirective(S: Node);
1019}
1020
1021void StmtPrinter::VisitOMPTargetParallelForDirective(
1022 OMPTargetParallelForDirective *Node) {
1023 Indent() << "#pragma omp target parallel for";
1024 PrintOMPExecutableDirective(S: Node);
1025}
1026
1027void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
1028 Indent() << "#pragma omp teams";
1029 PrintOMPExecutableDirective(S: Node);
1030}
1031
1032void StmtPrinter::VisitOMPCancellationPointDirective(
1033 OMPCancellationPointDirective *Node) {
1034 llvm::omp::Version OpenMPVersion =
1035 Context ? Context->getLangOpts().getOpenMPVersion()
1036 : llvm::omp::FallbackVersion;
1037 Indent() << "#pragma omp cancellation point "
1038 << getOpenMPDirectiveName(D: Node->getCancelRegion(), V: OpenMPVersion);
1039 PrintOMPExecutableDirective(S: Node);
1040}
1041
1042void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) {
1043 llvm::omp::Version OpenMPVersion =
1044 Context ? Context->getLangOpts().getOpenMPVersion()
1045 : llvm::omp::FallbackVersion;
1046 Indent() << "#pragma omp cancel "
1047 << getOpenMPDirectiveName(D: Node->getCancelRegion(), V: OpenMPVersion);
1048 PrintOMPExecutableDirective(S: Node);
1049}
1050
1051void StmtPrinter::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *Node) {
1052 Indent() << "#pragma omp taskloop";
1053 PrintOMPExecutableDirective(S: Node);
1054}
1055
1056void StmtPrinter::VisitOMPTaskLoopSimdDirective(
1057 OMPTaskLoopSimdDirective *Node) {
1058 Indent() << "#pragma omp taskloop simd";
1059 PrintOMPExecutableDirective(S: Node);
1060}
1061
1062void StmtPrinter::VisitOMPMasterTaskLoopDirective(
1063 OMPMasterTaskLoopDirective *Node) {
1064 Indent() << "#pragma omp master taskloop";
1065 PrintOMPExecutableDirective(S: Node);
1066}
1067
1068void StmtPrinter::VisitOMPMaskedTaskLoopDirective(
1069 OMPMaskedTaskLoopDirective *Node) {
1070 Indent() << "#pragma omp masked taskloop";
1071 PrintOMPExecutableDirective(S: Node);
1072}
1073
1074void StmtPrinter::VisitOMPMasterTaskLoopSimdDirective(
1075 OMPMasterTaskLoopSimdDirective *Node) {
1076 Indent() << "#pragma omp master taskloop simd";
1077 PrintOMPExecutableDirective(S: Node);
1078}
1079
1080void StmtPrinter::VisitOMPMaskedTaskLoopSimdDirective(
1081 OMPMaskedTaskLoopSimdDirective *Node) {
1082 Indent() << "#pragma omp masked taskloop simd";
1083 PrintOMPExecutableDirective(S: Node);
1084}
1085
1086void StmtPrinter::VisitOMPParallelMasterTaskLoopDirective(
1087 OMPParallelMasterTaskLoopDirective *Node) {
1088 Indent() << "#pragma omp parallel master taskloop";
1089 PrintOMPExecutableDirective(S: Node);
1090}
1091
1092void StmtPrinter::VisitOMPParallelMaskedTaskLoopDirective(
1093 OMPParallelMaskedTaskLoopDirective *Node) {
1094 Indent() << "#pragma omp parallel masked taskloop";
1095 PrintOMPExecutableDirective(S: Node);
1096}
1097
1098void StmtPrinter::VisitOMPParallelMasterTaskLoopSimdDirective(
1099 OMPParallelMasterTaskLoopSimdDirective *Node) {
1100 Indent() << "#pragma omp parallel master taskloop simd";
1101 PrintOMPExecutableDirective(S: Node);
1102}
1103
1104void StmtPrinter::VisitOMPParallelMaskedTaskLoopSimdDirective(
1105 OMPParallelMaskedTaskLoopSimdDirective *Node) {
1106 Indent() << "#pragma omp parallel masked taskloop simd";
1107 PrintOMPExecutableDirective(S: Node);
1108}
1109
1110void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) {
1111 Indent() << "#pragma omp distribute";
1112 PrintOMPExecutableDirective(S: Node);
1113}
1114
1115void StmtPrinter::VisitOMPTargetUpdateDirective(
1116 OMPTargetUpdateDirective *Node) {
1117 Indent() << "#pragma omp target update";
1118 PrintOMPExecutableDirective(S: Node, /*ForceNoStmt=*/true);
1119}
1120
1121void StmtPrinter::VisitOMPDistributeParallelForDirective(
1122 OMPDistributeParallelForDirective *Node) {
1123 Indent() << "#pragma omp distribute parallel for";
1124 PrintOMPExecutableDirective(S: Node);
1125}
1126
1127void StmtPrinter::VisitOMPDistributeParallelForSimdDirective(
1128 OMPDistributeParallelForSimdDirective *Node) {
1129 Indent() << "#pragma omp distribute parallel for simd";
1130 PrintOMPExecutableDirective(S: Node);
1131}
1132
1133void StmtPrinter::VisitOMPDistributeSimdDirective(
1134 OMPDistributeSimdDirective *Node) {
1135 Indent() << "#pragma omp distribute simd";
1136 PrintOMPExecutableDirective(S: Node);
1137}
1138
1139void StmtPrinter::VisitOMPTargetParallelForSimdDirective(
1140 OMPTargetParallelForSimdDirective *Node) {
1141 Indent() << "#pragma omp target parallel for simd";
1142 PrintOMPExecutableDirective(S: Node);
1143}
1144
1145void StmtPrinter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *Node) {
1146 Indent() << "#pragma omp target simd";
1147 PrintOMPExecutableDirective(S: Node);
1148}
1149
1150void StmtPrinter::VisitOMPTeamsDistributeDirective(
1151 OMPTeamsDistributeDirective *Node) {
1152 Indent() << "#pragma omp teams distribute";
1153 PrintOMPExecutableDirective(S: Node);
1154}
1155
1156void StmtPrinter::VisitOMPTeamsDistributeSimdDirective(
1157 OMPTeamsDistributeSimdDirective *Node) {
1158 Indent() << "#pragma omp teams distribute simd";
1159 PrintOMPExecutableDirective(S: Node);
1160}
1161
1162void StmtPrinter::VisitOMPTeamsDistributeParallelForSimdDirective(
1163 OMPTeamsDistributeParallelForSimdDirective *Node) {
1164 Indent() << "#pragma omp teams distribute parallel for simd";
1165 PrintOMPExecutableDirective(S: Node);
1166}
1167
1168void StmtPrinter::VisitOMPTeamsDistributeParallelForDirective(
1169 OMPTeamsDistributeParallelForDirective *Node) {
1170 Indent() << "#pragma omp teams distribute parallel for";
1171 PrintOMPExecutableDirective(S: Node);
1172}
1173
1174void StmtPrinter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *Node) {
1175 Indent() << "#pragma omp target teams";
1176 PrintOMPExecutableDirective(S: Node);
1177}
1178
1179void StmtPrinter::VisitOMPTargetTeamsDistributeDirective(
1180 OMPTargetTeamsDistributeDirective *Node) {
1181 Indent() << "#pragma omp target teams distribute";
1182 PrintOMPExecutableDirective(S: Node);
1183}
1184
1185void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForDirective(
1186 OMPTargetTeamsDistributeParallelForDirective *Node) {
1187 Indent() << "#pragma omp target teams distribute parallel for";
1188 PrintOMPExecutableDirective(S: Node);
1189}
1190
1191void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForSimdDirective(
1192 OMPTargetTeamsDistributeParallelForSimdDirective *Node) {
1193 Indent() << "#pragma omp target teams distribute parallel for simd";
1194 PrintOMPExecutableDirective(S: Node);
1195}
1196
1197void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective(
1198 OMPTargetTeamsDistributeSimdDirective *Node) {
1199 Indent() << "#pragma omp target teams distribute simd";
1200 PrintOMPExecutableDirective(S: Node);
1201}
1202
1203void StmtPrinter::VisitOMPInteropDirective(OMPInteropDirective *Node) {
1204 Indent() << "#pragma omp interop";
1205 PrintOMPExecutableDirective(S: Node);
1206}
1207
1208void StmtPrinter::VisitOMPDispatchDirective(OMPDispatchDirective *Node) {
1209 Indent() << "#pragma omp dispatch";
1210 PrintOMPExecutableDirective(S: Node);
1211}
1212
1213void StmtPrinter::VisitOMPMaskedDirective(OMPMaskedDirective *Node) {
1214 Indent() << "#pragma omp masked";
1215 PrintOMPExecutableDirective(S: Node);
1216}
1217
1218void StmtPrinter::VisitOMPGenericLoopDirective(OMPGenericLoopDirective *Node) {
1219 Indent() << "#pragma omp loop";
1220 PrintOMPExecutableDirective(S: Node);
1221}
1222
1223void StmtPrinter::VisitOMPTeamsGenericLoopDirective(
1224 OMPTeamsGenericLoopDirective *Node) {
1225 Indent() << "#pragma omp teams loop";
1226 PrintOMPExecutableDirective(S: Node);
1227}
1228
1229void StmtPrinter::VisitOMPTargetTeamsGenericLoopDirective(
1230 OMPTargetTeamsGenericLoopDirective *Node) {
1231 Indent() << "#pragma omp target teams loop";
1232 PrintOMPExecutableDirective(S: Node);
1233}
1234
1235void StmtPrinter::VisitOMPParallelGenericLoopDirective(
1236 OMPParallelGenericLoopDirective *Node) {
1237 Indent() << "#pragma omp parallel loop";
1238 PrintOMPExecutableDirective(S: Node);
1239}
1240
1241void StmtPrinter::VisitOMPTargetParallelGenericLoopDirective(
1242 OMPTargetParallelGenericLoopDirective *Node) {
1243 Indent() << "#pragma omp target parallel loop";
1244 PrintOMPExecutableDirective(S: Node);
1245}
1246
1247//===----------------------------------------------------------------------===//
1248// OpenACC construct printing methods
1249//===----------------------------------------------------------------------===//
1250void StmtPrinter::PrintOpenACCClauseList(OpenACCConstructStmt *S) {
1251 if (!S->clauses().empty()) {
1252 OS << ' ';
1253 OpenACCClausePrinter Printer(OS, Policy);
1254 Printer.VisitClauseList(List: S->clauses());
1255 }
1256}
1257void StmtPrinter::PrintOpenACCConstruct(OpenACCConstructStmt *S) {
1258 Indent() << "#pragma acc " << S->getDirectiveKind();
1259 PrintOpenACCClauseList(S);
1260 OS << '\n';
1261}
1262void StmtPrinter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) {
1263 PrintOpenACCConstruct(S);
1264 PrintStmt(S: S->getStructuredBlock());
1265}
1266
1267void StmtPrinter::VisitOpenACCLoopConstruct(OpenACCLoopConstruct *S) {
1268 PrintOpenACCConstruct(S);
1269 PrintStmt(S: S->getLoop());
1270}
1271
1272void StmtPrinter::VisitOpenACCCombinedConstruct(OpenACCCombinedConstruct *S) {
1273 PrintOpenACCConstruct(S);
1274 PrintStmt(S: S->getLoop());
1275}
1276
1277void StmtPrinter::VisitOpenACCDataConstruct(OpenACCDataConstruct *S) {
1278 PrintOpenACCConstruct(S);
1279 PrintStmt(S: S->getStructuredBlock());
1280}
1281void StmtPrinter::VisitOpenACCHostDataConstruct(OpenACCHostDataConstruct *S) {
1282 PrintOpenACCConstruct(S);
1283 PrintStmt(S: S->getStructuredBlock());
1284}
1285void StmtPrinter::VisitOpenACCEnterDataConstruct(OpenACCEnterDataConstruct *S) {
1286 PrintOpenACCConstruct(S);
1287}
1288void StmtPrinter::VisitOpenACCExitDataConstruct(OpenACCExitDataConstruct *S) {
1289 PrintOpenACCConstruct(S);
1290}
1291void StmtPrinter::VisitOpenACCInitConstruct(OpenACCInitConstruct *S) {
1292 PrintOpenACCConstruct(S);
1293}
1294void StmtPrinter::VisitOpenACCShutdownConstruct(OpenACCShutdownConstruct *S) {
1295 PrintOpenACCConstruct(S);
1296}
1297void StmtPrinter::VisitOpenACCSetConstruct(OpenACCSetConstruct *S) {
1298 PrintOpenACCConstruct(S);
1299}
1300void StmtPrinter::VisitOpenACCUpdateConstruct(OpenACCUpdateConstruct *S) {
1301 PrintOpenACCConstruct(S);
1302}
1303
1304void StmtPrinter::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) {
1305 Indent() << "#pragma acc wait";
1306 if (!S->getLParenLoc().isInvalid()) {
1307 OS << "(";
1308 if (S->hasDevNumExpr()) {
1309 OS << "devnum: ";
1310 S->getDevNumExpr()->printPretty(OS, Helper: nullptr, Policy);
1311 OS << " : ";
1312 }
1313
1314 if (S->hasQueuesTag())
1315 OS << "queues: ";
1316
1317 llvm::interleaveComma(c: S->getQueueIdExprs(), os&: OS, each_fn: [&](const Expr *E) {
1318 E->printPretty(OS, Helper: nullptr, Policy);
1319 });
1320
1321 OS << ")";
1322 }
1323
1324 PrintOpenACCClauseList(S);
1325 OS << '\n';
1326}
1327
1328void StmtPrinter::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
1329 Indent() << "#pragma acc atomic";
1330
1331 if (S->getAtomicKind() != OpenACCAtomicKind::None)
1332 OS << " " << S->getAtomicKind();
1333
1334 PrintOpenACCClauseList(S);
1335 OS << '\n';
1336 PrintStmt(S: S->getAssociatedStmt());
1337}
1338
1339void StmtPrinter::VisitOpenACCCacheConstruct(OpenACCCacheConstruct *S) {
1340 Indent() << "#pragma acc cache(";
1341 if (S->hasReadOnly())
1342 OS << "readonly: ";
1343
1344 llvm::interleaveComma(c: S->getVarList(), os&: OS, each_fn: [&](const Expr *E) {
1345 E->printPretty(OS, Helper: nullptr, Policy);
1346 });
1347
1348 OS << ")\n";
1349}
1350
1351//===----------------------------------------------------------------------===//
1352// Expr printing methods.
1353//===----------------------------------------------------------------------===//
1354
1355void StmtPrinter::VisitSourceLocExpr(SourceLocExpr *Node) {
1356 OS << Node->getBuiltinStr() << "()";
1357}
1358
1359void StmtPrinter::VisitEmbedExpr(EmbedExpr *Node) {
1360 // FIXME: Embed parameters are not reflected in the AST, so there is no way to
1361 // print them yet.
1362 OS << "#embed ";
1363 OS << Node->getFileName();
1364 OS << NL;
1365}
1366
1367void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {
1368 PrintExpr(E: Node->getSubExpr());
1369}
1370
1371void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
1372 ValueDecl *VD = Node->getDecl();
1373 if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Val: VD)) {
1374 OCED->getInit()->IgnoreImpCasts()->printPretty(OS, Helper: nullptr, Policy);
1375 return;
1376 }
1377 if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(Val: VD)) {
1378 TPOD->printAsExpr(OS, Policy);
1379 return;
1380 }
1381 bool ForceAnonymous =
1382 Policy.PrintAsCanonical && VD->getKind() == Decl::NonTypeTemplateParm;
1383 bool CleanUglifiedParameter = Policy.CleanUglifiedParameters &&
1384 isa<ParmVarDecl, NonTypeTemplateParmDecl>(Val: VD);
1385
1386 if (Policy.FullyQualifiedName && !ForceAnonymous && !CleanUglifiedParameter &&
1387 !VD->isTemplateParameter()) {
1388 VD->printQualifiedName(OS, Policy);
1389 } else {
1390 Node->getQualifier().print(OS, Policy);
1391 if (Node->hasTemplateKeyword())
1392 OS << "template ";
1393
1394 DeclarationNameInfo NameInfo = Node->getNameInfo();
1395 if (IdentifierInfo *ID = NameInfo.getName().getAsIdentifierInfo();
1396 !ForceAnonymous && (ID || NameInfo.getName().getNameKind() !=
1397 DeclarationName::Identifier)) {
1398 if (CleanUglifiedParameter && ID)
1399 OS << ID->deuglifiedName();
1400 else
1401 NameInfo.printName(OS, Policy);
1402 } else {
1403 switch (VD->getKind()) {
1404 case Decl::NonTypeTemplateParm: {
1405 auto *TD = cast<NonTypeTemplateParmDecl>(Val: VD);
1406 OS << "value-parameter-" << TD->getDepth() << '-' << TD->getIndex()
1407 << "";
1408 break;
1409 }
1410 case Decl::ParmVar: {
1411 auto *PD = cast<ParmVarDecl>(Val: VD);
1412 OS << "function-parameter-" << PD->getFunctionScopeDepth() << '-'
1413 << PD->getFunctionScopeIndex();
1414 break;
1415 }
1416 case Decl::Decomposition:
1417 OS << "decomposition";
1418 for (const auto &I : cast<DecompositionDecl>(Val: VD)->bindings())
1419 OS << '-' << I->getName();
1420 break;
1421 default:
1422 OS << "unhandled-anonymous-" << VD->getDeclKindName();
1423 break;
1424 }
1425 }
1426 }
1427 if (Node->hasExplicitTemplateArgs()) {
1428 const TemplateParameterList *TPL = nullptr;
1429 if (!Node->hadMultipleCandidates())
1430 if (auto *TD = dyn_cast<TemplateDecl>(Val: VD))
1431 TPL = TD->getTemplateParameters();
1432 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy, TPL);
1433 }
1434}
1435
1436void StmtPrinter::VisitDependentScopeDeclRefExpr(
1437 DependentScopeDeclRefExpr *Node) {
1438 Node->getQualifier().print(OS, Policy);
1439 if (Node->hasTemplateKeyword())
1440 OS << "template ";
1441 OS << Node->getNameInfo();
1442 if (Node->hasExplicitTemplateArgs())
1443 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy);
1444}
1445
1446void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
1447 Node->getQualifier().print(OS, Policy);
1448 if (Node->hasTemplateKeyword())
1449 OS << "template ";
1450 OS << Node->getNameInfo();
1451 if (Node->hasExplicitTemplateArgs())
1452 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy);
1453}
1454
1455static bool isImplicitSelf(const Expr *E) {
1456 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E)) {
1457 if (const auto *PD = dyn_cast<ImplicitParamDecl>(Val: DRE->getDecl())) {
1458 if (PD->getParameterKind() == ImplicitParamKind::ObjCSelf &&
1459 DRE->getBeginLoc().isInvalid())
1460 return true;
1461 }
1462 }
1463 return false;
1464}
1465
1466void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
1467 if (Node->getBase()) {
1468 if (!Policy.SuppressImplicitBase ||
1469 !isImplicitSelf(E: Node->getBase()->IgnoreImpCasts())) {
1470 PrintExpr(E: Node->getBase());
1471 OS << (Node->isArrow() ? "->" : ".");
1472 }
1473 }
1474 OS << *Node->getDecl();
1475}
1476
1477void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
1478 if (Node->isSuperReceiver())
1479 OS << "super.";
1480 else if (Node->isObjectReceiver() && Node->getBase()) {
1481 PrintExpr(E: Node->getBase());
1482 OS << ".";
1483 } else if (Node->isClassReceiver() && Node->getClassReceiver()) {
1484 OS << Node->getClassReceiver()->getName() << ".";
1485 }
1486
1487 if (Node->isImplicitProperty()) {
1488 if (const auto *Getter = Node->getImplicitPropertyGetter())
1489 Getter->getSelector().print(OS);
1490 else
1491 OS << SelectorTable::getPropertyNameFromSetterSelector(
1492 Sel: Node->getImplicitPropertySetter()->getSelector());
1493 } else
1494 OS << Node->getExplicitProperty()->getName();
1495}
1496
1497void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
1498 PrintExpr(E: Node->getBaseExpr());
1499 OS << "[";
1500 PrintExpr(E: Node->getKeyExpr());
1501 OS << "]";
1502}
1503
1504void StmtPrinter::VisitSYCLUniqueStableNameExpr(
1505 SYCLUniqueStableNameExpr *Node) {
1506 OS << "__builtin_sycl_unique_stable_name(";
1507 Node->getTypeSourceInfo()->getType().print(OS, Policy);
1508 OS << ")";
1509}
1510
1511void StmtPrinter::VisitUnresolvedSYCLKernelCallStmt(
1512 UnresolvedSYCLKernelCallStmt *Node) {
1513 PrintStmt(S: Node->getOriginalStmt());
1514}
1515
1516void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
1517 OS << PredefinedExpr::getIdentKindName(IK: Node->getIdentKind());
1518}
1519
1520void StmtPrinter::VisitOpenACCAsteriskSizeExpr(OpenACCAsteriskSizeExpr *Node) {
1521 OS << '*';
1522}
1523
1524void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
1525 CharacterLiteral::print(val: Node->getValue(), Kind: Node->getKind(), OS);
1526}
1527
1528/// Prints the given expression using the original source text. Returns true on
1529/// success, false otherwise.
1530static bool printExprAsWritten(raw_ostream &OS, Expr *E,
1531 const ASTContext *Context) {
1532 if (!Context)
1533 return false;
1534 bool Invalid = false;
1535 StringRef Source = Lexer::getSourceText(
1536 Range: CharSourceRange::getTokenRange(R: E->getSourceRange()),
1537 SM: Context->getSourceManager(), LangOpts: Context->getLangOpts(), Invalid: &Invalid);
1538 if (!Invalid) {
1539 OS << Source;
1540 return true;
1541 }
1542 return false;
1543}
1544
1545void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
1546 if (Policy.ConstantsAsWritten && printExprAsWritten(OS, E: Node, Context))
1547 return;
1548 bool isSigned = Node->getType()->isSignedIntegerType();
1549 OS << toString(I: Node->getValue(), Radix: 10, Signed: isSigned);
1550
1551 if (isa<BitIntType>(Val: Node->getType())) {
1552 OS << (isSigned ? "wb" : "uwb");
1553 return;
1554 }
1555
1556 // Emit suffixes. Integer literals are always a builtin integer type.
1557 switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
1558 default: llvm_unreachable("Unexpected type for integer literal!");
1559 case BuiltinType::Char_S:
1560 case BuiltinType::Char_U: OS << "i8"; break;
1561 case BuiltinType::UChar: OS << "Ui8"; break;
1562 case BuiltinType::SChar: OS << "i8"; break;
1563 case BuiltinType::Short: OS << "i16"; break;
1564 case BuiltinType::UShort: OS << "Ui16"; break;
1565 case BuiltinType::Int: break; // no suffix.
1566 case BuiltinType::UInt: OS << 'U'; break;
1567 case BuiltinType::Long: OS << 'L'; break;
1568 case BuiltinType::ULong: OS << "UL"; break;
1569 case BuiltinType::LongLong: OS << "LL"; break;
1570 case BuiltinType::ULongLong: OS << "ULL"; break;
1571 case BuiltinType::Int128:
1572 break; // no suffix.
1573 case BuiltinType::UInt128:
1574 break; // no suffix.
1575 case BuiltinType::WChar_S:
1576 case BuiltinType::WChar_U:
1577 break; // no suffix
1578 }
1579}
1580
1581void StmtPrinter::VisitFixedPointLiteral(FixedPointLiteral *Node) {
1582 if (Policy.ConstantsAsWritten && printExprAsWritten(OS, E: Node, Context))
1583 return;
1584 OS << Node->getValueAsString(/*Radix=*/10);
1585
1586 switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
1587 default: llvm_unreachable("Unexpected type for fixed point literal!");
1588 case BuiltinType::ShortFract: OS << "hr"; break;
1589 case BuiltinType::ShortAccum: OS << "hk"; break;
1590 case BuiltinType::UShortFract: OS << "uhr"; break;
1591 case BuiltinType::UShortAccum: OS << "uhk"; break;
1592 case BuiltinType::Fract: OS << "r"; break;
1593 case BuiltinType::Accum: OS << "k"; break;
1594 case BuiltinType::UFract: OS << "ur"; break;
1595 case BuiltinType::UAccum: OS << "uk"; break;
1596 case BuiltinType::LongFract: OS << "lr"; break;
1597 case BuiltinType::LongAccum: OS << "lk"; break;
1598 case BuiltinType::ULongFract: OS << "ulr"; break;
1599 case BuiltinType::ULongAccum: OS << "ulk"; break;
1600 }
1601}
1602
1603static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
1604 bool PrintSuffix) {
1605 SmallString<16> Str;
1606 Node->getValue().toString(Str);
1607 OS << Str;
1608 if (Str.find_first_not_of(Chars: "-0123456789") == StringRef::npos)
1609 OS << '.'; // Trailing dot in order to separate from ints.
1610
1611 if (!PrintSuffix)
1612 return;
1613
1614 // Emit suffixes. Float literals are always a builtin float type.
1615 switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
1616 default: llvm_unreachable("Unexpected type for float literal!");
1617 case BuiltinType::Half: break; // FIXME: suffix?
1618 case BuiltinType::Ibm128: break; // FIXME: No suffix for ibm128 literal
1619 case BuiltinType::Double: break; // no suffix.
1620 case BuiltinType::Float16: OS << "F16"; break;
1621 case BuiltinType::Float: OS << 'F'; break;
1622 case BuiltinType::LongDouble: OS << 'L'; break;
1623 case BuiltinType::Float128: OS << 'Q'; break;
1624 }
1625}
1626
1627void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
1628 if (Policy.ConstantsAsWritten && printExprAsWritten(OS, E: Node, Context))
1629 return;
1630 PrintFloatingLiteral(OS, Node, /*PrintSuffix=*/true);
1631}
1632
1633void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) {
1634 PrintExpr(E: Node->getSubExpr());
1635 OS << "i";
1636}
1637
1638void StmtPrinter::VisitStringLiteral(StringLiteral *Str) {
1639 Str->outputString(OS);
1640}
1641
1642void StmtPrinter::VisitParenExpr(ParenExpr *Node) {
1643 OS << "(";
1644 PrintExpr(E: Node->getSubExpr());
1645 OS << ")";
1646}
1647
1648void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
1649 if (!Node->isPostfix()) {
1650 OS << UnaryOperator::getOpcodeStr(Op: Node->getOpcode());
1651
1652 // Print a space if this is an "identifier operator" like __real, or if
1653 // it might be concatenated incorrectly like '+'.
1654 switch (Node->getOpcode()) {
1655 default: break;
1656 case UO_Real:
1657 case UO_Imag:
1658 case UO_Extension:
1659 OS << ' ';
1660 break;
1661 case UO_Plus:
1662 case UO_Minus:
1663 if (isa<UnaryOperator>(Val: Node->getSubExpr()))
1664 OS << ' ';
1665 break;
1666 }
1667 }
1668 PrintExpr(E: Node->getSubExpr());
1669
1670 if (Node->isPostfix())
1671 OS << UnaryOperator::getOpcodeStr(Op: Node->getOpcode());
1672}
1673
1674void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
1675 OS << "__builtin_offsetof(";
1676 Node->getTypeSourceInfo()->getType().print(OS, Policy);
1677 OS << ", ";
1678 bool PrintedSomething = false;
1679 for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) {
1680 OffsetOfNode ON = Node->getComponent(Idx: i);
1681 if (ON.getKind() == OffsetOfNode::Array) {
1682 // Array node
1683 OS << "[";
1684 PrintExpr(E: Node->getIndexExpr(Idx: ON.getArrayExprIndex()));
1685 OS << "]";
1686 PrintedSomething = true;
1687 continue;
1688 }
1689
1690 // Skip implicit base indirections.
1691 if (ON.getKind() == OffsetOfNode::Base)
1692 continue;
1693
1694 // Field or identifier node.
1695 const IdentifierInfo *Id = ON.getFieldName();
1696 if (!Id)
1697 continue;
1698
1699 if (PrintedSomething)
1700 OS << ".";
1701 else
1702 PrintedSomething = true;
1703 OS << Id->getName();
1704 }
1705 OS << ")";
1706}
1707
1708void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(
1709 UnaryExprOrTypeTraitExpr *Node) {
1710 const char *Spelling = getTraitSpelling(T: Node->getKind());
1711 if (Node->getKind() == UETT_AlignOf) {
1712 if (Policy.Alignof)
1713 Spelling = "alignof";
1714 else if (Policy.UnderscoreAlignof)
1715 Spelling = "_Alignof";
1716 else
1717 Spelling = "__alignof";
1718 }
1719
1720 OS << Spelling;
1721
1722 if (Node->isArgumentType()) {
1723 OS << '(';
1724 Node->getArgumentType().print(OS, Policy);
1725 OS << ')';
1726 } else {
1727 OS << " ";
1728 PrintExpr(E: Node->getArgumentExpr());
1729 }
1730}
1731
1732void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) {
1733 OS << "_Generic(";
1734 if (Node->isExprPredicate())
1735 PrintExpr(E: Node->getControllingExpr());
1736 else
1737 Node->getControllingType()->getType().print(OS, Policy);
1738
1739 for (const GenericSelectionExpr::Association &Assoc : Node->associations()) {
1740 OS << ", ";
1741 QualType T = Assoc.getType();
1742 if (T.isNull())
1743 OS << "default";
1744 else
1745 T.print(OS, Policy);
1746 OS << ": ";
1747 PrintExpr(E: Assoc.getAssociationExpr());
1748 }
1749 OS << ")";
1750}
1751
1752void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) {
1753 PrintExpr(E: Node->getLHS());
1754 OS << "[";
1755 PrintExpr(E: Node->getRHS());
1756 OS << "]";
1757}
1758
1759void StmtPrinter::VisitMatrixSingleSubscriptExpr(
1760 MatrixSingleSubscriptExpr *Node) {
1761 PrintExpr(E: Node->getBase());
1762 OS << "[";
1763 PrintExpr(E: Node->getRowIdx());
1764 OS << "]";
1765}
1766
1767void StmtPrinter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *Node) {
1768 PrintExpr(E: Node->getBase());
1769 OS << "[";
1770 PrintExpr(E: Node->getRowIdx());
1771 OS << "]";
1772 OS << "[";
1773 PrintExpr(E: Node->getColumnIdx());
1774 OS << "]";
1775}
1776
1777void StmtPrinter::VisitArraySectionExpr(ArraySectionExpr *Node) {
1778 PrintExpr(E: Node->getBase());
1779 OS << "[";
1780 if (Node->getLowerBound())
1781 PrintExpr(E: Node->getLowerBound());
1782 if (Node->getColonLocFirst().isValid()) {
1783 OS << ":";
1784 if (Node->getLength())
1785 PrintExpr(E: Node->getLength());
1786 }
1787 if (Node->isOMPArraySection() && Node->getColonLocSecond().isValid()) {
1788 OS << ":";
1789 if (Node->getStride())
1790 PrintExpr(E: Node->getStride());
1791 }
1792 OS << "]";
1793}
1794
1795void StmtPrinter::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *Node) {
1796 OS << "(";
1797 for (Expr *E : Node->getDimensions()) {
1798 OS << "[";
1799 PrintExpr(E);
1800 OS << "]";
1801 }
1802 OS << ")";
1803 PrintExpr(E: Node->getBase());
1804}
1805
1806void StmtPrinter::VisitOMPIteratorExpr(OMPIteratorExpr *Node) {
1807 OS << "iterator(";
1808 for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
1809 auto *VD = cast<ValueDecl>(Val: Node->getIteratorDecl(I));
1810 VD->getType().print(OS, Policy);
1811 const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
1812 OS << " " << VD->getName() << " = ";
1813 PrintExpr(E: Range.Begin);
1814 OS << ":";
1815 PrintExpr(E: Range.End);
1816 if (Range.Step) {
1817 OS << ":";
1818 PrintExpr(E: Range.Step);
1819 }
1820 if (I < E - 1)
1821 OS << ", ";
1822 }
1823 OS << ")";
1824}
1825
1826void StmtPrinter::PrintCallArgs(CallExpr *Call) {
1827 for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) {
1828 if (isa<CXXDefaultArgExpr>(Val: Call->getArg(Arg: i))) {
1829 // Don't print any defaulted arguments
1830 break;
1831 }
1832
1833 if (i) OS << ", ";
1834 PrintExpr(E: Call->getArg(Arg: i));
1835 }
1836}
1837
1838void StmtPrinter::VisitCallExpr(CallExpr *Call) {
1839 PrintExpr(E: Call->getCallee());
1840 OS << "(";
1841 PrintCallArgs(Call);
1842 OS << ")";
1843}
1844
1845static bool isImplicitThis(const Expr *E) {
1846 if (const auto *TE = dyn_cast<CXXThisExpr>(Val: E))
1847 return TE->isImplicit();
1848 return false;
1849}
1850
1851void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
1852 if (!Policy.SuppressImplicitBase || !isImplicitThis(E: Node->getBase())) {
1853 PrintExpr(E: Node->getBase());
1854
1855 auto *ParentMember = dyn_cast<MemberExpr>(Val: Node->getBase());
1856 FieldDecl *ParentDecl =
1857 ParentMember ? dyn_cast<FieldDecl>(Val: ParentMember->getMemberDecl())
1858 : nullptr;
1859
1860 if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
1861 OS << (Node->isArrow() ? "->" : ".");
1862 }
1863
1864 if (auto *FD = dyn_cast<FieldDecl>(Val: Node->getMemberDecl()))
1865 if (FD->isAnonymousStructOrUnion())
1866 return;
1867
1868 Node->getQualifier().print(OS, Policy);
1869 if (Node->hasTemplateKeyword())
1870 OS << "template ";
1871 OS << Node->getMemberNameInfo();
1872 const TemplateParameterList *TPL = nullptr;
1873 if (auto *FD = dyn_cast<FunctionDecl>(Val: Node->getMemberDecl())) {
1874 if (!Node->hadMultipleCandidates())
1875 if (auto *FTD = FD->getPrimaryTemplate())
1876 TPL = FTD->getTemplateParameters();
1877 } else if (auto *VTSD =
1878 dyn_cast<VarTemplateSpecializationDecl>(Val: Node->getMemberDecl()))
1879 TPL = VTSD->getSpecializedTemplate()->getTemplateParameters();
1880 if (Node->hasExplicitTemplateArgs())
1881 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy, TPL);
1882}
1883
1884void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
1885 PrintExpr(E: Node->getBase());
1886 OS << (Node->isArrow() ? "->isa" : ".isa");
1887}
1888
1889void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
1890 PrintExpr(E: Node->getBase());
1891 OS << ".";
1892 OS << Node->getAccessor().getName();
1893}
1894
1895void StmtPrinter::VisitMatrixElementExpr(MatrixElementExpr *Node) {
1896 PrintExpr(E: Node->getBase());
1897 OS << ".";
1898 OS << Node->getAccessor().getName();
1899}
1900
1901void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
1902 if (QualType T = Node->getType(); Policy.PrettyEnums && T->isEnumeralType()) {
1903 // special case enums to avoid producing cast expressions when naming
1904 // an enumerator would suffice
1905
1906 const auto *IL = dyn_cast<IntegerLiteral>(Val: Node->getSubExpr());
1907 const auto *ED = T->getAsEnumDecl();
1908 if (IL && ED) {
1909 llvm::APInt Val = IL->getValue();
1910 const auto ECD =
1911 llvm::find_if(Range: ED->enumerators(), P: [&](const EnumConstantDecl *ECD) {
1912 return llvm::APInt::isSameValue(I1: ECD->getInitVal(), I2: Val);
1913 });
1914 if (ECD != ED->enumerator_end()) {
1915 ECD->printQualifiedName(OS, Policy);
1916 return;
1917 }
1918 }
1919 }
1920 OS << '(';
1921 Node->getTypeAsWritten().print(OS, Policy);
1922 OS << ')';
1923 PrintExpr(E: Node->getSubExpr());
1924}
1925
1926void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) {
1927 OS << '(';
1928 Node->getType().print(OS, Policy);
1929 OS << ')';
1930 PrintExpr(E: Node->getInitializer());
1931}
1932
1933void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
1934 // No need to print anything, simply forward to the subexpression.
1935 PrintExpr(E: Node->getSubExpr());
1936}
1937
1938void StmtPrinter::VisitBinComma(BinaryOperator *Node) {
1939 PrintExpr(E: Node->getLHS());
1940 OS << BinaryOperator::getOpcodeStr(Op: Node->getOpcode()) << " ";
1941 PrintExpr(E: Node->getRHS());
1942}
1943
1944void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) {
1945 PrintExpr(E: Node->getLHS());
1946 OS << " " << BinaryOperator::getOpcodeStr(Op: Node->getOpcode()) << " ";
1947 PrintExpr(E: Node->getRHS());
1948}
1949
1950void StmtPrinter::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
1951 PrintExpr(E: Node->getLHS());
1952 OS << " " << BinaryOperator::getOpcodeStr(Op: Node->getOpcode()) << " ";
1953 PrintExpr(E: Node->getRHS());
1954}
1955
1956void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) {
1957 PrintExpr(E: Node->getCond());
1958 OS << " ? ";
1959 PrintExpr(E: Node->getLHS());
1960 OS << " : ";
1961 PrintExpr(E: Node->getRHS());
1962}
1963
1964// GNU extensions.
1965
1966void
1967StmtPrinter::VisitBinaryConditionalOperator(BinaryConditionalOperator *Node) {
1968 PrintExpr(E: Node->getCommon());
1969 OS << " ?: ";
1970 PrintExpr(E: Node->getFalseExpr());
1971}
1972
1973void StmtPrinter::VisitAddrLabelExpr(AddrLabelExpr *Node) {
1974 OS << "&&" << Node->getLabel()->getName();
1975}
1976
1977void StmtPrinter::VisitStmtExpr(StmtExpr *E) {
1978 OS << "(";
1979 PrintRawCompoundStmt(Node: E->getSubStmt());
1980 OS << ")";
1981}
1982
1983void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) {
1984 OS << "__builtin_choose_expr(";
1985 PrintExpr(E: Node->getCond());
1986 OS << ", ";
1987 PrintExpr(E: Node->getLHS());
1988 OS << ", ";
1989 PrintExpr(E: Node->getRHS());
1990 OS << ")";
1991}
1992
1993void StmtPrinter::VisitGNUNullExpr(GNUNullExpr *) {
1994 OS << "__null";
1995}
1996
1997void StmtPrinter::VisitShuffleVectorExpr(ShuffleVectorExpr *Node) {
1998 OS << "__builtin_shufflevector(";
1999 for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) {
2000 if (i) OS << ", ";
2001 PrintExpr(E: Node->getExpr(Index: i));
2002 }
2003 OS << ")";
2004}
2005
2006void StmtPrinter::VisitConvertVectorExpr(ConvertVectorExpr *Node) {
2007 OS << "__builtin_convertvector(";
2008 PrintExpr(E: Node->getSrcExpr());
2009 OS << ", ";
2010 Node->getType().print(OS, Policy);
2011 OS << ")";
2012}
2013
2014void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
2015 if (Node->getSyntacticForm()) {
2016 Visit(S: Node->getSyntacticForm());
2017 return;
2018 }
2019
2020 OS << "{";
2021 for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) {
2022 if (i) OS << ", ";
2023 if (Node->getInit(Init: i))
2024 PrintExpr(E: Node->getInit(Init: i));
2025 else
2026 OS << "{}";
2027 }
2028 OS << "}";
2029}
2030
2031void StmtPrinter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *Node) {
2032 // There's no way to express this expression in any of our supported
2033 // languages, so just emit something terse and (hopefully) clear.
2034 OS << "{";
2035 PrintExpr(E: Node->getSubExpr());
2036 OS << "}";
2037}
2038
2039void StmtPrinter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *Node) {
2040 OS << "*";
2041}
2042
2043void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) {
2044 OS << "(";
2045 for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) {
2046 if (i) OS << ", ";
2047 PrintExpr(E: Node->getExpr(Init: i));
2048 }
2049 OS << ")";
2050}
2051
2052void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) {
2053 bool NeedsEquals = true;
2054 for (const DesignatedInitExpr::Designator &D : Node->designators()) {
2055 if (D.isFieldDesignator()) {
2056 if (D.getDotLoc().isInvalid()) {
2057 if (const IdentifierInfo *II = D.getFieldName()) {
2058 OS << II->getName() << ":";
2059 NeedsEquals = false;
2060 }
2061 } else {
2062 OS << "." << D.getFieldName()->getName();
2063 }
2064 } else {
2065 OS << "[";
2066 if (D.isArrayDesignator()) {
2067 PrintExpr(E: Node->getArrayIndex(D));
2068 } else {
2069 PrintExpr(E: Node->getArrayRangeStart(D));
2070 OS << " ... ";
2071 PrintExpr(E: Node->getArrayRangeEnd(D));
2072 }
2073 OS << "]";
2074 }
2075 }
2076
2077 if (NeedsEquals)
2078 OS << " = ";
2079 else
2080 OS << " ";
2081 PrintExpr(E: Node->getInit());
2082}
2083
2084void StmtPrinter::VisitDesignatedInitUpdateExpr(
2085 DesignatedInitUpdateExpr *Node) {
2086 OS << "{";
2087 OS << "/*base*/";
2088 PrintExpr(E: Node->getBase());
2089 OS << ", ";
2090
2091 OS << "/*updater*/";
2092 PrintExpr(E: Node->getUpdater());
2093 OS << "}";
2094}
2095
2096void StmtPrinter::VisitNoInitExpr(NoInitExpr *Node) {
2097 OS << "/*no init*/";
2098}
2099
2100void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) {
2101 if (Node->getType()->getAsCXXRecordDecl()) {
2102 OS << "/*implicit*/";
2103 Node->getType().print(OS, Policy);
2104 OS << "()";
2105 } else {
2106 OS << "/*implicit*/(";
2107 Node->getType().print(OS, Policy);
2108 OS << ')';
2109 if (Node->getType()->isRecordType())
2110 OS << "{}";
2111 else
2112 OS << 0;
2113 }
2114}
2115
2116void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {
2117 OS << "__builtin_va_arg(";
2118 PrintExpr(E: Node->getSubExpr());
2119 OS << ", ";
2120 Node->getType().print(OS, Policy);
2121 OS << ")";
2122}
2123
2124void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) {
2125 PrintExpr(E: Node->getSyntacticForm());
2126}
2127
2128void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
2129 const char *Name = nullptr;
2130 switch (Node->getOp()) {
2131#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
2132 case AtomicExpr::AO ## ID: \
2133 Name = #ID "("; \
2134 break;
2135#include "clang/Basic/Builtins.inc"
2136 }
2137 OS << Name;
2138
2139 // AtomicExpr stores its subexpressions in a permuted order.
2140 PrintExpr(E: Node->getPtr());
2141 if (Node->hasVal1Operand()) {
2142 OS << ", ";
2143 PrintExpr(E: Node->getVal1());
2144 }
2145 if (Node->getOp() == AtomicExpr::AO__atomic_exchange ||
2146 Node->isCmpXChg()) {
2147 OS << ", ";
2148 PrintExpr(E: Node->getVal2());
2149 }
2150 if (Node->getOp() == AtomicExpr::AO__atomic_compare_exchange ||
2151 Node->getOp() == AtomicExpr::AO__atomic_compare_exchange_n) {
2152 OS << ", ";
2153 PrintExpr(E: Node->getWeak());
2154 }
2155 if (Node->getOp() != AtomicExpr::AO__c11_atomic_init &&
2156 Node->getOp() != AtomicExpr::AO__opencl_atomic_init) {
2157 OS << ", ";
2158 PrintExpr(E: Node->getOrder());
2159 }
2160 if (Node->isCmpXChg()) {
2161 OS << ", ";
2162 PrintExpr(E: Node->getOrderFail());
2163 }
2164 OS << ")";
2165}
2166
2167// C++
2168void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
2169 OverloadedOperatorKind Kind = Node->getOperator();
2170 if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
2171 if (Node->getNumArgs() == 1) {
2172 OS << getOperatorSpelling(Operator: Kind) << ' ';
2173 PrintExpr(E: Node->getArg(Arg: 0));
2174 } else {
2175 PrintExpr(E: Node->getArg(Arg: 0));
2176 OS << ' ' << getOperatorSpelling(Operator: Kind);
2177 }
2178 } else if (Kind == OO_Arrow) {
2179 PrintExpr(E: Node->getArg(Arg: 0));
2180 } else if (Kind == OO_Call || Kind == OO_Subscript) {
2181 PrintExpr(E: Node->getArg(Arg: 0));
2182 OS << (Kind == OO_Call ? '(' : '[');
2183 for (unsigned ArgIdx = 1; ArgIdx < Node->getNumArgs(); ++ArgIdx) {
2184 if (ArgIdx > 1)
2185 OS << ", ";
2186 if (!isa<CXXDefaultArgExpr>(Val: Node->getArg(Arg: ArgIdx)))
2187 PrintExpr(E: Node->getArg(Arg: ArgIdx));
2188 }
2189 OS << (Kind == OO_Call ? ')' : ']');
2190 } else if (Node->getNumArgs() == 1) {
2191 OS << getOperatorSpelling(Operator: Kind) << ' ';
2192 PrintExpr(E: Node->getArg(Arg: 0));
2193 } else if (Node->getNumArgs() == 2) {
2194 PrintExpr(E: Node->getArg(Arg: 0));
2195 OS << ' ' << getOperatorSpelling(Operator: Kind) << ' ';
2196 PrintExpr(E: Node->getArg(Arg: 1));
2197 } else {
2198 llvm_unreachable("unknown overloaded operator");
2199 }
2200}
2201
2202void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {
2203 // If we have a conversion operator call only print the argument.
2204 CXXMethodDecl *MD = Node->getMethodDecl();
2205 if (isa_and_nonnull<CXXConversionDecl>(Val: MD)) {
2206 PrintExpr(E: Node->getImplicitObjectArgument());
2207 return;
2208 }
2209 VisitCallExpr(Call: cast<CallExpr>(Val: Node));
2210}
2211
2212void StmtPrinter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *Node) {
2213 PrintExpr(E: Node->getCallee());
2214 OS << "<<<";
2215 PrintCallArgs(Call: Node->getConfig());
2216 OS << ">>>(";
2217 PrintCallArgs(Call: Node);
2218 OS << ")";
2219}
2220
2221void StmtPrinter::VisitCXXRewrittenBinaryOperator(
2222 CXXRewrittenBinaryOperator *Node) {
2223 CXXRewrittenBinaryOperator::DecomposedForm Decomposed =
2224 Node->getDecomposedForm();
2225 PrintExpr(E: const_cast<Expr*>(Decomposed.LHS));
2226 OS << ' ' << BinaryOperator::getOpcodeStr(Op: Decomposed.Opcode) << ' ';
2227 PrintExpr(E: const_cast<Expr*>(Decomposed.RHS));
2228}
2229
2230void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
2231 OS << Node->getCastName() << '<';
2232 Node->getTypeAsWritten().print(OS, Policy);
2233 OS << ">(";
2234 PrintExpr(E: Node->getSubExpr());
2235 OS << ")";
2236}
2237
2238void StmtPrinter::VisitCXXStaticCastExpr(CXXStaticCastExpr *Node) {
2239 VisitCXXNamedCastExpr(Node);
2240}
2241
2242void StmtPrinter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *Node) {
2243 VisitCXXNamedCastExpr(Node);
2244}
2245
2246void StmtPrinter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *Node) {
2247 VisitCXXNamedCastExpr(Node);
2248}
2249
2250void StmtPrinter::VisitCXXConstCastExpr(CXXConstCastExpr *Node) {
2251 VisitCXXNamedCastExpr(Node);
2252}
2253
2254void StmtPrinter::VisitBuiltinBitCastExpr(BuiltinBitCastExpr *Node) {
2255 OS << "__builtin_bit_cast(";
2256 Node->getTypeInfoAsWritten()->getType().print(OS, Policy);
2257 OS << ", ";
2258 PrintExpr(E: Node->getSubExpr());
2259 OS << ")";
2260}
2261
2262void StmtPrinter::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *Node) {
2263 VisitCXXNamedCastExpr(Node);
2264}
2265
2266void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
2267 OS << "typeid(";
2268 if (Node->isTypeOperand()) {
2269 Node->getTypeOperandSourceInfo()->getType().print(OS, Policy);
2270 } else {
2271 PrintExpr(E: Node->getExprOperand());
2272 }
2273 OS << ")";
2274}
2275
2276void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) {
2277 OS << "__uuidof(";
2278 if (Node->isTypeOperand()) {
2279 Node->getTypeOperandSourceInfo()->getType().print(OS, Policy);
2280 } else {
2281 PrintExpr(E: Node->getExprOperand());
2282 }
2283 OS << ")";
2284}
2285
2286void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
2287 PrintExpr(E: Node->getBaseExpr());
2288 if (Node->isArrow())
2289 OS << "->";
2290 else
2291 OS << ".";
2292 Node->getQualifierLoc().getNestedNameSpecifier().print(OS, Policy);
2293 OS << Node->getPropertyDecl()->getDeclName();
2294}
2295
2296void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) {
2297 PrintExpr(E: Node->getBase());
2298 OS << "[";
2299 PrintExpr(E: Node->getIdx());
2300 OS << "]";
2301}
2302
2303void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
2304 switch (Node->getLiteralOperatorKind()) {
2305 case UserDefinedLiteral::LOK_Raw:
2306 OS << cast<StringLiteral>(Val: Node->getArg(Arg: 0)->IgnoreImpCasts())->getString();
2307 break;
2308 case UserDefinedLiteral::LOK_Template: {
2309 const auto *DRE = cast<DeclRefExpr>(Val: Node->getCallee()->IgnoreImpCasts());
2310 const TemplateArgumentList *Args =
2311 cast<FunctionDecl>(Val: DRE->getDecl())->getTemplateSpecializationArgs();
2312 assert(Args);
2313
2314 if (Args->size() != 1 || Args->get(Idx: 0).getKind() != TemplateArgument::Pack) {
2315 const TemplateParameterList *TPL = nullptr;
2316 if (!DRE->hadMultipleCandidates())
2317 if (const auto *TD = dyn_cast<TemplateDecl>(Val: DRE->getDecl()))
2318 TPL = TD->getTemplateParameters();
2319 OS << "operator\"\"" << Node->getUDSuffix()->getName();
2320 printTemplateArgumentList(OS, Args: Args->asArray(), Policy, TPL);
2321 OS << "()";
2322 return;
2323 }
2324
2325 const TemplateArgument &Pack = Args->get(Idx: 0);
2326 for (const auto &P : Pack.pack_elements()) {
2327 char C = (char)P.getAsIntegral().getZExtValue();
2328 OS << C;
2329 }
2330 break;
2331 }
2332 case UserDefinedLiteral::LOK_Integer: {
2333 // Print integer literal without suffix.
2334 const auto *Int = cast<IntegerLiteral>(Val: Node->getCookedLiteral());
2335 OS << toString(I: Int->getValue(), Radix: 10, /*isSigned*/Signed: false);
2336 break;
2337 }
2338 case UserDefinedLiteral::LOK_Floating: {
2339 // Print floating literal without suffix.
2340 auto *Float = cast<FloatingLiteral>(Val: Node->getCookedLiteral());
2341 PrintFloatingLiteral(OS, Node: Float, /*PrintSuffix=*/false);
2342 break;
2343 }
2344 case UserDefinedLiteral::LOK_String:
2345 case UserDefinedLiteral::LOK_Character:
2346 PrintExpr(E: Node->getCookedLiteral());
2347 break;
2348 }
2349 OS << Node->getUDSuffix()->getName();
2350}
2351
2352void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
2353 OS << (Node->getValue() ? "true" : "false");
2354}
2355
2356void StmtPrinter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *Node) {
2357 OS << "nullptr";
2358}
2359
2360void StmtPrinter::VisitCXXThisExpr(CXXThisExpr *Node) {
2361 OS << "this";
2362}
2363
2364void StmtPrinter::VisitCXXThrowExpr(CXXThrowExpr *Node) {
2365 if (!Node->getSubExpr())
2366 OS << "throw";
2367 else {
2368 OS << "throw ";
2369 PrintExpr(E: Node->getSubExpr());
2370 }
2371}
2372
2373void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) {
2374 // Nothing to print: we picked up the default argument.
2375}
2376
2377void StmtPrinter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Node) {
2378 // Nothing to print: we picked up the default initializer.
2379}
2380
2381void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
2382 auto TargetType = Node->getType();
2383 auto *Auto = TargetType->getContainedDeducedType();
2384 bool Bare = Auto && Auto->isDeduced();
2385
2386 // Parenthesize deduced casts.
2387 if (Bare)
2388 OS << '(';
2389 TargetType.print(OS, Policy);
2390 if (Bare)
2391 OS << ')';
2392
2393 // No extra braces surrounding the inner construct.
2394 if (!Node->isListInitialization())
2395 OS << '(';
2396 PrintExpr(E: Node->getSubExpr());
2397 if (!Node->isListInitialization())
2398 OS << ')';
2399}
2400
2401void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
2402 PrintExpr(E: Node->getSubExpr());
2403}
2404
2405void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
2406 Node->getType().print(OS, Policy);
2407 if (Node->isStdInitListInitialization())
2408 /* Nothing to do; braces are part of creating the std::initializer_list. */;
2409 else if (Node->isListInitialization())
2410 OS << "{";
2411 else
2412 OS << "(";
2413 for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(),
2414 ArgEnd = Node->arg_end();
2415 Arg != ArgEnd; ++Arg) {
2416 if ((*Arg)->isDefaultArgument())
2417 break;
2418 if (Arg != Node->arg_begin())
2419 OS << ", ";
2420 PrintExpr(E: *Arg);
2421 }
2422 if (Node->isStdInitListInitialization())
2423 /* See above. */;
2424 else if (Node->isListInitialization())
2425 OS << "}";
2426 else
2427 OS << ")";
2428}
2429
2430void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
2431 OS << '[';
2432 bool NeedComma = false;
2433 switch (Node->getCaptureDefault()) {
2434 case LCD_None:
2435 break;
2436
2437 case LCD_ByCopy:
2438 OS << '=';
2439 NeedComma = true;
2440 break;
2441
2442 case LCD_ByRef:
2443 OS << '&';
2444 NeedComma = true;
2445 break;
2446 }
2447 for (LambdaExpr::capture_iterator C = Node->explicit_capture_begin(),
2448 CEnd = Node->explicit_capture_end();
2449 C != CEnd;
2450 ++C) {
2451 if (C->capturesVLAType())
2452 continue;
2453
2454 if (NeedComma)
2455 OS << ", ";
2456 NeedComma = true;
2457
2458 switch (C->getCaptureKind()) {
2459 case LCK_This:
2460 OS << "this";
2461 break;
2462
2463 case LCK_StarThis:
2464 OS << "*this";
2465 break;
2466
2467 case LCK_ByRef:
2468 if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(Capture: C))
2469 OS << '&';
2470 OS << C->getCapturedVar()->getName();
2471 break;
2472
2473 case LCK_ByCopy:
2474 OS << C->getCapturedVar()->getName();
2475 break;
2476
2477 case LCK_VLAType:
2478 llvm_unreachable("VLA type in explicit captures.");
2479 }
2480
2481 if (C->isPackExpansion())
2482 OS << "...";
2483
2484 if (Node->isInitCapture(Capture: C)) {
2485 // Init captures are always VarDecl.
2486 auto *D = cast<VarDecl>(Val: C->getCapturedVar());
2487
2488 llvm::StringRef Pre;
2489 llvm::StringRef Post;
2490 if (D->getInitStyle() == VarDecl::CallInit &&
2491 !isa<ParenListExpr>(Val: D->getInit())) {
2492 Pre = "(";
2493 Post = ")";
2494 } else if (D->getInitStyle() == VarDecl::CInit) {
2495 Pre = " = ";
2496 }
2497
2498 OS << Pre;
2499 PrintExpr(E: D->getInit());
2500 OS << Post;
2501 }
2502 }
2503 OS << ']';
2504
2505 if (!Node->getExplicitTemplateParameters().empty()) {
2506 Node->getTemplateParameterList()->print(
2507 Out&: OS, Context: Node->getLambdaClass()->getASTContext(),
2508 /*OmitTemplateKW*/true);
2509 }
2510
2511 if (Node->hasExplicitParameters()) {
2512 OS << '(';
2513 CXXMethodDecl *Method = Node->getCallOperator();
2514 NeedComma = false;
2515 for (const auto *P : Method->parameters()) {
2516 if (NeedComma) {
2517 OS << ", ";
2518 } else {
2519 NeedComma = true;
2520 }
2521 std::string ParamStr =
2522 (Policy.CleanUglifiedParameters && P->getIdentifier())
2523 ? P->getIdentifier()->deuglifiedName().str()
2524 : P->getNameAsString();
2525 P->getOriginalType().print(OS, Policy, PlaceHolder: ParamStr);
2526 }
2527 if (Method->isVariadic()) {
2528 if (NeedComma)
2529 OS << ", ";
2530 OS << "...";
2531 }
2532 OS << ')';
2533
2534 if (Node->isMutable())
2535 OS << " mutable";
2536
2537 auto *Proto = Method->getType()->castAs<FunctionProtoType>();
2538 Proto->printExceptionSpecification(OS, Policy);
2539
2540 // FIXME: Attributes
2541
2542 // Print the trailing return type if it was specified in the source.
2543 if (Node->hasExplicitResultType()) {
2544 OS << " -> ";
2545 Proto->getReturnType().print(OS, Policy);
2546 }
2547 }
2548
2549 // Print the body.
2550 OS << ' ';
2551 if (Policy.TerseOutput || Policy.SuppressLambdaBody)
2552 OS << "{}";
2553 else
2554 PrintRawCompoundStmt(Node: Node->getCompoundStmtBody());
2555}
2556
2557void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) {
2558 if (TypeSourceInfo *TSInfo = Node->getTypeSourceInfo())
2559 TSInfo->getType().print(OS, Policy);
2560 else
2561 Node->getType().print(OS, Policy);
2562 OS << "()";
2563}
2564
2565void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
2566 if (E->isGlobalNew())
2567 OS << "::";
2568 OS << "new ";
2569 unsigned NumPlace = E->getNumPlacementArgs();
2570 if (NumPlace > 0 && !isa<CXXDefaultArgExpr>(Val: E->getPlacementArg(I: 0))) {
2571 OS << "(";
2572 PrintExpr(E: E->getPlacementArg(I: 0));
2573 for (unsigned i = 1; i < NumPlace; ++i) {
2574 if (isa<CXXDefaultArgExpr>(Val: E->getPlacementArg(I: i)))
2575 break;
2576 OS << ", ";
2577 PrintExpr(E: E->getPlacementArg(I: i));
2578 }
2579 OS << ") ";
2580 }
2581 if (E->isParenTypeId())
2582 OS << "(";
2583 std::string TypeS;
2584 if (E->isArray()) {
2585 llvm::raw_string_ostream s(TypeS);
2586 s << '[';
2587 if (std::optional<Expr *> Size = E->getArraySize())
2588 (*Size)->printPretty(OS&: s, Helper, Policy);
2589 s << ']';
2590 }
2591 E->getAllocatedType().print(OS, Policy, PlaceHolder: TypeS);
2592 if (E->isParenTypeId())
2593 OS << ")";
2594
2595 CXXNewInitializationStyle InitStyle = E->getInitializationStyle();
2596 if (InitStyle != CXXNewInitializationStyle::None) {
2597 bool Bare = InitStyle == CXXNewInitializationStyle::Parens &&
2598 !isa<ParenListExpr>(Val: E->getInitializer());
2599 if (Bare)
2600 OS << "(";
2601 PrintExpr(E: E->getInitializer());
2602 if (Bare)
2603 OS << ")";
2604 }
2605}
2606
2607void StmtPrinter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
2608 if (E->isGlobalDelete())
2609 OS << "::";
2610 OS << "delete ";
2611 if (E->isArrayForm())
2612 OS << "[] ";
2613 PrintExpr(E: E->getArgument());
2614}
2615
2616void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
2617 PrintExpr(E: E->getBase());
2618 if (E->isArrow())
2619 OS << "->";
2620 else
2621 OS << '.';
2622 E->getQualifier().print(OS, Policy);
2623 OS << "~";
2624
2625 if (const IdentifierInfo *II = E->getDestroyedTypeIdentifier())
2626 OS << II->getName();
2627 else
2628 E->getDestroyedType().print(OS, Policy);
2629}
2630
2631void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
2632 if (E->isListInitialization() && !E->isStdInitListInitialization())
2633 OS << "{";
2634
2635 for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
2636 if (isa<CXXDefaultArgExpr>(Val: E->getArg(Arg: i))) {
2637 // Don't print any defaulted arguments
2638 break;
2639 }
2640
2641 if (i) OS << ", ";
2642 PrintExpr(E: E->getArg(Arg: i));
2643 }
2644
2645 if (E->isListInitialization() && !E->isStdInitListInitialization())
2646 OS << "}";
2647}
2648
2649void StmtPrinter::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E) {
2650 // Parens are printed by the surrounding context.
2651 OS << "<forwarded>";
2652}
2653
2654void StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
2655 PrintExpr(E: E->getSubExpr());
2656}
2657
2658void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) {
2659 // Just forward to the subexpression.
2660 PrintExpr(E: E->getSubExpr());
2661}
2662
2663void StmtPrinter::VisitCXXUnresolvedConstructExpr(
2664 CXXUnresolvedConstructExpr *Node) {
2665 Node->getTypeAsWritten().print(OS, Policy);
2666 if (!Node->isListInitialization())
2667 OS << '(';
2668 for (auto Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); Arg != ArgEnd;
2669 ++Arg) {
2670 if (Arg != Node->arg_begin())
2671 OS << ", ";
2672 PrintExpr(E: *Arg);
2673 }
2674 if (!Node->isListInitialization())
2675 OS << ')';
2676}
2677
2678void StmtPrinter::VisitCXXReflectExpr(CXXReflectExpr *S) {
2679 // TODO(Reflection): add support for the remaining reflection kinds.
2680 OS << "^^";
2681 switch (S->getKind()) {
2682 case ReflectionKind::Null:
2683 assert(false && "null reflection can't be constructed from parsing a "
2684 "reflection operand");
2685 break;
2686 case ReflectionKind::Type:
2687 S->getTypeSourceInfo()->getType().print(OS, Policy);
2688 break;
2689 }
2690}
2691
2692void StmtPrinter::VisitDependentTemplateIdExpr(DependentTemplateIdExpr *Node) {
2693 Node->getTemplateName().print(OS, Policy, Qual: TemplateName::Qualified::None);
2694 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy,
2695 TPL: Node->getParameter()->getTemplateParameters());
2696}
2697
2698void StmtPrinter::VisitCXXDependentScopeMemberExpr(
2699 CXXDependentScopeMemberExpr *Node) {
2700 if (!Node->isImplicitAccess()) {
2701 PrintExpr(E: Node->getBase());
2702 OS << (Node->isArrow() ? "->" : ".");
2703 }
2704 Node->getQualifier().print(OS, Policy);
2705 if (Node->hasTemplateKeyword())
2706 OS << "template ";
2707 OS << Node->getMemberNameInfo();
2708 if (Node->hasExplicitTemplateArgs())
2709 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy);
2710}
2711
2712void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
2713 if (!Node->isImplicitAccess()) {
2714 PrintExpr(E: Node->getBase());
2715 OS << (Node->isArrow() ? "->" : ".");
2716 }
2717 Node->getQualifier().print(OS, Policy);
2718 if (Node->hasTemplateKeyword())
2719 OS << "template ";
2720 OS << Node->getMemberNameInfo();
2721 if (Node->hasExplicitTemplateArgs())
2722 printTemplateArgumentList(OS, Args: Node->template_arguments(), Policy);
2723}
2724
2725void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) {
2726 OS << getTraitSpelling(T: E->getTrait()) << "(";
2727 for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
2728 if (I > 0)
2729 OS << ", ";
2730 E->getArg(I)->getType().print(OS, Policy);
2731 }
2732 OS << ")";
2733}
2734
2735void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
2736 OS << getTraitSpelling(T: E->getTrait()) << '(';
2737 E->getQueriedType().print(OS, Policy);
2738 OS << ')';
2739}
2740
2741void StmtPrinter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
2742 OS << getTraitSpelling(T: E->getTrait()) << '(';
2743 PrintExpr(E: E->getQueriedExpression());
2744 OS << ')';
2745}
2746
2747void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
2748 OS << "noexcept(";
2749 PrintExpr(E: E->getOperand());
2750 OS << ")";
2751}
2752
2753void StmtPrinter::VisitPackExpansionExpr(PackExpansionExpr *E) {
2754 PrintExpr(E: E->getPattern());
2755 OS << "...";
2756}
2757
2758void StmtPrinter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
2759 OS << "sizeof...(" << *E->getPack() << ")";
2760}
2761
2762void StmtPrinter::VisitPackIndexingExpr(PackIndexingExpr *E) {
2763 PrintExpr(E: E->getPackIdExpression());
2764 OS << "...[";
2765 PrintExpr(E: E->getIndexExpr());
2766 OS << "]";
2767}
2768
2769void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr(
2770 SubstNonTypeTemplateParmPackExpr *Node) {
2771 OS << *Node->getParameterPack();
2772}
2773
2774void StmtPrinter::VisitSubstNonTypeTemplateParmExpr(
2775 SubstNonTypeTemplateParmExpr *Node) {
2776 Visit(S: Node->getReplacement());
2777}
2778
2779void StmtPrinter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
2780 OS << *E->getParameterPack();
2781}
2782
2783void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
2784 PrintExpr(E: Node->getSubExpr());
2785}
2786
2787void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) {
2788 OS << "(";
2789 if (E->getLHS()) {
2790 PrintExpr(E: E->getLHS());
2791 OS << " " << BinaryOperator::getOpcodeStr(Op: E->getOperator()) << " ";
2792 }
2793 OS << "...";
2794 if (E->getRHS()) {
2795 OS << " " << BinaryOperator::getOpcodeStr(Op: E->getOperator()) << " ";
2796 PrintExpr(E: E->getRHS());
2797 }
2798 OS << ")";
2799}
2800
2801void StmtPrinter::VisitCXXParenListInitExpr(CXXParenListInitExpr *Node) {
2802 llvm::interleaveComma(c: Node->getUserSpecifiedInitExprs(), os&: OS,
2803 each_fn: [&](Expr *E) { PrintExpr(E); });
2804}
2805
2806void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
2807 NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc();
2808 NNS.getNestedNameSpecifier().print(OS, Policy);
2809 if (E->getTemplateKWLoc().isValid())
2810 OS << "template ";
2811 OS << E->getFoundDecl()->getName();
2812 printTemplateArgumentList(OS, Args: E->getTemplateArgsAsWritten()->arguments(),
2813 Policy,
2814 TPL: E->getConceptDecl()->getTemplateParameters());
2815}
2816
2817void StmtPrinter::VisitRequiresExpr(RequiresExpr *E) {
2818 OS << "requires ";
2819 auto LocalParameters = E->getLocalParameters();
2820 if (!LocalParameters.empty()) {
2821 OS << "(";
2822 for (ParmVarDecl *LocalParam : LocalParameters) {
2823 PrintRawDecl(D: LocalParam);
2824 if (LocalParam != LocalParameters.back())
2825 OS << ", ";
2826 }
2827
2828 OS << ") ";
2829 }
2830 OS << "{ ";
2831 auto Requirements = E->getRequirements();
2832 for (concepts::Requirement *Req : Requirements) {
2833 if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Val: Req)) {
2834 if (TypeReq->isSubstitutionFailure())
2835 OS << "<<error-type>>";
2836 else
2837 TypeReq->getType()->getType().print(OS, Policy);
2838 } else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Val: Req)) {
2839 if (ExprReq->isCompound())
2840 OS << "{ ";
2841 if (ExprReq->isExprSubstitutionFailure())
2842 OS << "<<error-expression>>";
2843 else
2844 PrintExpr(E: ExprReq->getExpr());
2845 if (ExprReq->isCompound()) {
2846 OS << " }";
2847 if (ExprReq->getNoexceptLoc().isValid())
2848 OS << " noexcept";
2849 const auto &RetReq = ExprReq->getReturnTypeRequirement();
2850 if (!RetReq.isEmpty()) {
2851 OS << " -> ";
2852 if (RetReq.isSubstitutionFailure())
2853 OS << "<<error-type>>";
2854 else if (RetReq.isTypeConstraint())
2855 RetReq.getTypeConstraint()->print(OS, Policy);
2856 }
2857 }
2858 } else {
2859 auto *NestedReq = cast<concepts::NestedRequirement>(Val: Req);
2860 OS << "requires ";
2861 if (NestedReq->hasInvalidConstraint())
2862 OS << "<<error-expression>>";
2863 else
2864 PrintExpr(E: NestedReq->getConstraintExpr());
2865 }
2866 OS << "; ";
2867 }
2868 OS << "}";
2869}
2870
2871// C++ Coroutines
2872
2873void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
2874 Visit(S: S->getBody());
2875}
2876
2877void StmtPrinter::VisitCoreturnStmt(CoreturnStmt *S) {
2878 OS << "co_return";
2879 if (S->getOperand()) {
2880 OS << " ";
2881 Visit(S: S->getOperand());
2882 }
2883 OS << ";";
2884}
2885
2886void StmtPrinter::VisitCoawaitExpr(CoawaitExpr *S) {
2887 OS << "co_await ";
2888 PrintExpr(E: S->getOperand());
2889}
2890
2891void StmtPrinter::VisitDependentCoawaitExpr(DependentCoawaitExpr *S) {
2892 OS << "co_await ";
2893 PrintExpr(E: S->getOperand());
2894}
2895
2896void StmtPrinter::VisitCoyieldExpr(CoyieldExpr *S) {
2897 OS << "co_yield ";
2898 PrintExpr(E: S->getOperand());
2899}
2900
2901// Obj-C
2902
2903void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
2904 OS << "@";
2905 VisitStringLiteral(Str: Node->getString());
2906}
2907
2908void StmtPrinter::VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
2909 OS << "@";
2910 Visit(S: E->getSubExpr());
2911}
2912
2913void StmtPrinter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
2914 OS << "@[ ";
2915 ObjCArrayLiteral::child_range Ch = E->children();
2916 for (auto I = Ch.begin(), E = Ch.end(); I != E; ++I) {
2917 if (I != Ch.begin())
2918 OS << ", ";
2919 Visit(S: *I);
2920 }
2921 OS << " ]";
2922}
2923
2924void StmtPrinter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
2925 OS << "@{ ";
2926 for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
2927 if (I > 0)
2928 OS << ", ";
2929
2930 ObjCDictionaryElement Element = E->getKeyValueElement(Index: I);
2931 Visit(S: Element.Key);
2932 OS << " : ";
2933 Visit(S: Element.Value);
2934 if (Element.isPackExpansion())
2935 OS << "...";
2936 }
2937 OS << " }";
2938}
2939
2940void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
2941 OS << "@encode(";
2942 Node->getEncodedType().print(OS, Policy);
2943 OS << ')';
2944}
2945
2946void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
2947 OS << "@selector(";
2948 Node->getSelector().print(OS);
2949 OS << ')';
2950}
2951
2952void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
2953 OS << "@protocol(" << *Node->getProtocol() << ')';
2954}
2955
2956void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
2957 OS << "[";
2958 switch (Mess->getReceiverKind()) {
2959 case ObjCMessageExpr::Instance:
2960 PrintExpr(E: Mess->getInstanceReceiver());
2961 break;
2962
2963 case ObjCMessageExpr::Class:
2964 Mess->getClassReceiver().print(OS, Policy);
2965 break;
2966
2967 case ObjCMessageExpr::SuperInstance:
2968 case ObjCMessageExpr::SuperClass:
2969 OS << "Super";
2970 break;
2971 }
2972
2973 OS << ' ';
2974 Selector selector = Mess->getSelector();
2975 if (selector.isUnarySelector()) {
2976 OS << selector.getNameForSlot(argIndex: 0);
2977 } else {
2978 for (unsigned i = 0, e = Mess->getNumArgs(); i != e; ++i) {
2979 if (i < selector.getNumArgs()) {
2980 if (i > 0) OS << ' ';
2981 if (selector.getIdentifierInfoForSlot(argIndex: i))
2982 OS << selector.getIdentifierInfoForSlot(argIndex: i)->getName() << ':';
2983 else
2984 OS << ":";
2985 }
2986 else OS << ", "; // Handle variadic methods.
2987
2988 PrintExpr(E: Mess->getArg(Arg: i));
2989 }
2990 }
2991 OS << "]";
2992}
2993
2994void StmtPrinter::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) {
2995 OS << (Node->getValue() ? "__objc_yes" : "__objc_no");
2996}
2997
2998void
2999StmtPrinter::VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) {
3000 PrintExpr(E: E->getSubExpr());
3001}
3002
3003void
3004StmtPrinter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) {
3005 OS << '(' << E->getBridgeKindName();
3006 E->getType().print(OS, Policy);
3007 OS << ')';
3008 PrintExpr(E: E->getSubExpr());
3009}
3010
3011void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
3012 BlockDecl *BD = Node->getBlockDecl();
3013 OS << "^";
3014
3015 const FunctionType *AFT = Node->getFunctionType();
3016
3017 if (isa<FunctionNoProtoType>(Val: AFT)) {
3018 OS << "()";
3019 } else if (!BD->param_empty() || cast<FunctionProtoType>(Val: AFT)->isVariadic()) {
3020 OS << '(';
3021 for (BlockDecl::param_iterator AI = BD->param_begin(),
3022 E = BD->param_end(); AI != E; ++AI) {
3023 if (AI != BD->param_begin()) OS << ", ";
3024 std::string ParamStr = (*AI)->getNameAsString();
3025 (*AI)->getType().print(OS, Policy, PlaceHolder: ParamStr);
3026 }
3027
3028 const auto *FT = cast<FunctionProtoType>(Val: AFT);
3029 if (FT->isVariadic()) {
3030 if (!BD->param_empty()) OS << ", ";
3031 OS << "...";
3032 }
3033 OS << ')';
3034 }
3035 OS << "{ }";
3036}
3037
3038void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
3039 PrintExpr(E: Node->getSourceExpr());
3040}
3041
3042void StmtPrinter::VisitRecoveryExpr(RecoveryExpr *Node) {
3043 OS << "<recovery-expr>(";
3044 const char *Sep = "";
3045 for (Expr *E : Node->subExpressions()) {
3046 OS << Sep;
3047 PrintExpr(E);
3048 Sep = ", ";
3049 }
3050 OS << ')';
3051}
3052
3053void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) {
3054 OS << "__builtin_astype(";
3055 PrintExpr(E: Node->getSrcExpr());
3056 OS << ", ";
3057 Node->getType().print(OS, Policy);
3058 OS << ")";
3059}
3060
3061void StmtPrinter::VisitHLSLOutArgExpr(HLSLOutArgExpr *Node) {
3062 PrintExpr(E: Node->getArgLValue());
3063}
3064
3065//===----------------------------------------------------------------------===//
3066// Stmt method implementations
3067//===----------------------------------------------------------------------===//
3068
3069void Stmt::dumpPretty(const ASTContext &Context) const {
3070 printPretty(OS&: llvm::errs(), Helper: nullptr, Policy: PrintingPolicy(Context.getLangOpts()));
3071}
3072
3073void Stmt::printPretty(raw_ostream &Out, PrinterHelper *Helper,
3074 const PrintingPolicy &Policy, unsigned Indentation,
3075 StringRef NL, const ASTContext *Context) const {
3076 StmtPrinter P(Out, Helper, Policy, Indentation, NL, Context);
3077 P.Visit(S: const_cast<Stmt *>(this));
3078}
3079
3080void Stmt::printPrettyControlled(raw_ostream &Out, PrinterHelper *Helper,
3081 const PrintingPolicy &Policy,
3082 unsigned Indentation, StringRef NL,
3083 const ASTContext *Context) const {
3084 StmtPrinter P(Out, Helper, Policy, Indentation, NL, Context);
3085 P.PrintControlledStmt(S: const_cast<Stmt *>(this));
3086}
3087
3088void Stmt::printJson(raw_ostream &Out, PrinterHelper *Helper,
3089 const PrintingPolicy &Policy, bool AddQuotes) const {
3090 std::string Buf;
3091 llvm::raw_string_ostream TempOut(Buf);
3092
3093 printPretty(Out&: TempOut, Helper, Policy);
3094
3095 Out << JsonFormat(RawSR: TempOut.str(), AddQuotes);
3096}
3097
3098//===----------------------------------------------------------------------===//
3099// PrinterHelper
3100//===----------------------------------------------------------------------===//
3101
3102// Implement virtual destructor.
3103PrinterHelper::~PrinterHelper() = default;
3104