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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/AST/StmtPrinter.cpp