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