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