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