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

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