1 | //===--- DeclPrinter.cpp - Printing implementation for Decl 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 Decl::print method, which pretty prints the |
10 | // AST back out to C/Objective-C/C++/Objective-C++ code. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | #include "clang/AST/ASTContext.h" |
14 | #include "clang/AST/Attr.h" |
15 | #include "clang/AST/Decl.h" |
16 | #include "clang/AST/DeclCXX.h" |
17 | #include "clang/AST/DeclObjC.h" |
18 | #include "clang/AST/DeclTemplate.h" |
19 | #include "clang/AST/DeclVisitor.h" |
20 | #include "clang/AST/Expr.h" |
21 | #include "clang/AST/ExprCXX.h" |
22 | #include "clang/AST/PrettyPrinter.h" |
23 | #include "clang/Basic/Module.h" |
24 | #include "clang/Basic/SourceManager.h" |
25 | #include "llvm/Support/raw_ostream.h" |
26 | using namespace clang; |
27 | |
28 | namespace { |
29 | class DeclPrinter : public DeclVisitor<DeclPrinter> { |
30 | raw_ostream &Out; |
31 | PrintingPolicy Policy; |
32 | const ASTContext &Context; |
33 | unsigned Indentation; |
34 | bool PrintInstantiation; |
35 | |
36 | raw_ostream& Indent() { return Indent(Indentation); } |
37 | raw_ostream& Indent(unsigned Indentation); |
38 | void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls); |
39 | |
40 | void Print(AccessSpecifier AS); |
41 | void PrintConstructorInitializers(CXXConstructorDecl *CDecl, |
42 | std::string &Proto); |
43 | |
44 | /// Print an Objective-C method type in parentheses. |
45 | /// |
46 | /// \param Quals The Objective-C declaration qualifiers. |
47 | /// \param T The type to print. |
48 | void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals, |
49 | QualType T); |
50 | |
51 | void PrintObjCTypeParams(ObjCTypeParamList *Params); |
52 | void PrintOpenACCRoutineOnLambda(Decl *D); |
53 | |
54 | public: |
55 | DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy, |
56 | const ASTContext &Context, unsigned Indentation = 0, |
57 | bool PrintInstantiation = false) |
58 | : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation), |
59 | PrintInstantiation(PrintInstantiation) {} |
60 | |
61 | void VisitDeclContext(DeclContext *DC, bool Indent = true); |
62 | |
63 | void VisitTranslationUnitDecl(TranslationUnitDecl *D); |
64 | void VisitTypedefDecl(TypedefDecl *D); |
65 | void VisitTypeAliasDecl(TypeAliasDecl *D); |
66 | void VisitEnumDecl(EnumDecl *D); |
67 | void VisitRecordDecl(RecordDecl *D); |
68 | void VisitEnumConstantDecl(EnumConstantDecl *D); |
69 | void VisitEmptyDecl(EmptyDecl *D); |
70 | void VisitFunctionDecl(FunctionDecl *D); |
71 | void VisitFriendDecl(FriendDecl *D); |
72 | void VisitFieldDecl(FieldDecl *D); |
73 | void VisitVarDecl(VarDecl *D); |
74 | void VisitLabelDecl(LabelDecl *D); |
75 | void VisitParmVarDecl(ParmVarDecl *D); |
76 | void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); |
77 | void VisitTopLevelStmtDecl(TopLevelStmtDecl *D); |
78 | void VisitImportDecl(ImportDecl *D); |
79 | void VisitStaticAssertDecl(StaticAssertDecl *D); |
80 | void VisitNamespaceDecl(NamespaceDecl *D); |
81 | void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); |
82 | void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); |
83 | void VisitCXXRecordDecl(CXXRecordDecl *D); |
84 | void VisitLinkageSpecDecl(LinkageSpecDecl *D); |
85 | void VisitTemplateDecl(const TemplateDecl *D); |
86 | void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); |
87 | void VisitClassTemplateDecl(ClassTemplateDecl *D); |
88 | void VisitClassTemplateSpecializationDecl( |
89 | ClassTemplateSpecializationDecl *D); |
90 | void VisitClassTemplatePartialSpecializationDecl( |
91 | ClassTemplatePartialSpecializationDecl *D); |
92 | void VisitObjCMethodDecl(ObjCMethodDecl *D); |
93 | void VisitObjCImplementationDecl(ObjCImplementationDecl *D); |
94 | void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); |
95 | void VisitObjCProtocolDecl(ObjCProtocolDecl *D); |
96 | void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); |
97 | void VisitObjCCategoryDecl(ObjCCategoryDecl *D); |
98 | void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); |
99 | void VisitObjCPropertyDecl(ObjCPropertyDecl *D); |
100 | void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); |
101 | void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); |
102 | void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); |
103 | void VisitUsingDecl(UsingDecl *D); |
104 | void VisitUsingEnumDecl(UsingEnumDecl *D); |
105 | void VisitUsingShadowDecl(UsingShadowDecl *D); |
106 | void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); |
107 | void VisitOMPAllocateDecl(OMPAllocateDecl *D); |
108 | void VisitOMPRequiresDecl(OMPRequiresDecl *D); |
109 | void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); |
110 | void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D); |
111 | void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); |
112 | void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP); |
113 | void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP); |
114 | void VisitHLSLBufferDecl(HLSLBufferDecl *D); |
115 | |
116 | void VisitOpenACCDeclareDecl(OpenACCDeclareDecl *D); |
117 | void VisitOpenACCRoutineDecl(OpenACCRoutineDecl *D); |
118 | |
119 | void printTemplateParameters(const TemplateParameterList *Params, |
120 | bool OmitTemplateKW = false); |
121 | void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args, |
122 | const TemplateParameterList *Params); |
123 | void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args, |
124 | const TemplateParameterList *Params); |
125 | enum class AttrPosAsWritten { Default = 0, Left, Right }; |
126 | bool |
127 | prettyPrintAttributes(const Decl *D, |
128 | AttrPosAsWritten Pos = AttrPosAsWritten::Default); |
129 | void prettyPrintPragmas(Decl *D); |
130 | void printDeclType(QualType T, StringRef DeclName, bool Pack = false); |
131 | }; |
132 | } |
133 | |
134 | void Decl::print(raw_ostream &Out, unsigned Indentation, |
135 | bool PrintInstantiation) const { |
136 | print(Out, Policy: getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation); |
137 | } |
138 | |
139 | void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, |
140 | unsigned Indentation, bool PrintInstantiation) const { |
141 | DeclPrinter Printer(Out, Policy, getASTContext(), Indentation, |
142 | PrintInstantiation); |
143 | Printer.Visit(const_cast<Decl*>(this)); |
144 | } |
145 | |
146 | void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, |
147 | bool OmitTemplateKW) const { |
148 | print(Out, Context, Policy: Context.getPrintingPolicy(), OmitTemplateKW); |
149 | } |
150 | |
151 | void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, |
152 | const PrintingPolicy &Policy, |
153 | bool OmitTemplateKW) const { |
154 | DeclPrinter Printer(Out, Policy, Context); |
155 | Printer.printTemplateParameters(Params: this, OmitTemplateKW); |
156 | } |
157 | |
158 | static QualType GetBaseType(QualType T) { |
159 | // FIXME: This should be on the Type class! |
160 | QualType BaseType = T; |
161 | while (!BaseType->isSpecifierType()) { |
162 | if (const PointerType *PTy = BaseType->getAs<PointerType>()) |
163 | BaseType = PTy->getPointeeType(); |
164 | else if (const ObjCObjectPointerType *OPT = |
165 | BaseType->getAs<ObjCObjectPointerType>()) |
166 | BaseType = OPT->getPointeeType(); |
167 | else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>()) |
168 | BaseType = BPy->getPointeeType(); |
169 | else if (const ArrayType *ATy = dyn_cast<ArrayType>(Val&: BaseType)) |
170 | BaseType = ATy->getElementType(); |
171 | else if (const FunctionType *FTy = BaseType->getAs<FunctionType>()) |
172 | BaseType = FTy->getReturnType(); |
173 | else if (const VectorType *VTy = BaseType->getAs<VectorType>()) |
174 | BaseType = VTy->getElementType(); |
175 | else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>()) |
176 | BaseType = RTy->getPointeeType(); |
177 | else if (const AutoType *ATy = BaseType->getAs<AutoType>()) |
178 | BaseType = ATy->getDeducedType(); |
179 | else if (const ParenType *PTy = BaseType->getAs<ParenType>()) |
180 | BaseType = PTy->desugar(); |
181 | else |
182 | // This must be a syntax error. |
183 | break; |
184 | } |
185 | return BaseType; |
186 | } |
187 | |
188 | static QualType getDeclType(Decl* D) { |
189 | if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(Val: D)) |
190 | return TDD->getUnderlyingType(); |
191 | if (ValueDecl* VD = dyn_cast<ValueDecl>(Val: D)) |
192 | return VD->getType(); |
193 | return QualType(); |
194 | } |
195 | |
196 | void Decl::printGroup(Decl** Begin, unsigned NumDecls, |
197 | raw_ostream &Out, const PrintingPolicy &Policy, |
198 | unsigned Indentation) { |
199 | if (NumDecls == 1) { |
200 | (*Begin)->print(Out, Policy, Indentation); |
201 | return; |
202 | } |
203 | |
204 | Decl** End = Begin + NumDecls; |
205 | TagDecl* TD = dyn_cast<TagDecl>(Val: *Begin); |
206 | if (TD) |
207 | ++Begin; |
208 | |
209 | PrintingPolicy SubPolicy(Policy); |
210 | |
211 | bool isFirst = true; |
212 | for ( ; Begin != End; ++Begin) { |
213 | if (isFirst) { |
214 | if(TD) |
215 | SubPolicy.IncludeTagDefinition = true; |
216 | SubPolicy.SuppressSpecifiers = false; |
217 | isFirst = false; |
218 | } else { |
219 | if (!isFirst) Out << ", "; |
220 | SubPolicy.IncludeTagDefinition = false; |
221 | SubPolicy.SuppressSpecifiers = true; |
222 | } |
223 | |
224 | (*Begin)->print(Out, Policy: SubPolicy, Indentation); |
225 | } |
226 | } |
227 | |
228 | LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const { |
229 | // Get the translation unit |
230 | const DeclContext *DC = this; |
231 | while (!DC->isTranslationUnit()) |
232 | DC = DC->getParent(); |
233 | |
234 | ASTContext &Ctx = cast<TranslationUnitDecl>(Val: DC)->getASTContext(); |
235 | DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0); |
236 | Printer.VisitDeclContext(DC: const_cast<DeclContext *>(this), /*Indent=*/false); |
237 | } |
238 | |
239 | raw_ostream& DeclPrinter::Indent(unsigned Indentation) { |
240 | for (unsigned i = 0; i != Indentation; ++i) |
241 | Out << " "; |
242 | return Out; |
243 | } |
244 | |
245 | static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A, |
246 | const Decl *D) { |
247 | SourceLocation ALoc = A->getLoc(); |
248 | SourceLocation DLoc = D->getLocation(); |
249 | const ASTContext &C = D->getASTContext(); |
250 | if (ALoc.isInvalid() || DLoc.isInvalid()) |
251 | return DeclPrinter::AttrPosAsWritten::Left; |
252 | |
253 | if (C.getSourceManager().isBeforeInTranslationUnit(LHS: ALoc, RHS: DLoc)) |
254 | return DeclPrinter::AttrPosAsWritten::Left; |
255 | |
256 | return DeclPrinter::AttrPosAsWritten::Right; |
257 | } |
258 | |
259 | // returns true if an attribute was printed. |
260 | bool DeclPrinter::prettyPrintAttributes(const Decl *D, |
261 | AttrPosAsWritten Pos /*=Default*/) { |
262 | bool hasPrinted = false; |
263 | |
264 | if (D->hasAttrs()) { |
265 | const AttrVec &Attrs = D->getAttrs(); |
266 | for (auto *A : Attrs) { |
267 | if (A->isInherited() || A->isImplicit()) |
268 | continue; |
269 | // Print out the keyword attributes, they aren't regular attributes. |
270 | if (Policy.PolishForDeclaration && !A->isKeywordAttribute()) |
271 | continue; |
272 | switch (A->getKind()) { |
273 | #define ATTR(X) |
274 | #define PRAGMA_SPELLING_ATTR(X) case attr::X: |
275 | #include "clang/Basic/AttrList.inc" |
276 | break; |
277 | default: |
278 | AttrPosAsWritten APos = getPosAsWritten(A, D); |
279 | assert(APos != AttrPosAsWritten::Default && |
280 | "Default not a valid for an attribute location"); |
281 | if (Pos == AttrPosAsWritten::Default || Pos == APos) { |
282 | if (Pos != AttrPosAsWritten::Left) |
283 | Out << ' '; |
284 | A->printPretty(OS&: Out, Policy); |
285 | hasPrinted = true; |
286 | if (Pos == AttrPosAsWritten::Left) |
287 | Out << ' '; |
288 | } |
289 | break; |
290 | } |
291 | } |
292 | } |
293 | return hasPrinted; |
294 | } |
295 | |
296 | void DeclPrinter::PrintOpenACCRoutineOnLambda(Decl *D) { |
297 | CXXRecordDecl *CXXRD = nullptr; |
298 | if (const auto *VD = dyn_cast<VarDecl>(Val: D)) { |
299 | if (const auto *Init = VD->getInit()) |
300 | CXXRD = Init->getType().isNull() ? nullptr |
301 | : Init->getType()->getAsCXXRecordDecl(); |
302 | } else if (const auto *FD = dyn_cast<FieldDecl>(Val: D)) { |
303 | CXXRD = |
304 | FD->getType().isNull() ? nullptr : FD->getType()->getAsCXXRecordDecl(); |
305 | } |
306 | |
307 | if (!CXXRD || !CXXRD->isLambda()) |
308 | return; |
309 | |
310 | if (const auto *Call = CXXRD->getLambdaCallOperator()) { |
311 | for (auto *A : Call->specific_attrs<OpenACCRoutineDeclAttr>()) { |
312 | A->printPretty(Out, Policy); |
313 | Indent(); |
314 | } |
315 | } |
316 | } |
317 | |
318 | void DeclPrinter::prettyPrintPragmas(Decl *D) { |
319 | if (Policy.PolishForDeclaration) |
320 | return; |
321 | |
322 | PrintOpenACCRoutineOnLambda(D); |
323 | |
324 | if (D->hasAttrs()) { |
325 | AttrVec &Attrs = D->getAttrs(); |
326 | for (auto *A : Attrs) { |
327 | switch (A->getKind()) { |
328 | #define ATTR(X) |
329 | #define PRAGMA_SPELLING_ATTR(X) case attr::X: |
330 | #include "clang/Basic/AttrList.inc" |
331 | A->printPretty(OS&: Out, Policy); |
332 | Indent(); |
333 | break; |
334 | default: |
335 | break; |
336 | } |
337 | } |
338 | } |
339 | } |
340 | |
341 | void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) { |
342 | // Normally, a PackExpansionType is written as T[3]... (for instance, as a |
343 | // template argument), but if it is the type of a declaration, the ellipsis |
344 | // is placed before the name being declared. |
345 | if (auto *PET = T->getAs<PackExpansionType>()) { |
346 | Pack = true; |
347 | T = PET->getPattern(); |
348 | } |
349 | T.print(OS&: Out, Policy, PlaceHolder: (Pack ? "...": "") + DeclName, Indentation); |
350 | } |
351 | |
352 | void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) { |
353 | this->Indent(); |
354 | Decl::printGroup(Begin: Decls.data(), NumDecls: Decls.size(), Out, Policy, Indentation); |
355 | Out << ";\n"; |
356 | Decls.clear(); |
357 | |
358 | } |
359 | |
360 | void DeclPrinter::Print(AccessSpecifier AS) { |
361 | const auto AccessSpelling = getAccessSpelling(AS); |
362 | if (AccessSpelling.empty()) |
363 | llvm_unreachable("No access specifier!"); |
364 | Out << AccessSpelling; |
365 | } |
366 | |
367 | void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl, |
368 | std::string &Proto) { |
369 | bool HasInitializerList = false; |
370 | for (const auto *BMInitializer : CDecl->inits()) { |
371 | if (BMInitializer->isInClassMemberInitializer()) |
372 | continue; |
373 | if (!BMInitializer->isWritten()) |
374 | continue; |
375 | |
376 | if (!HasInitializerList) { |
377 | Proto += " : "; |
378 | Out << Proto; |
379 | Proto.clear(); |
380 | HasInitializerList = true; |
381 | } else |
382 | Out << ", "; |
383 | |
384 | if (BMInitializer->isAnyMemberInitializer()) { |
385 | FieldDecl *FD = BMInitializer->getAnyMember(); |
386 | Out << *FD; |
387 | } else if (BMInitializer->isDelegatingInitializer()) { |
388 | Out << CDecl->getNameAsString(); |
389 | } else { |
390 | Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); |
391 | } |
392 | |
393 | if (Expr *Init = BMInitializer->getInit()) { |
394 | bool OutParens = !isa<InitListExpr>(Val: Init); |
395 | |
396 | if (OutParens) |
397 | Out << "("; |
398 | |
399 | if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Val: Init)) |
400 | Init = Tmp->getSubExpr(); |
401 | |
402 | Init = Init->IgnoreParens(); |
403 | |
404 | Expr *SimpleInit = nullptr; |
405 | Expr **Args = nullptr; |
406 | unsigned NumArgs = 0; |
407 | if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Val: Init)) { |
408 | Args = ParenList->getExprs(); |
409 | NumArgs = ParenList->getNumExprs(); |
410 | } else if (CXXConstructExpr *Construct = |
411 | dyn_cast<CXXConstructExpr>(Val: Init)) { |
412 | Args = Construct->getArgs(); |
413 | NumArgs = Construct->getNumArgs(); |
414 | } else |
415 | SimpleInit = Init; |
416 | |
417 | if (SimpleInit) |
418 | SimpleInit->printPretty(Out, nullptr, Policy, Indentation, "\n", |
419 | &Context); |
420 | else { |
421 | for (unsigned I = 0; I != NumArgs; ++I) { |
422 | assert(Args[I] != nullptr && "Expected non-null Expr"); |
423 | if (isa<CXXDefaultArgExpr>(Val: Args[I])) |
424 | break; |
425 | |
426 | if (I) |
427 | Out << ", "; |
428 | Args[I]->printPretty(Out, nullptr, Policy, Indentation, "\n", |
429 | &Context); |
430 | } |
431 | } |
432 | |
433 | if (OutParens) |
434 | Out << ")"; |
435 | } else { |
436 | Out << "()"; |
437 | } |
438 | |
439 | if (BMInitializer->isPackExpansion()) |
440 | Out << "..."; |
441 | } |
442 | } |
443 | |
444 | //---------------------------------------------------------------------------- |
445 | // Common C declarations |
446 | //---------------------------------------------------------------------------- |
447 | |
448 | void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { |
449 | if (Policy.TerseOutput) |
450 | return; |
451 | |
452 | if (Indent) |
453 | Indentation += Policy.Indentation; |
454 | |
455 | SmallVector<Decl*, 2> Decls; |
456 | for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); |
457 | D != DEnd; ++D) { |
458 | |
459 | // Don't print ObjCIvarDecls, as they are printed when visiting the |
460 | // containing ObjCInterfaceDecl. |
461 | if (isa<ObjCIvarDecl>(Val: *D)) |
462 | continue; |
463 | |
464 | // Skip over implicit declarations in pretty-printing mode. |
465 | if (D->isImplicit()) |
466 | continue; |
467 | |
468 | // Don't print implicit specializations, as they are printed when visiting |
469 | // corresponding templates. |
470 | if (auto FD = dyn_cast<FunctionDecl>(Val: *D)) |
471 | if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation && |
472 | !isa<ClassTemplateSpecializationDecl>(Val: DC)) |
473 | continue; |
474 | |
475 | // The next bits of code handle stuff like "struct {int x;} a,b"; we're |
476 | // forced to merge the declarations because there's no other way to |
477 | // refer to the struct in question. When that struct is named instead, we |
478 | // also need to merge to avoid splitting off a stand-alone struct |
479 | // declaration that produces the warning ext_no_declarators in some |
480 | // contexts. |
481 | // |
482 | // This limited merging is safe without a bunch of other checks because it |
483 | // only merges declarations directly referring to the tag, not typedefs. |
484 | // |
485 | // Check whether the current declaration should be grouped with a previous |
486 | // non-free-standing tag declaration. |
487 | QualType CurDeclType = getDeclType(D: *D); |
488 | if (!Decls.empty() && !CurDeclType.isNull()) { |
489 | QualType BaseType = GetBaseType(T: CurDeclType); |
490 | if (!BaseType.isNull() && isa<ElaboratedType>(Val: BaseType) && |
491 | cast<ElaboratedType>(Val&: BaseType)->getOwnedTagDecl() == Decls[0]) { |
492 | Decls.push_back(Elt: *D); |
493 | continue; |
494 | } |
495 | } |
496 | |
497 | // If we have a merged group waiting to be handled, handle it now. |
498 | if (!Decls.empty()) |
499 | ProcessDeclGroup(Decls); |
500 | |
501 | // If the current declaration is not a free standing declaration, save it |
502 | // so we can merge it with the subsequent declaration(s) using it. |
503 | if (isa<TagDecl>(Val: *D) && !cast<TagDecl>(Val: *D)->isFreeStanding()) { |
504 | Decls.push_back(Elt: *D); |
505 | continue; |
506 | } |
507 | |
508 | if (isa<AccessSpecDecl>(Val: *D)) { |
509 | Indentation -= Policy.Indentation; |
510 | this->Indent(); |
511 | Print(AS: D->getAccess()); |
512 | Out << ":\n"; |
513 | Indentation += Policy.Indentation; |
514 | continue; |
515 | } |
516 | |
517 | this->Indent(); |
518 | Visit(*D); |
519 | |
520 | // FIXME: Need to be able to tell the DeclPrinter when |
521 | const char *Terminator = nullptr; |
522 | if (isa<OMPThreadPrivateDecl>(Val: *D) || isa<OMPDeclareReductionDecl>(Val: *D) || |
523 | isa<OMPDeclareMapperDecl>(Val: *D) || isa<OMPRequiresDecl>(Val: *D) || |
524 | isa<OMPAllocateDecl>(Val: *D)) |
525 | Terminator = nullptr; |
526 | else if (isa<OpenACCDeclareDecl, OpenACCRoutineDecl>(Val: *D)) |
527 | Terminator = nullptr; |
528 | else if (isa<ObjCMethodDecl>(Val: *D) && cast<ObjCMethodDecl>(Val: *D)->hasBody()) |
529 | Terminator = nullptr; |
530 | else if (auto FD = dyn_cast<FunctionDecl>(Val: *D)) { |
531 | if (FD->doesThisDeclarationHaveABody() && !FD->isDefaulted()) |
532 | Terminator = nullptr; |
533 | else |
534 | Terminator = ";"; |
535 | } else if (auto TD = dyn_cast<FunctionTemplateDecl>(Val: *D)) { |
536 | if (TD->getTemplatedDecl()->doesThisDeclarationHaveABody()) |
537 | Terminator = nullptr; |
538 | else |
539 | Terminator = ";"; |
540 | } else if (isa<NamespaceDecl, LinkageSpecDecl, ObjCImplementationDecl, |
541 | ObjCInterfaceDecl, ObjCProtocolDecl, ObjCCategoryImplDecl, |
542 | ObjCCategoryDecl, HLSLBufferDecl>(Val: *D)) |
543 | Terminator = nullptr; |
544 | else if (isa<EnumConstantDecl>(Val: *D)) { |
545 | DeclContext::decl_iterator Next = D; |
546 | ++Next; |
547 | if (Next != DEnd) |
548 | Terminator = ","; |
549 | } else |
550 | Terminator = ";"; |
551 | |
552 | if (Terminator) |
553 | Out << Terminator; |
554 | if (!Policy.TerseOutput && |
555 | ((isa<FunctionDecl>(Val: *D) && |
556 | cast<FunctionDecl>(Val: *D)->doesThisDeclarationHaveABody()) || |
557 | (isa<FunctionTemplateDecl>(Val: *D) && |
558 | cast<FunctionTemplateDecl>(Val: *D)->getTemplatedDecl()->doesThisDeclarationHaveABody()))) |
559 | ; // StmtPrinter already added '\n' after CompoundStmt. |
560 | else |
561 | Out << "\n"; |
562 | |
563 | // Declare target attribute is special one, natural spelling for the pragma |
564 | // assumes "ending" construct so print it here. |
565 | if (D->hasAttr<OMPDeclareTargetDeclAttr>()) |
566 | Out << "#pragma omp end declare target\n"; |
567 | } |
568 | |
569 | if (!Decls.empty()) |
570 | ProcessDeclGroup(Decls); |
571 | |
572 | if (Indent) |
573 | Indentation -= Policy.Indentation; |
574 | } |
575 | |
576 | void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { |
577 | VisitDeclContext(D, false); |
578 | } |
579 | |
580 | void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { |
581 | if (!Policy.SuppressSpecifiers) { |
582 | Out << "typedef "; |
583 | |
584 | if (D->isModulePrivate()) |
585 | Out << "__module_private__ "; |
586 | } |
587 | QualType Ty = D->getTypeSourceInfo()->getType(); |
588 | Ty.print(Out, Policy, D->getName(), Indentation); |
589 | prettyPrintAttributes(D); |
590 | } |
591 | |
592 | void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { |
593 | Out << "using "<< *D; |
594 | prettyPrintAttributes(D); |
595 | Out << " = "<< D->getTypeSourceInfo()->getType().getAsString(Policy); |
596 | } |
597 | |
598 | void DeclPrinter::VisitEnumDecl(EnumDecl *D) { |
599 | if (!Policy.SuppressSpecifiers && D->isModulePrivate()) |
600 | Out << "__module_private__ "; |
601 | Out << "enum"; |
602 | if (D->isScoped()) { |
603 | if (D->isScopedUsingClassTag()) |
604 | Out << " class"; |
605 | else |
606 | Out << " struct"; |
607 | } |
608 | |
609 | prettyPrintAttributes(D); |
610 | |
611 | if (D->getDeclName()) |
612 | Out << ' ' << D->getDeclName(); |
613 | |
614 | if (D->isFixed()) |
615 | Out << " : "<< D->getIntegerType().stream(Policy); |
616 | |
617 | if (D->isCompleteDefinition()) { |
618 | Out << " {\n"; |
619 | VisitDeclContext(D); |
620 | Indent() << "}"; |
621 | } |
622 | } |
623 | |
624 | void DeclPrinter::VisitRecordDecl(RecordDecl *D) { |
625 | if (!Policy.SuppressSpecifiers && D->isModulePrivate()) |
626 | Out << "__module_private__ "; |
627 | Out << D->getKindName(); |
628 | |
629 | prettyPrintAttributes(D); |
630 | |
631 | if (D->getIdentifier()) |
632 | Out << ' ' << *D; |
633 | |
634 | if (D->isCompleteDefinition()) { |
635 | Out << " {\n"; |
636 | VisitDeclContext(D); |
637 | Indent() << "}"; |
638 | } |
639 | } |
640 | |
641 | void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { |
642 | Out << *D; |
643 | prettyPrintAttributes(D); |
644 | if (Expr *Init = D->getInitExpr()) { |
645 | Out << " = "; |
646 | Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); |
647 | } |
648 | } |
649 | |
650 | static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out, |
651 | PrintingPolicy &Policy, unsigned Indentation, |
652 | const ASTContext &Context) { |
653 | std::string Proto = "explicit"; |
654 | llvm::raw_string_ostream EOut(Proto); |
655 | if (ES.getExpr()) { |
656 | EOut << "("; |
657 | ES.getExpr()->printPretty(EOut, nullptr, Policy, Indentation, "\n", |
658 | &Context); |
659 | EOut << ")"; |
660 | } |
661 | EOut << " "; |
662 | Out << Proto; |
663 | } |
664 | |
665 | static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy, |
666 | QualType T, |
667 | llvm::raw_ostream &Out) { |
668 | StringRef prefix = T->isClassType() ? "class " |
669 | : T->isStructureType() ? "struct " |
670 | : T->isUnionType() ? "union " |
671 | : ""; |
672 | Out << prefix; |
673 | } |
674 | |
675 | void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { |
676 | if (!D->getDescribedFunctionTemplate() && |
677 | !D->isFunctionTemplateSpecialization()) { |
678 | prettyPrintPragmas(D); |
679 | prettyPrintAttributes(D, AttrPosAsWritten::Left); |
680 | } |
681 | |
682 | if (D->isFunctionTemplateSpecialization()) |
683 | Out << "template<> "; |
684 | else if (!D->getDescribedFunctionTemplate()) { |
685 | for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists(); |
686 | I < NumTemplateParams; ++I) |
687 | printTemplateParameters(Params: D->getTemplateParameterList(I)); |
688 | } |
689 | |
690 | CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(Val: D); |
691 | CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(Val: D); |
692 | CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(Val: D); |
693 | if (!Policy.SuppressSpecifiers) { |
694 | switch (D->getStorageClass()) { |
695 | case SC_None: break; |
696 | case SC_Extern: Out << "extern "; break; |
697 | case SC_Static: Out << "static "; break; |
698 | case SC_PrivateExtern: Out << "__private_extern__ "; break; |
699 | case SC_Auto: case SC_Register: |
700 | llvm_unreachable("invalid for functions"); |
701 | } |
702 | |
703 | if (D->isInlineSpecified()) Out << "inline "; |
704 | if (D->isVirtualAsWritten()) Out << "virtual "; |
705 | if (D->isModulePrivate()) Out << "__module_private__ "; |
706 | if (D->isConstexprSpecified() && !D->isExplicitlyDefaulted()) |
707 | Out << "constexpr "; |
708 | if (D->isConsteval()) Out << "consteval "; |
709 | else if (D->isImmediateFunction()) |
710 | Out << "immediate "; |
711 | ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(Function: D); |
712 | if (ExplicitSpec.isSpecified()) |
713 | printExplicitSpecifier(ES: ExplicitSpec, Out, Policy, Indentation, Context); |
714 | } |
715 | |
716 | PrintingPolicy SubPolicy(Policy); |
717 | SubPolicy.SuppressSpecifiers = false; |
718 | std::string Proto; |
719 | |
720 | if (Policy.FullyQualifiedName) { |
721 | Proto += D->getQualifiedNameAsString(); |
722 | } else { |
723 | llvm::raw_string_ostream OS(Proto); |
724 | if (!Policy.SuppressScope) { |
725 | if (const NestedNameSpecifier *NS = D->getQualifier()) { |
726 | NS->print(OS, Policy); |
727 | } |
728 | } |
729 | D->getNameInfo().printName(OS, Policy); |
730 | } |
731 | |
732 | if (GuideDecl) |
733 | Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString(); |
734 | if (D->isFunctionTemplateSpecialization()) { |
735 | llvm::raw_string_ostream POut(Proto); |
736 | DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation); |
737 | const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten(); |
738 | if (TArgAsWritten && !Policy.PrintAsCanonical) |
739 | TArgPrinter.printTemplateArguments(Args: TArgAsWritten->arguments(), Params: nullptr); |
740 | else if (const TemplateArgumentList *TArgs = |
741 | D->getTemplateSpecializationArgs()) |
742 | TArgPrinter.printTemplateArguments(Args: TArgs->asArray(), Params: nullptr); |
743 | } |
744 | |
745 | QualType Ty = D->getType(); |
746 | while (const ParenType *PT = dyn_cast<ParenType>(Val&: Ty)) { |
747 | Proto = '(' + Proto + ')'; |
748 | Ty = PT->getInnerType(); |
749 | } |
750 | |
751 | if (const FunctionType *AFT = Ty->getAs<FunctionType>()) { |
752 | const FunctionProtoType *FT = nullptr; |
753 | if (D->hasWrittenPrototype()) |
754 | FT = dyn_cast<FunctionProtoType>(Val: AFT); |
755 | |
756 | Proto += "("; |
757 | if (FT) { |
758 | llvm::raw_string_ostream POut(Proto); |
759 | DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation); |
760 | for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { |
761 | if (i) POut << ", "; |
762 | ParamPrinter.VisitParmVarDecl(D: D->getParamDecl(i)); |
763 | } |
764 | |
765 | if (FT->isVariadic()) { |
766 | if (D->getNumParams()) POut << ", "; |
767 | POut << "..."; |
768 | } else if (!D->getNumParams() && !Context.getLangOpts().CPlusPlus) { |
769 | // The function has a prototype, so it needs to retain the prototype |
770 | // in C. |
771 | POut << "void"; |
772 | } |
773 | } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { |
774 | for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { |
775 | if (i) |
776 | Proto += ", "; |
777 | Proto += D->getParamDecl(i)->getNameAsString(); |
778 | } |
779 | } |
780 | |
781 | Proto += ")"; |
782 | |
783 | if (FT) { |
784 | if (FT->isConst()) |
785 | Proto += " const"; |
786 | if (FT->isVolatile()) |
787 | Proto += " volatile"; |
788 | if (FT->isRestrict()) |
789 | Proto += " restrict"; |
790 | |
791 | switch (FT->getRefQualifier()) { |
792 | case RQ_None: |
793 | break; |
794 | case RQ_LValue: |
795 | Proto += " &"; |
796 | break; |
797 | case RQ_RValue: |
798 | Proto += " &&"; |
799 | break; |
800 | } |
801 | } |
802 | |
803 | if (FT && FT->hasDynamicExceptionSpec()) { |
804 | Proto += " throw("; |
805 | if (FT->getExceptionSpecType() == EST_MSAny) |
806 | Proto += "..."; |
807 | else |
808 | for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { |
809 | if (I) |
810 | Proto += ", "; |
811 | |
812 | Proto += FT->getExceptionType(i: I).getAsString(Policy: SubPolicy); |
813 | } |
814 | Proto += ")"; |
815 | } else if (FT && isNoexceptExceptionSpec(ESpecType: FT->getExceptionSpecType())) { |
816 | Proto += " noexcept"; |
817 | if (isComputedNoexcept(ESpecType: FT->getExceptionSpecType())) { |
818 | Proto += "("; |
819 | llvm::raw_string_ostream EOut(Proto); |
820 | FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy, |
821 | Indentation, "\n", &Context); |
822 | Proto += ")"; |
823 | } |
824 | } |
825 | |
826 | if (CDecl) { |
827 | if (!Policy.TerseOutput) |
828 | PrintConstructorInitializers(CDecl, Proto); |
829 | } else if (!ConversionDecl && !isa<CXXDestructorDecl>(Val: D)) { |
830 | if (FT && FT->hasTrailingReturn()) { |
831 | if (!GuideDecl) |
832 | Out << "auto "; |
833 | Out << Proto << " -> "; |
834 | Proto.clear(); |
835 | } |
836 | if (!Policy.SuppressTagKeyword && Policy.SuppressScope && |
837 | !Policy.SuppressUnwrittenScope) |
838 | MaybePrintTagKeywordIfSupressingScopes(Policy, T: AFT->getReturnType(), |
839 | Out); |
840 | AFT->getReturnType().print(OS&: Out, Policy, PlaceHolder: Proto); |
841 | Proto.clear(); |
842 | } |
843 | Out << Proto; |
844 | |
845 | if (const AssociatedConstraint &TrailingRequiresClause = |
846 | D->getTrailingRequiresClause()) { |
847 | Out << " requires "; |
848 | // FIXME: The printer could support printing expressions and types as if |
849 | // expanded by an index. Pass in the ArgumentPackSubstitutionIndex when |
850 | // that's supported. |
851 | TrailingRequiresClause.ConstraintExpr->printPretty( |
852 | Out, nullptr, SubPolicy, Indentation, "\n", &Context); |
853 | } |
854 | } else { |
855 | Ty.print(OS&: Out, Policy, PlaceHolder: Proto); |
856 | } |
857 | |
858 | prettyPrintAttributes(D, AttrPosAsWritten::Right); |
859 | |
860 | if (D->isPureVirtual()) |
861 | Out << " = 0"; |
862 | else if (D->isDeletedAsWritten()) { |
863 | Out << " = delete"; |
864 | if (const StringLiteral *M = D->getDeletedMessage()) { |
865 | Out << "("; |
866 | M->outputString(OS&: Out); |
867 | Out << ")"; |
868 | } |
869 | } else if (D->isExplicitlyDefaulted()) |
870 | Out << " = default"; |
871 | else if (D->doesThisDeclarationHaveABody()) { |
872 | if (!Policy.TerseOutput) { |
873 | if (!D->hasPrototype() && D->getNumParams()) { |
874 | // This is a K&R function definition, so we need to print the |
875 | // parameters. |
876 | Out << '\n'; |
877 | DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation); |
878 | Indentation += Policy.Indentation; |
879 | for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { |
880 | Indent(); |
881 | ParamPrinter.VisitParmVarDecl(D: D->getParamDecl(i)); |
882 | Out << ";\n"; |
883 | } |
884 | Indentation -= Policy.Indentation; |
885 | } |
886 | |
887 | if (D->getBody()) |
888 | D->getBody()->printPrettyControlled(OS&: Out, Helper: nullptr, Policy: SubPolicy, Indentation, NewlineSymbol: "\n", |
889 | Context: &Context); |
890 | } else { |
891 | if (!Policy.TerseOutput && isa<CXXConstructorDecl>(Val: *D)) |
892 | Out << " {}"; |
893 | } |
894 | } |
895 | } |
896 | |
897 | void DeclPrinter::VisitFriendDecl(FriendDecl *D) { |
898 | if (TypeSourceInfo *TSI = D->getFriendType()) { |
899 | unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists(); |
900 | for (unsigned i = 0; i < NumTPLists; ++i) |
901 | printTemplateParameters(Params: D->getFriendTypeTemplateParameterList(N: i)); |
902 | Out << "friend "; |
903 | Out << TSI->getType().getAsString(Policy); |
904 | } |
905 | else if (FunctionDecl *FD = |
906 | dyn_cast<FunctionDecl>(Val: D->getFriendDecl())) { |
907 | Out << "friend "; |
908 | VisitFunctionDecl(D: FD); |
909 | } |
910 | else if (FunctionTemplateDecl *FTD = |
911 | dyn_cast<FunctionTemplateDecl>(Val: D->getFriendDecl())) { |
912 | Out << "friend "; |
913 | VisitFunctionTemplateDecl(D: FTD); |
914 | } |
915 | else if (ClassTemplateDecl *CTD = |
916 | dyn_cast<ClassTemplateDecl>(Val: D->getFriendDecl())) { |
917 | Out << "friend "; |
918 | VisitRedeclarableTemplateDecl(CTD); |
919 | } |
920 | |
921 | if (D->isPackExpansion()) |
922 | Out << "..."; |
923 | } |
924 | |
925 | void DeclPrinter::VisitFieldDecl(FieldDecl *D) { |
926 | prettyPrintPragmas(D); |
927 | // FIXME: add printing of pragma attributes if required. |
928 | if (!Policy.SuppressSpecifiers && D->isMutable()) |
929 | Out << "mutable "; |
930 | if (!Policy.SuppressSpecifiers && D->isModulePrivate()) |
931 | Out << "__module_private__ "; |
932 | |
933 | Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()). |
934 | stream(Policy, D->getName(), Indentation); |
935 | |
936 | if (D->isBitField()) { |
937 | Out << " : "; |
938 | D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation, "\n", |
939 | &Context); |
940 | } |
941 | |
942 | Expr *Init = D->getInClassInitializer(); |
943 | if (!Policy.SuppressInitializers && Init) { |
944 | if (D->getInClassInitStyle() == ICIS_ListInit) |
945 | Out << " "; |
946 | else |
947 | Out << " = "; |
948 | Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); |
949 | } |
950 | prettyPrintAttributes(D); |
951 | } |
952 | |
953 | void DeclPrinter::VisitLabelDecl(LabelDecl *D) { |
954 | Out << *D << ":"; |
955 | } |
956 | |
957 | void DeclPrinter::VisitVarDecl(VarDecl *D) { |
958 | prettyPrintPragmas(D); |
959 | |
960 | prettyPrintAttributes(D, AttrPosAsWritten::Left); |
961 | |
962 | if (const auto *Param = dyn_cast<ParmVarDecl>(Val: D); |
963 | Param && Param->isExplicitObjectParameter()) |
964 | Out << "this "; |
965 | |
966 | QualType T = D->getTypeSourceInfo() |
967 | ? D->getTypeSourceInfo()->getType() |
968 | : D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); |
969 | |
970 | if (!Policy.SuppressSpecifiers) { |
971 | StorageClass SC = D->getStorageClass(); |
972 | if (SC != SC_None) |
973 | Out << VarDecl::getStorageClassSpecifierString(SC) << " "; |
974 | |
975 | switch (D->getTSCSpec()) { |
976 | case TSCS_unspecified: |
977 | break; |
978 | case TSCS___thread: |
979 | Out << "__thread "; |
980 | break; |
981 | case TSCS__Thread_local: |
982 | Out << "_Thread_local "; |
983 | break; |
984 | case TSCS_thread_local: |
985 | Out << "thread_local "; |
986 | break; |
987 | } |
988 | |
989 | if (D->isModulePrivate()) |
990 | Out << "__module_private__ "; |
991 | |
992 | if (D->isConstexpr()) { |
993 | Out << "constexpr "; |
994 | T.removeLocalConst(); |
995 | } |
996 | } |
997 | |
998 | if (!Policy.SuppressTagKeyword && Policy.SuppressScope && |
999 | !Policy.SuppressUnwrittenScope) |
1000 | MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out); |
1001 | |
1002 | printDeclType(T, DeclName: (isa<ParmVarDecl>(Val: D) && Policy.CleanUglifiedParameters && |
1003 | D->getIdentifier()) |
1004 | ? D->getIdentifier()->deuglifiedName() |
1005 | : D->getName()); |
1006 | |
1007 | prettyPrintAttributes(D, AttrPosAsWritten::Right); |
1008 | |
1009 | Expr *Init = D->getInit(); |
1010 | if (!Policy.SuppressInitializers && Init) { |
1011 | bool ImplicitInit = false; |
1012 | if (D->isCXXForRangeDecl()) { |
1013 | // FIXME: We should print the range expression instead. |
1014 | ImplicitInit = true; |
1015 | } else if (CXXConstructExpr *Construct = |
1016 | dyn_cast<CXXConstructExpr>(Val: Init->IgnoreImplicit())) { |
1017 | if (D->getInitStyle() == VarDecl::CallInit && |
1018 | !Construct->isListInitialization()) { |
1019 | ImplicitInit = Construct->getNumArgs() == 0 || |
1020 | Construct->getArg(Arg: 0)->isDefaultArgument(); |
1021 | } |
1022 | } |
1023 | if (!ImplicitInit) { |
1024 | if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Val: Init)) |
1025 | Out << "("; |
1026 | else if (D->getInitStyle() == VarDecl::CInit) { |
1027 | Out << " = "; |
1028 | } |
1029 | PrintingPolicy SubPolicy(Policy); |
1030 | SubPolicy.SuppressSpecifiers = false; |
1031 | SubPolicy.IncludeTagDefinition = false; |
1032 | Init->printPretty(Out, nullptr, SubPolicy, Indentation, "\n", &Context); |
1033 | if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Val: Init)) |
1034 | Out << ")"; |
1035 | } |
1036 | } |
1037 | } |
1038 | |
1039 | void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { |
1040 | VisitVarDecl(D); |
1041 | } |
1042 | |
1043 | void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { |
1044 | Out << "__asm ("; |
1045 | D->getAsmStringExpr()->printPretty(Out, nullptr, Policy, Indentation, "\n", |
1046 | &Context); |
1047 | Out << ")"; |
1048 | } |
1049 | |
1050 | void DeclPrinter::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) { |
1051 | assert(D->getStmt()); |
1052 | D->getStmt()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n", Context: &Context); |
1053 | } |
1054 | |
1055 | void DeclPrinter::VisitImportDecl(ImportDecl *D) { |
1056 | Out << "@import "<< D->getImportedModule()->getFullModuleName() |
1057 | << ";\n"; |
1058 | } |
1059 | |
1060 | void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { |
1061 | Out << "static_assert("; |
1062 | D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation, "\n", |
1063 | &Context); |
1064 | if (Expr *E = D->getMessage()) { |
1065 | Out << ", "; |
1066 | E->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); |
1067 | } |
1068 | Out << ")"; |
1069 | } |
1070 | |
1071 | //---------------------------------------------------------------------------- |
1072 | // C++ declarations |
1073 | //---------------------------------------------------------------------------- |
1074 | void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { |
1075 | if (D->isInline()) |
1076 | Out << "inline "; |
1077 | |
1078 | Out << "namespace "; |
1079 | if (D->getDeclName()) |
1080 | Out << D->getDeclName() << ' '; |
1081 | Out << "{\n"; |
1082 | |
1083 | VisitDeclContext(D); |
1084 | Indent() << "}"; |
1085 | } |
1086 | |
1087 | void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { |
1088 | Out << "using namespace "; |
1089 | if (D->getQualifier()) |
1090 | D->getQualifier()->print(OS&: Out, Policy); |
1091 | Out << *D->getNominatedNamespaceAsWritten(); |
1092 | } |
1093 | |
1094 | void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { |
1095 | Out << "namespace "<< *D << " = "; |
1096 | if (D->getQualifier()) |
1097 | D->getQualifier()->print(OS&: Out, Policy); |
1098 | Out << *D->getAliasedNamespace(); |
1099 | } |
1100 | |
1101 | void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) { |
1102 | prettyPrintAttributes(D); |
1103 | } |
1104 | |
1105 | void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { |
1106 | // FIXME: add printing of pragma attributes if required. |
1107 | if (!Policy.SuppressSpecifiers && D->isModulePrivate()) |
1108 | Out << "__module_private__ "; |
1109 | |
1110 | Out << D->getKindName() << ' '; |
1111 | |
1112 | // FIXME: Move before printing the decl kind to match the behavior of the |
1113 | // attribute printing for variables and function where they are printed first. |
1114 | if (prettyPrintAttributes(D, AttrPosAsWritten::Left)) |
1115 | Out << ' '; |
1116 | |
1117 | if (D->getIdentifier()) { |
1118 | if (auto *NNS = D->getQualifier()) |
1119 | NNS->print(Out, Policy); |
1120 | Out << *D; |
1121 | |
1122 | if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) { |
1123 | const TemplateParameterList *TParams = |
1124 | S->getSpecializedTemplate()->getTemplateParameters(); |
1125 | const ASTTemplateArgumentListInfo *TArgAsWritten = |
1126 | S->getTemplateArgsAsWritten(); |
1127 | if (TArgAsWritten && !Policy.PrintAsCanonical) |
1128 | printTemplateArguments(Args: TArgAsWritten->arguments(), Params: TParams); |
1129 | else |
1130 | printTemplateArguments(Args: S->getTemplateArgs().asArray(), Params: TParams); |
1131 | } |
1132 | } |
1133 | |
1134 | prettyPrintAttributes(D, AttrPosAsWritten::Right); |
1135 | |
1136 | if (D->isCompleteDefinition()) { |
1137 | Out << ' '; |
1138 | // Print the base classes |
1139 | if (D->getNumBases()) { |
1140 | Out << ": "; |
1141 | for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), |
1142 | BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { |
1143 | if (Base != D->bases_begin()) |
1144 | Out << ", "; |
1145 | |
1146 | if (Base->isVirtual()) |
1147 | Out << "virtual "; |
1148 | |
1149 | AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); |
1150 | if (AS != AS_none) { |
1151 | Print(AS); |
1152 | Out << " "; |
1153 | } |
1154 | Out << Base->getType().getAsString(Policy); |
1155 | |
1156 | if (Base->isPackExpansion()) |
1157 | Out << "..."; |
1158 | } |
1159 | Out << ' '; |
1160 | } |
1161 | |
1162 | // Print the class definition |
1163 | // FIXME: Doesn't print access specifiers, e.g., "public:" |
1164 | if (Policy.TerseOutput) { |
1165 | Out << "{}"; |
1166 | } else { |
1167 | Out << "{\n"; |
1168 | VisitDeclContext(D); |
1169 | Indent() << "}"; |
1170 | } |
1171 | } |
1172 | } |
1173 | |
1174 | void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { |
1175 | const char *l; |
1176 | if (D->getLanguage() == LinkageSpecLanguageIDs::C) |
1177 | l = "C"; |
1178 | else { |
1179 | assert(D->getLanguage() == LinkageSpecLanguageIDs::CXX && |
1180 | "unknown language in linkage specification"); |
1181 | l = "C++"; |
1182 | } |
1183 | |
1184 | Out << "extern \""<< l << "\" "; |
1185 | if (D->hasBraces()) { |
1186 | Out << "{\n"; |
1187 | VisitDeclContext(D); |
1188 | Indent() << "}"; |
1189 | } else |
1190 | Visit(*D->decls_begin()); |
1191 | } |
1192 | |
1193 | void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params, |
1194 | bool OmitTemplateKW) { |
1195 | assert(Params); |
1196 | |
1197 | // Don't print invented template parameter lists. |
1198 | if (!Params->empty() && Params->getParam(Idx: 0)->isImplicit()) |
1199 | return; |
1200 | |
1201 | if (!OmitTemplateKW) |
1202 | Out << "template "; |
1203 | Out << '<'; |
1204 | |
1205 | bool NeedComma = false; |
1206 | for (const Decl *Param : *Params) { |
1207 | if (Param->isImplicit()) |
1208 | continue; |
1209 | |
1210 | if (NeedComma) |
1211 | Out << ", "; |
1212 | else |
1213 | NeedComma = true; |
1214 | |
1215 | if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { |
1216 | VisitTemplateTypeParmDecl(TTP: TTP); |
1217 | } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { |
1218 | VisitNonTypeTemplateParmDecl(NTTP: NTTP); |
1219 | } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) { |
1220 | VisitTemplateDecl(D: TTPD); |
1221 | // FIXME: print the default argument, if present. |
1222 | } |
1223 | } |
1224 | |
1225 | Out << '>'; |
1226 | |
1227 | if (const Expr *RequiresClause = Params->getRequiresClause()) { |
1228 | Out << " requires "; |
1229 | RequiresClause->printPretty(Out, nullptr, Policy, Indentation, "\n", |
1230 | &Context); |
1231 | } |
1232 | |
1233 | if (!OmitTemplateKW) |
1234 | Out << ' '; |
1235 | } |
1236 | |
1237 | void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args, |
1238 | const TemplateParameterList *Params) { |
1239 | Out << "<"; |
1240 | for (size_t I = 0, E = Args.size(); I < E; ++I) { |
1241 | if (I) |
1242 | Out << ", "; |
1243 | if (!Params) |
1244 | Args[I].print(Policy, Out, /*IncludeType*/ true); |
1245 | else |
1246 | Args[I].print(Policy, Out, |
1247 | IncludeType: TemplateParameterList::shouldIncludeTypeForArgument( |
1248 | Policy, TPL: Params, Idx: I)); |
1249 | } |
1250 | Out << ">"; |
1251 | } |
1252 | |
1253 | void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args, |
1254 | const TemplateParameterList *Params) { |
1255 | Out << "<"; |
1256 | for (size_t I = 0, E = Args.size(); I < E; ++I) { |
1257 | if (I) |
1258 | Out << ", "; |
1259 | if (!Params) |
1260 | Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true); |
1261 | else |
1262 | Args[I].getArgument().print( |
1263 | Policy, Out, |
1264 | IncludeType: TemplateParameterList::shouldIncludeTypeForArgument(Policy, TPL: Params, |
1265 | Idx: I)); |
1266 | } |
1267 | Out << ">"; |
1268 | } |
1269 | |
1270 | void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { |
1271 | printTemplateParameters(Params: D->getTemplateParameters()); |
1272 | |
1273 | if (const TemplateTemplateParmDecl *TTP = |
1274 | dyn_cast<TemplateTemplateParmDecl>(Val: D)) { |
1275 | if (TTP->wasDeclaredWithTypename()) |
1276 | Out << "typename"; |
1277 | else |
1278 | Out << "class"; |
1279 | |
1280 | if (TTP->isParameterPack()) |
1281 | Out << " ..."; |
1282 | else if (TTP->getDeclName()) |
1283 | Out << ' '; |
1284 | |
1285 | if (TTP->getDeclName()) { |
1286 | if (Policy.CleanUglifiedParameters && TTP->getIdentifier()) |
1287 | Out << TTP->getIdentifier()->deuglifiedName(); |
1288 | else |
1289 | Out << TTP->getDeclName(); |
1290 | } |
1291 | } else if (auto *TD = D->getTemplatedDecl()) |
1292 | Visit(TD); |
1293 | else if (const auto *Concept = dyn_cast<ConceptDecl>(Val: D)) { |
1294 | Out << "concept "<< Concept->getName() << " = "; |
1295 | Concept->getConstraintExpr()->printPretty(Out, nullptr, Policy, Indentation, |
1296 | "\n", &Context); |
1297 | } |
1298 | } |
1299 | |
1300 | void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { |
1301 | prettyPrintPragmas(D->getTemplatedDecl()); |
1302 | // Print any leading template parameter lists. |
1303 | if (const FunctionDecl *FD = D->getTemplatedDecl()) { |
1304 | for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists(); |
1305 | I < NumTemplateParams; ++I) |
1306 | printTemplateParameters(Params: FD->getTemplateParameterList(I)); |
1307 | } |
1308 | VisitRedeclarableTemplateDecl(D); |
1309 | // Declare target attribute is special one, natural spelling for the pragma |
1310 | // assumes "ending" construct so print it here. |
1311 | if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>()) |
1312 | Out << "#pragma omp end declare target\n"; |
1313 | |
1314 | // Never print "instantiations" for deduction guides (they don't really |
1315 | // have them). |
1316 | if (PrintInstantiation && |
1317 | !isa<CXXDeductionGuideDecl>(Val: D->getTemplatedDecl())) { |
1318 | FunctionDecl *PrevDecl = D->getTemplatedDecl(); |
1319 | const FunctionDecl *Def; |
1320 | if (PrevDecl->isDefined(Definition&: Def) && Def != PrevDecl) |
1321 | return; |
1322 | for (auto *I : D->specializations()) |
1323 | if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) { |
1324 | if (!PrevDecl->isThisDeclarationADefinition()) |
1325 | Out << ";\n"; |
1326 | Indent(); |
1327 | prettyPrintPragmas(I); |
1328 | Visit(I); |
1329 | } |
1330 | } |
1331 | } |
1332 | |
1333 | void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { |
1334 | VisitRedeclarableTemplateDecl(D); |
1335 | |
1336 | if (PrintInstantiation) { |
1337 | for (auto *I : D->specializations()) |
1338 | if (I->getSpecializationKind() == TSK_ImplicitInstantiation) { |
1339 | if (D->isThisDeclarationADefinition()) |
1340 | Out << ";"; |
1341 | Out << "\n"; |
1342 | Indent(); |
1343 | Visit(I); |
1344 | } |
1345 | } |
1346 | } |
1347 | |
1348 | void DeclPrinter::VisitClassTemplateSpecializationDecl( |
1349 | ClassTemplateSpecializationDecl *D) { |
1350 | Out << "template<> "; |
1351 | VisitCXXRecordDecl(D); |
1352 | } |
1353 | |
1354 | void DeclPrinter::VisitClassTemplatePartialSpecializationDecl( |
1355 | ClassTemplatePartialSpecializationDecl *D) { |
1356 | printTemplateParameters(Params: D->getTemplateParameters()); |
1357 | VisitCXXRecordDecl(D); |
1358 | } |
1359 | |
1360 | //---------------------------------------------------------------------------- |
1361 | // Objective-C declarations |
1362 | //---------------------------------------------------------------------------- |
1363 | |
1364 | void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx, |
1365 | Decl::ObjCDeclQualifier Quals, |
1366 | QualType T) { |
1367 | Out << '('; |
1368 | if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In) |
1369 | Out << "in "; |
1370 | if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout) |
1371 | Out << "inout "; |
1372 | if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out) |
1373 | Out << "out "; |
1374 | if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy) |
1375 | Out << "bycopy "; |
1376 | if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref) |
1377 | Out << "byref "; |
1378 | if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway) |
1379 | Out << "oneway "; |
1380 | if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) { |
1381 | if (auto nullability = AttributedType::stripOuterNullability(T)) |
1382 | Out << getNullabilitySpelling(kind: *nullability, isContextSensitive: true) << ' '; |
1383 | } |
1384 | |
1385 | Out << Ctx.getUnqualifiedObjCPointerType(type: T).getAsString(Policy); |
1386 | Out << ')'; |
1387 | } |
1388 | |
1389 | void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) { |
1390 | Out << "<"; |
1391 | unsigned First = true; |
1392 | for (auto *Param : *Params) { |
1393 | if (First) { |
1394 | First = false; |
1395 | } else { |
1396 | Out << ", "; |
1397 | } |
1398 | |
1399 | switch (Param->getVariance()) { |
1400 | case ObjCTypeParamVariance::Invariant: |
1401 | break; |
1402 | |
1403 | case ObjCTypeParamVariance::Covariant: |
1404 | Out << "__covariant "; |
1405 | break; |
1406 | |
1407 | case ObjCTypeParamVariance::Contravariant: |
1408 | Out << "__contravariant "; |
1409 | break; |
1410 | } |
1411 | |
1412 | Out << Param->getDeclName(); |
1413 | |
1414 | if (Param->hasExplicitBound()) { |
1415 | Out << " : "<< Param->getUnderlyingType().getAsString(Policy); |
1416 | } |
1417 | } |
1418 | Out << ">"; |
1419 | } |
1420 | |
1421 | void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { |
1422 | if (OMD->isInstanceMethod()) |
1423 | Out << "- "; |
1424 | else |
1425 | Out << "+ "; |
1426 | if (!OMD->getReturnType().isNull()) { |
1427 | PrintObjCMethodType(Ctx&: OMD->getASTContext(), Quals: OMD->getObjCDeclQualifier(), |
1428 | T: OMD->getReturnType()); |
1429 | } |
1430 | |
1431 | std::string name = OMD->getSelector().getAsString(); |
1432 | std::string::size_type pos, lastPos = 0; |
1433 | for (const auto *PI : OMD->parameters()) { |
1434 | // FIXME: selector is missing here! |
1435 | pos = name.find_first_of(c: ':', pos: lastPos); |
1436 | if (lastPos != 0) |
1437 | Out << " "; |
1438 | Out << name.substr(pos: lastPos, n: pos - lastPos) << ':'; |
1439 | PrintObjCMethodType(Ctx&: OMD->getASTContext(), |
1440 | Quals: PI->getObjCDeclQualifier(), |
1441 | T: PI->getType()); |
1442 | Out << *PI; |
1443 | lastPos = pos + 1; |
1444 | } |
1445 | |
1446 | if (OMD->param_begin() == OMD->param_end()) |
1447 | Out << name; |
1448 | |
1449 | if (OMD->isVariadic()) |
1450 | Out << ", ..."; |
1451 | |
1452 | prettyPrintAttributes(OMD); |
1453 | |
1454 | if (OMD->getBody() && !Policy.TerseOutput) { |
1455 | Out << ' '; |
1456 | OMD->getBody()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n", |
1457 | Context: &Context); |
1458 | } |
1459 | else if (Policy.PolishForDeclaration) |
1460 | Out << ';'; |
1461 | } |
1462 | |
1463 | void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { |
1464 | std::string I = OID->getNameAsString(); |
1465 | ObjCInterfaceDecl *SID = OID->getSuperClass(); |
1466 | |
1467 | bool eolnOut = false; |
1468 | if (SID) |
1469 | Out << "@implementation "<< I << " : "<< *SID; |
1470 | else |
1471 | Out << "@implementation "<< I; |
1472 | |
1473 | if (OID->ivar_size() > 0) { |
1474 | Out << "{\n"; |
1475 | eolnOut = true; |
1476 | Indentation += Policy.Indentation; |
1477 | for (const auto *I : OID->ivars()) { |
1478 | Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). |
1479 | getAsString(Policy) << ' ' << *I << ";\n"; |
1480 | } |
1481 | Indentation -= Policy.Indentation; |
1482 | Out << "}\n"; |
1483 | } |
1484 | else if (SID || (OID->decls_begin() != OID->decls_end())) { |
1485 | Out << "\n"; |
1486 | eolnOut = true; |
1487 | } |
1488 | VisitDeclContext(OID, false); |
1489 | if (!eolnOut) |
1490 | Out << "\n"; |
1491 | Out << "@end"; |
1492 | } |
1493 | |
1494 | void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { |
1495 | std::string I = OID->getNameAsString(); |
1496 | ObjCInterfaceDecl *SID = OID->getSuperClass(); |
1497 | |
1498 | if (!OID->isThisDeclarationADefinition()) { |
1499 | Out << "@class "<< I; |
1500 | |
1501 | if (auto TypeParams = OID->getTypeParamListAsWritten()) { |
1502 | PrintObjCTypeParams(Params: TypeParams); |
1503 | } |
1504 | |
1505 | Out << ";"; |
1506 | return; |
1507 | } |
1508 | bool eolnOut = false; |
1509 | if (OID->hasAttrs()) { |
1510 | prettyPrintAttributes(OID); |
1511 | Out << "\n"; |
1512 | } |
1513 | |
1514 | Out << "@interface "<< I; |
1515 | |
1516 | if (auto TypeParams = OID->getTypeParamListAsWritten()) { |
1517 | PrintObjCTypeParams(Params: TypeParams); |
1518 | } |
1519 | |
1520 | if (SID) |
1521 | Out << " : "<< QualType(OID->getSuperClassType(), 0).getAsString(Policy); |
1522 | |
1523 | // Protocols? |
1524 | const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); |
1525 | if (!Protocols.empty()) { |
1526 | for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), |
1527 | E = Protocols.end(); I != E; ++I) |
1528 | Out << (I == Protocols.begin() ? '<' : ',') << **I; |
1529 | Out << "> "; |
1530 | } |
1531 | |
1532 | if (OID->ivar_size() > 0) { |
1533 | Out << "{\n"; |
1534 | eolnOut = true; |
1535 | Indentation += Policy.Indentation; |
1536 | for (const auto *I : OID->ivars()) { |
1537 | Indent() << I->getASTContext() |
1538 | .getUnqualifiedObjCPointerType(I->getType()) |
1539 | .getAsString(Policy) << ' ' << *I << ";\n"; |
1540 | } |
1541 | Indentation -= Policy.Indentation; |
1542 | Out << "}\n"; |
1543 | } |
1544 | else if (SID || (OID->decls_begin() != OID->decls_end())) { |
1545 | Out << "\n"; |
1546 | eolnOut = true; |
1547 | } |
1548 | |
1549 | VisitDeclContext(OID, false); |
1550 | if (!eolnOut) |
1551 | Out << "\n"; |
1552 | Out << "@end"; |
1553 | // FIXME: implement the rest... |
1554 | } |
1555 | |
1556 | void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { |
1557 | if (!PID->isThisDeclarationADefinition()) { |
1558 | Out << "@protocol "<< *PID << ";\n"; |
1559 | return; |
1560 | } |
1561 | // Protocols? |
1562 | const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols(); |
1563 | if (!Protocols.empty()) { |
1564 | Out << "@protocol "<< *PID; |
1565 | for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), |
1566 | E = Protocols.end(); I != E; ++I) |
1567 | Out << (I == Protocols.begin() ? '<' : ',') << **I; |
1568 | Out << ">\n"; |
1569 | } else |
1570 | Out << "@protocol "<< *PID << '\n'; |
1571 | VisitDeclContext(PID, false); |
1572 | Out << "@end"; |
1573 | } |
1574 | |
1575 | void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { |
1576 | Out << "@implementation "; |
1577 | if (const auto *CID = PID->getClassInterface()) |
1578 | Out << *CID; |
1579 | else |
1580 | Out << "<<error-type>>"; |
1581 | Out << '(' << *PID << ")\n"; |
1582 | |
1583 | VisitDeclContext(PID, false); |
1584 | Out << "@end"; |
1585 | // FIXME: implement the rest... |
1586 | } |
1587 | |
1588 | void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { |
1589 | Out << "@interface "; |
1590 | if (const auto *CID = PID->getClassInterface()) |
1591 | Out << *CID; |
1592 | else |
1593 | Out << "<<error-type>>"; |
1594 | if (auto TypeParams = PID->getTypeParamList()) { |
1595 | PrintObjCTypeParams(Params: TypeParams); |
1596 | } |
1597 | Out << "("<< *PID << ")\n"; |
1598 | if (PID->ivar_size() > 0) { |
1599 | Out << "{\n"; |
1600 | Indentation += Policy.Indentation; |
1601 | for (const auto *I : PID->ivars()) |
1602 | Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). |
1603 | getAsString(Policy) << ' ' << *I << ";\n"; |
1604 | Indentation -= Policy.Indentation; |
1605 | Out << "}\n"; |
1606 | } |
1607 | |
1608 | VisitDeclContext(PID, false); |
1609 | Out << "@end"; |
1610 | |
1611 | // FIXME: implement the rest... |
1612 | } |
1613 | |
1614 | void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { |
1615 | Out << "@compatibility_alias "<< *AID |
1616 | << ' ' << *AID->getClassInterface() << ";\n"; |
1617 | } |
1618 | |
1619 | /// PrintObjCPropertyDecl - print a property declaration. |
1620 | /// |
1621 | /// Print attributes in the following order: |
1622 | /// - class |
1623 | /// - nonatomic | atomic |
1624 | /// - assign | retain | strong | copy | weak | unsafe_unretained |
1625 | /// - readwrite | readonly |
1626 | /// - getter & setter |
1627 | /// - nullability |
1628 | void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { |
1629 | if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) |
1630 | Out << "@required\n"; |
1631 | else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional) |
1632 | Out << "@optional\n"; |
1633 | |
1634 | QualType T = PDecl->getType(); |
1635 | |
1636 | Out << "@property"; |
1637 | if (PDecl->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr) { |
1638 | bool first = true; |
1639 | Out << "("; |
1640 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) { |
1641 | Out << (first ? "": ", ") << "class"; |
1642 | first = false; |
1643 | } |
1644 | |
1645 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct) { |
1646 | Out << (first ? "": ", ") << "direct"; |
1647 | first = false; |
1648 | } |
1649 | |
1650 | if (PDecl->getPropertyAttributes() & |
1651 | ObjCPropertyAttribute::kind_nonatomic) { |
1652 | Out << (first ? "": ", ") << "nonatomic"; |
1653 | first = false; |
1654 | } |
1655 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) { |
1656 | Out << (first ? "": ", ") << "atomic"; |
1657 | first = false; |
1658 | } |
1659 | |
1660 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign) { |
1661 | Out << (first ? "": ", ") << "assign"; |
1662 | first = false; |
1663 | } |
1664 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain) { |
1665 | Out << (first ? "": ", ") << "retain"; |
1666 | first = false; |
1667 | } |
1668 | |
1669 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong) { |
1670 | Out << (first ? "": ", ") << "strong"; |
1671 | first = false; |
1672 | } |
1673 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) { |
1674 | Out << (first ? "": ", ") << "copy"; |
1675 | first = false; |
1676 | } |
1677 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) { |
1678 | Out << (first ? "": ", ") << "weak"; |
1679 | first = false; |
1680 | } |
1681 | if (PDecl->getPropertyAttributes() & |
1682 | ObjCPropertyAttribute::kind_unsafe_unretained) { |
1683 | Out << (first ? "": ", ") << "unsafe_unretained"; |
1684 | first = false; |
1685 | } |
1686 | |
1687 | if (PDecl->getPropertyAttributes() & |
1688 | ObjCPropertyAttribute::kind_readwrite) { |
1689 | Out << (first ? "": ", ") << "readwrite"; |
1690 | first = false; |
1691 | } |
1692 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) { |
1693 | Out << (first ? "": ", ") << "readonly"; |
1694 | first = false; |
1695 | } |
1696 | |
1697 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) { |
1698 | Out << (first ? "": ", ") << "getter = "; |
1699 | PDecl->getGetterName().print(OS&: Out); |
1700 | first = false; |
1701 | } |
1702 | if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) { |
1703 | Out << (first ? "": ", ") << "setter = "; |
1704 | PDecl->getSetterName().print(OS&: Out); |
1705 | first = false; |
1706 | } |
1707 | |
1708 | if (PDecl->getPropertyAttributes() & |
1709 | ObjCPropertyAttribute::kind_nullability) { |
1710 | if (auto nullability = AttributedType::stripOuterNullability(T)) { |
1711 | if (*nullability == NullabilityKind::Unspecified && |
1712 | (PDecl->getPropertyAttributes() & |
1713 | ObjCPropertyAttribute::kind_null_resettable)) { |
1714 | Out << (first ? "": ", ") << "null_resettable"; |
1715 | } else { |
1716 | Out << (first ? "": ", ") |
1717 | << getNullabilitySpelling(kind: *nullability, isContextSensitive: true); |
1718 | } |
1719 | first = false; |
1720 | } |
1721 | } |
1722 | |
1723 | (void) first; // Silence dead store warning due to idiomatic code. |
1724 | Out << ")"; |
1725 | } |
1726 | std::string TypeStr = PDecl->getASTContext().getUnqualifiedObjCPointerType(T). |
1727 | getAsString(Policy); |
1728 | Out << ' ' << TypeStr; |
1729 | if (!StringRef(TypeStr).ends_with(Suffix: "*")) |
1730 | Out << ' '; |
1731 | Out << *PDecl; |
1732 | if (Policy.PolishForDeclaration) |
1733 | Out << ';'; |
1734 | } |
1735 | |
1736 | void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { |
1737 | if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) |
1738 | Out << "@synthesize "; |
1739 | else |
1740 | Out << "@dynamic "; |
1741 | Out << *PID->getPropertyDecl(); |
1742 | if (PID->getPropertyIvarDecl()) |
1743 | Out << '=' << *PID->getPropertyIvarDecl(); |
1744 | } |
1745 | |
1746 | void DeclPrinter::VisitUsingDecl(UsingDecl *D) { |
1747 | if (!D->isAccessDeclaration()) |
1748 | Out << "using "; |
1749 | if (D->hasTypename()) |
1750 | Out << "typename "; |
1751 | D->getQualifier()->print(OS&: Out, Policy); |
1752 | |
1753 | // Use the correct record name when the using declaration is used for |
1754 | // inheriting constructors. |
1755 | for (const auto *Shadow : D->shadows()) { |
1756 | if (const auto *ConstructorShadow = |
1757 | dyn_cast<ConstructorUsingShadowDecl>(Shadow)) { |
1758 | assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext()); |
1759 | Out << *ConstructorShadow->getNominatedBaseClass(); |
1760 | return; |
1761 | } |
1762 | } |
1763 | Out << *D; |
1764 | } |
1765 | |
1766 | void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl *D) { |
1767 | Out << "using enum "<< D->getEnumDecl(); |
1768 | } |
1769 | |
1770 | void |
1771 | DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { |
1772 | Out << "using typename "; |
1773 | D->getQualifier()->print(OS&: Out, Policy); |
1774 | Out << D->getDeclName(); |
1775 | } |
1776 | |
1777 | void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { |
1778 | if (!D->isAccessDeclaration()) |
1779 | Out << "using "; |
1780 | D->getQualifier()->print(OS&: Out, Policy); |
1781 | Out << D->getDeclName(); |
1782 | } |
1783 | |
1784 | void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { |
1785 | // ignore |
1786 | } |
1787 | |
1788 | void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { |
1789 | Out << "#pragma omp threadprivate"; |
1790 | if (!D->varlist_empty()) { |
1791 | for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), |
1792 | E = D->varlist_end(); |
1793 | I != E; ++I) { |
1794 | Out << (I == D->varlist_begin() ? '(' : ','); |
1795 | NamedDecl *ND = cast<DeclRefExpr>(Val: *I)->getDecl(); |
1796 | ND->printQualifiedName(OS&: Out); |
1797 | } |
1798 | Out << ")"; |
1799 | } |
1800 | } |
1801 | |
1802 | void DeclPrinter::VisitHLSLBufferDecl(HLSLBufferDecl *D) { |
1803 | if (D->isCBuffer()) |
1804 | Out << "cbuffer "; |
1805 | else |
1806 | Out << "tbuffer "; |
1807 | |
1808 | Out << *D; |
1809 | |
1810 | prettyPrintAttributes(D); |
1811 | |
1812 | Out << " {\n"; |
1813 | VisitDeclContext(D); |
1814 | Indent() << "}"; |
1815 | } |
1816 | |
1817 | void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) { |
1818 | Out << "#pragma omp allocate"; |
1819 | if (!D->varlist_empty()) { |
1820 | for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(), |
1821 | E = D->varlist_end(); |
1822 | I != E; ++I) { |
1823 | Out << (I == D->varlist_begin() ? '(' : ','); |
1824 | NamedDecl *ND = cast<DeclRefExpr>(Val: *I)->getDecl(); |
1825 | ND->printQualifiedName(OS&: Out); |
1826 | } |
1827 | Out << ")"; |
1828 | } |
1829 | if (!D->clauselist_empty()) { |
1830 | OMPClausePrinter Printer(Out, Policy, Context.getLangOpts().OpenMP); |
1831 | for (OMPClause *C : D->clauselists()) { |
1832 | Out << " "; |
1833 | Printer.Visit(C); |
1834 | } |
1835 | } |
1836 | } |
1837 | |
1838 | void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { |
1839 | Out << "#pragma omp requires "; |
1840 | if (!D->clauselist_empty()) { |
1841 | OMPClausePrinter Printer(Out, Policy, Context.getLangOpts().OpenMP); |
1842 | for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I) |
1843 | Printer.Visit(*I); |
1844 | } |
1845 | } |
1846 | |
1847 | void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { |
1848 | if (!D->isInvalidDecl()) { |
1849 | Out << "#pragma omp declare reduction ("; |
1850 | if (D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) { |
1851 | const char *OpName = |
1852 | getOperatorSpelling(D->getDeclName().getCXXOverloadedOperator()); |
1853 | assert(OpName && "not an overloaded operator"); |
1854 | Out << OpName; |
1855 | } else { |
1856 | assert(D->getDeclName().isIdentifier()); |
1857 | D->printName(Out, Policy); |
1858 | } |
1859 | Out << " : "; |
1860 | D->getType().print(Out, Policy); |
1861 | Out << " : "; |
1862 | D->getCombiner()->printPretty(Out, nullptr, Policy, 0, "\n", &Context); |
1863 | Out << ")"; |
1864 | if (auto *Init = D->getInitializer()) { |
1865 | Out << " initializer("; |
1866 | switch (D->getInitializerKind()) { |
1867 | case OMPDeclareReductionInitKind::Direct: |
1868 | Out << "omp_priv("; |
1869 | break; |
1870 | case OMPDeclareReductionInitKind::Copy: |
1871 | Out << "omp_priv = "; |
1872 | break; |
1873 | case OMPDeclareReductionInitKind::Call: |
1874 | break; |
1875 | } |
1876 | Init->printPretty(Out, nullptr, Policy, 0, "\n", &Context); |
1877 | if (D->getInitializerKind() == OMPDeclareReductionInitKind::Direct) |
1878 | Out << ")"; |
1879 | Out << ")"; |
1880 | } |
1881 | } |
1882 | } |
1883 | |
1884 | void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { |
1885 | if (!D->isInvalidDecl()) { |
1886 | Out << "#pragma omp declare mapper ("; |
1887 | D->printName(Out, Policy); |
1888 | Out << " : "; |
1889 | D->getType().print(Out, Policy); |
1890 | Out << " "; |
1891 | Out << D->getVarName(); |
1892 | Out << ")"; |
1893 | if (!D->clauselist_empty()) { |
1894 | OMPClausePrinter Printer(Out, Policy, Context.getLangOpts().OpenMP); |
1895 | for (auto *C : D->clauselists()) { |
1896 | Out << " "; |
1897 | Printer.Visit(C); |
1898 | } |
1899 | } |
1900 | } |
1901 | } |
1902 | |
1903 | void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { |
1904 | D->getInit()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); |
1905 | } |
1906 | |
1907 | void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) { |
1908 | if (const TypeConstraint *TC = TTP->getTypeConstraint()) |
1909 | TC->print(OS&: Out, Policy); |
1910 | else if (TTP->wasDeclaredWithTypename()) |
1911 | Out << "typename"; |
1912 | else |
1913 | Out << "class"; |
1914 | |
1915 | if (TTP->isParameterPack()) |
1916 | Out << " ..."; |
1917 | else if (TTP->getDeclName()) |
1918 | Out << ' '; |
1919 | |
1920 | if (TTP->getDeclName()) { |
1921 | if (Policy.CleanUglifiedParameters && TTP->getIdentifier()) |
1922 | Out << TTP->getIdentifier()->deuglifiedName(); |
1923 | else |
1924 | Out << TTP->getDeclName(); |
1925 | } |
1926 | |
1927 | if (TTP->hasDefaultArgument()) { |
1928 | Out << " = "; |
1929 | TTP->getDefaultArgument().getArgument().print(Policy, Out, |
1930 | /*IncludeType=*/false); |
1931 | } |
1932 | } |
1933 | |
1934 | void DeclPrinter::VisitNonTypeTemplateParmDecl( |
1935 | const NonTypeTemplateParmDecl *NTTP) { |
1936 | StringRef Name; |
1937 | if (IdentifierInfo *II = NTTP->getIdentifier()) |
1938 | Name = |
1939 | Policy.CleanUglifiedParameters ? II->deuglifiedName() : II->getName(); |
1940 | printDeclType(T: NTTP->getType(), DeclName: Name, Pack: NTTP->isParameterPack()); |
1941 | |
1942 | if (NTTP->hasDefaultArgument()) { |
1943 | Out << " = "; |
1944 | NTTP->getDefaultArgument().getArgument().print(Policy, Out, |
1945 | /*IncludeType=*/false); |
1946 | } |
1947 | } |
1948 | |
1949 | void DeclPrinter::VisitOpenACCDeclareDecl(OpenACCDeclareDecl *D) { |
1950 | if (!D->isInvalidDecl()) { |
1951 | Out << "#pragma acc declare"; |
1952 | if (!D->clauses().empty()) { |
1953 | Out << ' '; |
1954 | OpenACCClausePrinter Printer(Out, Policy); |
1955 | Printer.VisitClauseList(List: D->clauses()); |
1956 | } |
1957 | } |
1958 | } |
1959 | void DeclPrinter::VisitOpenACCRoutineDecl(OpenACCRoutineDecl *D) { |
1960 | if (!D->isInvalidDecl()) { |
1961 | Out << "#pragma acc routine"; |
1962 | |
1963 | Out << "("; |
1964 | |
1965 | // The referenced function was named here, but this makes us tolerant of |
1966 | // errors. |
1967 | if (D->getFunctionReference()) |
1968 | D->getFunctionReference()->printPretty(Out, nullptr, Policy, Indentation, |
1969 | "\n", &Context); |
1970 | else |
1971 | Out << "<error>"; |
1972 | |
1973 | Out << ")"; |
1974 | |
1975 | if (!D->clauses().empty()) { |
1976 | Out << ' '; |
1977 | OpenACCClausePrinter Printer(Out, Policy); |
1978 | Printer.VisitClauseList(List: D->clauses()); |
1979 | } |
1980 | } |
1981 | } |
1982 |
Definitions
- DeclPrinter
- Indent
- DeclPrinter
- AttrPosAsWritten
- GetBaseType
- getDeclType
- printGroup
- dumpDeclContext
- Indent
- getPosAsWritten
- prettyPrintAttributes
- PrintOpenACCRoutineOnLambda
- prettyPrintPragmas
- printDeclType
- ProcessDeclGroup
- PrintConstructorInitializers
- VisitDeclContext
- VisitTranslationUnitDecl
- VisitTypedefDecl
- VisitTypeAliasDecl
- VisitEnumDecl
- VisitRecordDecl
- VisitEnumConstantDecl
- printExplicitSpecifier
- MaybePrintTagKeywordIfSupressingScopes
- VisitFunctionDecl
- VisitFriendDecl
- VisitFieldDecl
- VisitLabelDecl
- VisitVarDecl
- VisitParmVarDecl
- VisitFileScopeAsmDecl
- VisitTopLevelStmtDecl
- VisitImportDecl
- VisitStaticAssertDecl
- VisitNamespaceDecl
- VisitUsingDirectiveDecl
- VisitNamespaceAliasDecl
- VisitEmptyDecl
- VisitCXXRecordDecl
- VisitLinkageSpecDecl
- printTemplateParameters
- printTemplateArguments
- printTemplateArguments
- VisitTemplateDecl
- VisitFunctionTemplateDecl
- VisitClassTemplateDecl
- VisitClassTemplateSpecializationDecl
- VisitClassTemplatePartialSpecializationDecl
- PrintObjCMethodType
- PrintObjCTypeParams
- VisitObjCMethodDecl
- VisitObjCImplementationDecl
- VisitObjCInterfaceDecl
- VisitObjCProtocolDecl
- VisitObjCCategoryImplDecl
- VisitObjCCategoryDecl
- VisitObjCCompatibleAliasDecl
- VisitObjCPropertyDecl
- VisitObjCPropertyImplDecl
- VisitUsingDecl
- VisitUsingEnumDecl
- VisitUnresolvedUsingTypenameDecl
- VisitUnresolvedUsingValueDecl
- VisitUsingShadowDecl
- VisitOMPThreadPrivateDecl
- VisitHLSLBufferDecl
- VisitOMPAllocateDecl
- VisitOMPRequiresDecl
- VisitOMPDeclareReductionDecl
- VisitOMPDeclareMapperDecl
- VisitOMPCapturedExprDecl
- VisitTemplateTypeParmDecl
- VisitNonTypeTemplateParmDecl
- VisitOpenACCDeclareDecl
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more