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