File: | tools/clang/lib/AST/TypePrinter.cpp |
Warning: | line 1540, column 11 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- TypePrinter.cpp - Pretty-Print Clang Types -------------------------===// | |||
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 contains code to print types from Clang's type system. | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
13 | #include "clang/AST/PrettyPrinter.h" | |||
14 | #include "clang/AST/ASTContext.h" | |||
15 | #include "clang/AST/Decl.h" | |||
16 | #include "clang/AST/DeclBase.h" | |||
17 | #include "clang/AST/DeclCXX.h" | |||
18 | #include "clang/AST/DeclObjC.h" | |||
19 | #include "clang/AST/DeclTemplate.h" | |||
20 | #include "clang/AST/Expr.h" | |||
21 | #include "clang/AST/NestedNameSpecifier.h" | |||
22 | #include "clang/AST/TemplateBase.h" | |||
23 | #include "clang/AST/TemplateName.h" | |||
24 | #include "clang/AST/Type.h" | |||
25 | #include "clang/Basic/AddressSpaces.h" | |||
26 | #include "clang/Basic/ExceptionSpecificationType.h" | |||
27 | #include "clang/Basic/IdentifierTable.h" | |||
28 | #include "clang/Basic/LLVM.h" | |||
29 | #include "clang/Basic/LangOptions.h" | |||
30 | #include "clang/Basic/SourceLocation.h" | |||
31 | #include "clang/Basic/SourceManager.h" | |||
32 | #include "clang/Basic/Specifiers.h" | |||
33 | #include "llvm/ADT/ArrayRef.h" | |||
34 | #include "llvm/ADT/SmallString.h" | |||
35 | #include "llvm/ADT/StringRef.h" | |||
36 | #include "llvm/ADT/Twine.h" | |||
37 | #include "llvm/Support/Casting.h" | |||
38 | #include "llvm/Support/Compiler.h" | |||
39 | #include "llvm/Support/ErrorHandling.h" | |||
40 | #include "llvm/Support/SaveAndRestore.h" | |||
41 | #include "llvm/Support/raw_ostream.h" | |||
42 | #include <cassert> | |||
43 | #include <string> | |||
44 | ||||
45 | using namespace clang; | |||
46 | ||||
47 | namespace { | |||
48 | ||||
49 | /// RAII object that enables printing of the ARC __strong lifetime | |||
50 | /// qualifier. | |||
51 | class IncludeStrongLifetimeRAII { | |||
52 | PrintingPolicy &Policy; | |||
53 | bool Old; | |||
54 | ||||
55 | public: | |||
56 | explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy) | |||
57 | : Policy(Policy), Old(Policy.SuppressStrongLifetime) { | |||
58 | if (!Policy.SuppressLifetimeQualifiers) | |||
59 | Policy.SuppressStrongLifetime = false; | |||
60 | } | |||
61 | ||||
62 | ~IncludeStrongLifetimeRAII() { | |||
63 | Policy.SuppressStrongLifetime = Old; | |||
64 | } | |||
65 | }; | |||
66 | ||||
67 | class ParamPolicyRAII { | |||
68 | PrintingPolicy &Policy; | |||
69 | bool Old; | |||
70 | ||||
71 | public: | |||
72 | explicit ParamPolicyRAII(PrintingPolicy &Policy) | |||
73 | : Policy(Policy), Old(Policy.SuppressSpecifiers) { | |||
74 | Policy.SuppressSpecifiers = false; | |||
75 | } | |||
76 | ||||
77 | ~ParamPolicyRAII() { | |||
78 | Policy.SuppressSpecifiers = Old; | |||
79 | } | |||
80 | }; | |||
81 | ||||
82 | class ElaboratedTypePolicyRAII { | |||
83 | PrintingPolicy &Policy; | |||
84 | bool SuppressTagKeyword; | |||
85 | bool SuppressScope; | |||
86 | ||||
87 | public: | |||
88 | explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) { | |||
89 | SuppressTagKeyword = Policy.SuppressTagKeyword; | |||
90 | SuppressScope = Policy.SuppressScope; | |||
91 | Policy.SuppressTagKeyword = true; | |||
92 | Policy.SuppressScope = true; | |||
93 | } | |||
94 | ||||
95 | ~ElaboratedTypePolicyRAII() { | |||
96 | Policy.SuppressTagKeyword = SuppressTagKeyword; | |||
97 | Policy.SuppressScope = SuppressScope; | |||
98 | } | |||
99 | }; | |||
100 | ||||
101 | class TypePrinter { | |||
102 | PrintingPolicy Policy; | |||
103 | unsigned Indentation; | |||
104 | bool HasEmptyPlaceHolder = false; | |||
105 | bool InsideCCAttribute = false; | |||
106 | ||||
107 | public: | |||
108 | explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0) | |||
109 | : Policy(Policy), Indentation(Indentation) {} | |||
110 | ||||
111 | void print(const Type *ty, Qualifiers qs, raw_ostream &OS, | |||
112 | StringRef PlaceHolder); | |||
113 | void print(QualType T, raw_ostream &OS, StringRef PlaceHolder); | |||
114 | ||||
115 | static bool canPrefixQualifiers(const Type *T, bool &NeedARCStrongQualifier); | |||
116 | void spaceBeforePlaceHolder(raw_ostream &OS); | |||
117 | void printTypeSpec(NamedDecl *D, raw_ostream &OS); | |||
118 | ||||
119 | void printBefore(QualType T, raw_ostream &OS); | |||
120 | void printAfter(QualType T, raw_ostream &OS); | |||
121 | void AppendScope(DeclContext *DC, raw_ostream &OS); | |||
122 | void printTag(TagDecl *T, raw_ostream &OS); | |||
123 | void printFunctionAfter(const FunctionType::ExtInfo &Info, raw_ostream &OS); | |||
124 | #define ABSTRACT_TYPE(CLASS, PARENT) | |||
125 | #define TYPE(CLASS, PARENT) \ | |||
126 | void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \ | |||
127 | void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS); | |||
128 | #include "clang/AST/TypeNodes.inc" | |||
129 | ||||
130 | private: | |||
131 | void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS); | |||
132 | void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS); | |||
133 | }; | |||
134 | ||||
135 | } // namespace | |||
136 | ||||
137 | static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, | |||
138 | bool HasRestrictKeyword) { | |||
139 | bool appendSpace = false; | |||
140 | if (TypeQuals & Qualifiers::Const) { | |||
141 | OS << "const"; | |||
142 | appendSpace = true; | |||
143 | } | |||
144 | if (TypeQuals & Qualifiers::Volatile) { | |||
145 | if (appendSpace) OS << ' '; | |||
146 | OS << "volatile"; | |||
147 | appendSpace = true; | |||
148 | } | |||
149 | if (TypeQuals & Qualifiers::Restrict) { | |||
150 | if (appendSpace) OS << ' '; | |||
151 | if (HasRestrictKeyword) { | |||
152 | OS << "restrict"; | |||
153 | } else { | |||
154 | OS << "__restrict"; | |||
155 | } | |||
156 | } | |||
157 | } | |||
158 | ||||
159 | void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) { | |||
160 | if (!HasEmptyPlaceHolder) | |||
161 | OS << ' '; | |||
162 | } | |||
163 | ||||
164 | static SplitQualType splitAccordingToPolicy(QualType QT, | |||
165 | const PrintingPolicy &Policy) { | |||
166 | if (Policy.PrintCanonicalTypes) | |||
167 | QT = QT.getCanonicalType(); | |||
168 | return QT.split(); | |||
169 | } | |||
170 | ||||
171 | void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) { | |||
172 | SplitQualType split = splitAccordingToPolicy(t, Policy); | |||
173 | print(split.Ty, split.Quals, OS, PlaceHolder); | |||
174 | } | |||
175 | ||||
176 | void TypePrinter::print(const Type *T, Qualifiers Quals, raw_ostream &OS, | |||
177 | StringRef PlaceHolder) { | |||
178 | if (!T) { | |||
179 | OS << "NULL TYPE"; | |||
180 | return; | |||
181 | } | |||
182 | ||||
183 | SaveAndRestore<bool> PHVal(HasEmptyPlaceHolder, PlaceHolder.empty()); | |||
184 | ||||
185 | printBefore(T, Quals, OS); | |||
186 | OS << PlaceHolder; | |||
187 | printAfter(T, Quals, OS); | |||
188 | } | |||
189 | ||||
190 | bool TypePrinter::canPrefixQualifiers(const Type *T, | |||
191 | bool &NeedARCStrongQualifier) { | |||
192 | // CanPrefixQualifiers - We prefer to print type qualifiers before the type, | |||
193 | // so that we get "const int" instead of "int const", but we can't do this if | |||
194 | // the type is complex. For example if the type is "int*", we *must* print | |||
195 | // "int * const", printing "const int *" is different. Only do this when the | |||
196 | // type expands to a simple string. | |||
197 | bool CanPrefixQualifiers = false; | |||
198 | NeedARCStrongQualifier = false; | |||
199 | Type::TypeClass TC = T->getTypeClass(); | |||
200 | if (const auto *AT = dyn_cast<AutoType>(T)) | |||
201 | TC = AT->desugar()->getTypeClass(); | |||
202 | if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) | |||
203 | TC = Subst->getReplacementType()->getTypeClass(); | |||
204 | ||||
205 | switch (TC) { | |||
206 | case Type::Auto: | |||
207 | case Type::Builtin: | |||
208 | case Type::Complex: | |||
209 | case Type::UnresolvedUsing: | |||
210 | case Type::Typedef: | |||
211 | case Type::TypeOfExpr: | |||
212 | case Type::TypeOf: | |||
213 | case Type::Decltype: | |||
214 | case Type::UnaryTransform: | |||
215 | case Type::Record: | |||
216 | case Type::Enum: | |||
217 | case Type::Elaborated: | |||
218 | case Type::TemplateTypeParm: | |||
219 | case Type::SubstTemplateTypeParmPack: | |||
220 | case Type::DeducedTemplateSpecialization: | |||
221 | case Type::TemplateSpecialization: | |||
222 | case Type::InjectedClassName: | |||
223 | case Type::DependentName: | |||
224 | case Type::DependentTemplateSpecialization: | |||
225 | case Type::ObjCObject: | |||
226 | case Type::ObjCTypeParam: | |||
227 | case Type::ObjCInterface: | |||
228 | case Type::Atomic: | |||
229 | case Type::Pipe: | |||
230 | CanPrefixQualifiers = true; | |||
231 | break; | |||
232 | ||||
233 | case Type::ObjCObjectPointer: | |||
234 | CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() || | |||
235 | T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType(); | |||
236 | break; | |||
237 | ||||
238 | case Type::ConstantArray: | |||
239 | case Type::IncompleteArray: | |||
240 | case Type::VariableArray: | |||
241 | case Type::DependentSizedArray: | |||
242 | NeedARCStrongQualifier = true; | |||
243 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | |||
244 | ||||
245 | case Type::Adjusted: | |||
246 | case Type::Decayed: | |||
247 | case Type::Pointer: | |||
248 | case Type::BlockPointer: | |||
249 | case Type::LValueReference: | |||
250 | case Type::RValueReference: | |||
251 | case Type::MemberPointer: | |||
252 | case Type::DependentAddressSpace: | |||
253 | case Type::DependentVector: | |||
254 | case Type::DependentSizedExtVector: | |||
255 | case Type::Vector: | |||
256 | case Type::ExtVector: | |||
257 | case Type::FunctionProto: | |||
258 | case Type::FunctionNoProto: | |||
259 | case Type::Paren: | |||
260 | case Type::PackExpansion: | |||
261 | case Type::SubstTemplateTypeParm: | |||
262 | case Type::MacroQualified: | |||
263 | CanPrefixQualifiers = false; | |||
264 | break; | |||
265 | ||||
266 | case Type::Attributed: { | |||
267 | // We still want to print the address_space before the type if it is an | |||
268 | // address_space attribute. | |||
269 | const auto *AttrTy = cast<AttributedType>(T); | |||
270 | CanPrefixQualifiers = AttrTy->getAttrKind() == attr::AddressSpace; | |||
271 | } | |||
272 | } | |||
273 | ||||
274 | return CanPrefixQualifiers; | |||
275 | } | |||
276 | ||||
277 | void TypePrinter::printBefore(QualType T, raw_ostream &OS) { | |||
278 | SplitQualType Split = splitAccordingToPolicy(T, Policy); | |||
279 | ||||
280 | // If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2 | |||
281 | // at this level. | |||
282 | Qualifiers Quals = Split.Quals; | |||
283 | if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(Split.Ty)) | |||
284 | Quals -= QualType(Subst, 0).getQualifiers(); | |||
285 | ||||
286 | printBefore(Split.Ty, Quals, OS); | |||
287 | } | |||
288 | ||||
289 | /// Prints the part of the type string before an identifier, e.g. for | |||
290 | /// "int foo[10]" it prints "int ". | |||
291 | void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) { | |||
292 | if (Policy.SuppressSpecifiers && T->isSpecifierType()) | |||
293 | return; | |||
294 | ||||
295 | SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder); | |||
296 | ||||
297 | // Print qualifiers as appropriate. | |||
298 | ||||
299 | bool CanPrefixQualifiers = false; | |||
300 | bool NeedARCStrongQualifier = false; | |||
301 | CanPrefixQualifiers = canPrefixQualifiers(T, NeedARCStrongQualifier); | |||
302 | ||||
303 | if (CanPrefixQualifiers && !Quals.empty()) { | |||
304 | if (NeedARCStrongQualifier) { | |||
305 | IncludeStrongLifetimeRAII Strong(Policy); | |||
306 | Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true); | |||
307 | } else { | |||
308 | Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true); | |||
309 | } | |||
310 | } | |||
311 | ||||
312 | bool hasAfterQuals = false; | |||
313 | if (!CanPrefixQualifiers && !Quals.empty()) { | |||
314 | hasAfterQuals = !Quals.isEmptyWhenPrinted(Policy); | |||
315 | if (hasAfterQuals) | |||
316 | HasEmptyPlaceHolder = false; | |||
317 | } | |||
318 | ||||
319 | switch (T->getTypeClass()) { | |||
320 | #define ABSTRACT_TYPE(CLASS, PARENT) | |||
321 | #define TYPE(CLASS, PARENT) case Type::CLASS: \ | |||
322 | print##CLASS##Before(cast<CLASS##Type>(T), OS); \ | |||
323 | break; | |||
324 | #include "clang/AST/TypeNodes.inc" | |||
325 | } | |||
326 | ||||
327 | if (hasAfterQuals) { | |||
328 | if (NeedARCStrongQualifier) { | |||
329 | IncludeStrongLifetimeRAII Strong(Policy); | |||
330 | Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get()); | |||
331 | } else { | |||
332 | Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get()); | |||
333 | } | |||
334 | } | |||
335 | } | |||
336 | ||||
337 | void TypePrinter::printAfter(QualType t, raw_ostream &OS) { | |||
338 | SplitQualType split = splitAccordingToPolicy(t, Policy); | |||
339 | printAfter(split.Ty, split.Quals, OS); | |||
340 | } | |||
341 | ||||
342 | /// Prints the part of the type string after an identifier, e.g. for | |||
343 | /// "int foo[10]" it prints "[10]". | |||
344 | void TypePrinter::printAfter(const Type *T, Qualifiers Quals, raw_ostream &OS) { | |||
345 | switch (T->getTypeClass()) { | |||
346 | #define ABSTRACT_TYPE(CLASS, PARENT) | |||
347 | #define TYPE(CLASS, PARENT) case Type::CLASS: \ | |||
348 | print##CLASS##After(cast<CLASS##Type>(T), OS); \ | |||
349 | break; | |||
350 | #include "clang/AST/TypeNodes.inc" | |||
351 | } | |||
352 | } | |||
353 | ||||
354 | void TypePrinter::printBuiltinBefore(const BuiltinType *T, raw_ostream &OS) { | |||
355 | OS << T->getName(Policy); | |||
356 | spaceBeforePlaceHolder(OS); | |||
357 | } | |||
358 | ||||
359 | void TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) {} | |||
360 | ||||
361 | void TypePrinter::printComplexBefore(const ComplexType *T, raw_ostream &OS) { | |||
362 | OS << "_Complex "; | |||
363 | printBefore(T->getElementType(), OS); | |||
364 | } | |||
365 | ||||
366 | void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) { | |||
367 | printAfter(T->getElementType(), OS); | |||
368 | } | |||
369 | ||||
370 | void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) { | |||
371 | IncludeStrongLifetimeRAII Strong(Policy); | |||
372 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
373 | printBefore(T->getPointeeType(), OS); | |||
374 | // Handle things like 'int (*A)[4];' correctly. | |||
375 | // FIXME: this should include vectors, but vectors use attributes I guess. | |||
376 | if (isa<ArrayType>(T->getPointeeType())) | |||
377 | OS << '('; | |||
378 | OS << '*'; | |||
379 | } | |||
380 | ||||
381 | void TypePrinter::printPointerAfter(const PointerType *T, raw_ostream &OS) { | |||
382 | IncludeStrongLifetimeRAII Strong(Policy); | |||
383 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
384 | // Handle things like 'int (*A)[4];' correctly. | |||
385 | // FIXME: this should include vectors, but vectors use attributes I guess. | |||
386 | if (isa<ArrayType>(T->getPointeeType())) | |||
387 | OS << ')'; | |||
388 | printAfter(T->getPointeeType(), OS); | |||
389 | } | |||
390 | ||||
391 | void TypePrinter::printBlockPointerBefore(const BlockPointerType *T, | |||
392 | raw_ostream &OS) { | |||
393 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
394 | printBefore(T->getPointeeType(), OS); | |||
395 | OS << '^'; | |||
396 | } | |||
397 | ||||
398 | void TypePrinter::printBlockPointerAfter(const BlockPointerType *T, | |||
399 | raw_ostream &OS) { | |||
400 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
401 | printAfter(T->getPointeeType(), OS); | |||
402 | } | |||
403 | ||||
404 | // When printing a reference, the referenced type might also be a reference. | |||
405 | // If so, we want to skip that before printing the inner type. | |||
406 | static QualType skipTopLevelReferences(QualType T) { | |||
407 | if (auto *Ref = T->getAs<ReferenceType>()) | |||
408 | return skipTopLevelReferences(Ref->getPointeeTypeAsWritten()); | |||
409 | return T; | |||
410 | } | |||
411 | ||||
412 | void TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T, | |||
413 | raw_ostream &OS) { | |||
414 | IncludeStrongLifetimeRAII Strong(Policy); | |||
415 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
416 | QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten()); | |||
417 | printBefore(Inner, OS); | |||
418 | // Handle things like 'int (&A)[4];' correctly. | |||
419 | // FIXME: this should include vectors, but vectors use attributes I guess. | |||
420 | if (isa<ArrayType>(Inner)) | |||
421 | OS << '('; | |||
422 | OS << '&'; | |||
423 | } | |||
424 | ||||
425 | void TypePrinter::printLValueReferenceAfter(const LValueReferenceType *T, | |||
426 | raw_ostream &OS) { | |||
427 | IncludeStrongLifetimeRAII Strong(Policy); | |||
428 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
429 | QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten()); | |||
430 | // Handle things like 'int (&A)[4];' correctly. | |||
431 | // FIXME: this should include vectors, but vectors use attributes I guess. | |||
432 | if (isa<ArrayType>(Inner)) | |||
433 | OS << ')'; | |||
434 | printAfter(Inner, OS); | |||
435 | } | |||
436 | ||||
437 | void TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T, | |||
438 | raw_ostream &OS) { | |||
439 | IncludeStrongLifetimeRAII Strong(Policy); | |||
440 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
441 | QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten()); | |||
442 | printBefore(Inner, OS); | |||
443 | // Handle things like 'int (&&A)[4];' correctly. | |||
444 | // FIXME: this should include vectors, but vectors use attributes I guess. | |||
445 | if (isa<ArrayType>(Inner)) | |||
446 | OS << '('; | |||
447 | OS << "&&"; | |||
448 | } | |||
449 | ||||
450 | void TypePrinter::printRValueReferenceAfter(const RValueReferenceType *T, | |||
451 | raw_ostream &OS) { | |||
452 | IncludeStrongLifetimeRAII Strong(Policy); | |||
453 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
454 | QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten()); | |||
455 | // Handle things like 'int (&&A)[4];' correctly. | |||
456 | // FIXME: this should include vectors, but vectors use attributes I guess. | |||
457 | if (isa<ArrayType>(Inner)) | |||
458 | OS << ')'; | |||
459 | printAfter(Inner, OS); | |||
460 | } | |||
461 | ||||
462 | void TypePrinter::printMemberPointerBefore(const MemberPointerType *T, | |||
463 | raw_ostream &OS) { | |||
464 | IncludeStrongLifetimeRAII Strong(Policy); | |||
465 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
466 | printBefore(T->getPointeeType(), OS); | |||
467 | // Handle things like 'int (Cls::*A)[4];' correctly. | |||
468 | // FIXME: this should include vectors, but vectors use attributes I guess. | |||
469 | if (isa<ArrayType>(T->getPointeeType())) | |||
470 | OS << '('; | |||
471 | ||||
472 | PrintingPolicy InnerPolicy(Policy); | |||
473 | InnerPolicy.IncludeTagDefinition = false; | |||
474 | TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef()); | |||
475 | ||||
476 | OS << "::*"; | |||
477 | } | |||
478 | ||||
479 | void TypePrinter::printMemberPointerAfter(const MemberPointerType *T, | |||
480 | raw_ostream &OS) { | |||
481 | IncludeStrongLifetimeRAII Strong(Policy); | |||
482 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
483 | // Handle things like 'int (Cls::*A)[4];' correctly. | |||
484 | // FIXME: this should include vectors, but vectors use attributes I guess. | |||
485 | if (isa<ArrayType>(T->getPointeeType())) | |||
486 | OS << ')'; | |||
487 | printAfter(T->getPointeeType(), OS); | |||
488 | } | |||
489 | ||||
490 | void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T, | |||
491 | raw_ostream &OS) { | |||
492 | IncludeStrongLifetimeRAII Strong(Policy); | |||
493 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
494 | printBefore(T->getElementType(), OS); | |||
495 | } | |||
496 | ||||
497 | void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T, | |||
498 | raw_ostream &OS) { | |||
499 | OS << '['; | |||
500 | if (T->getIndexTypeQualifiers().hasQualifiers()) { | |||
501 | AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), | |||
502 | Policy.Restrict); | |||
503 | OS << ' '; | |||
504 | } | |||
505 | ||||
506 | if (T->getSizeModifier() == ArrayType::Static) | |||
507 | OS << "static "; | |||
508 | ||||
509 | OS << T->getSize().getZExtValue() << ']'; | |||
510 | printAfter(T->getElementType(), OS); | |||
511 | } | |||
512 | ||||
513 | void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T, | |||
514 | raw_ostream &OS) { | |||
515 | IncludeStrongLifetimeRAII Strong(Policy); | |||
516 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
517 | printBefore(T->getElementType(), OS); | |||
518 | } | |||
519 | ||||
520 | void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T, | |||
521 | raw_ostream &OS) { | |||
522 | OS << "[]"; | |||
523 | printAfter(T->getElementType(), OS); | |||
524 | } | |||
525 | ||||
526 | void TypePrinter::printVariableArrayBefore(const VariableArrayType *T, | |||
527 | raw_ostream &OS) { | |||
528 | IncludeStrongLifetimeRAII Strong(Policy); | |||
529 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
530 | printBefore(T->getElementType(), OS); | |||
531 | } | |||
532 | ||||
533 | void TypePrinter::printVariableArrayAfter(const VariableArrayType *T, | |||
534 | raw_ostream &OS) { | |||
535 | OS << '['; | |||
536 | if (T->getIndexTypeQualifiers().hasQualifiers()) { | |||
537 | AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.Restrict); | |||
538 | OS << ' '; | |||
539 | } | |||
540 | ||||
541 | if (T->getSizeModifier() == VariableArrayType::Static) | |||
542 | OS << "static "; | |||
543 | else if (T->getSizeModifier() == VariableArrayType::Star) | |||
544 | OS << '*'; | |||
545 | ||||
546 | if (T->getSizeExpr()) | |||
547 | T->getSizeExpr()->printPretty(OS, nullptr, Policy); | |||
548 | OS << ']'; | |||
549 | ||||
550 | printAfter(T->getElementType(), OS); | |||
551 | } | |||
552 | ||||
553 | void TypePrinter::printAdjustedBefore(const AdjustedType *T, raw_ostream &OS) { | |||
554 | // Print the adjusted representation, otherwise the adjustment will be | |||
555 | // invisible. | |||
556 | printBefore(T->getAdjustedType(), OS); | |||
557 | } | |||
558 | ||||
559 | void TypePrinter::printAdjustedAfter(const AdjustedType *T, raw_ostream &OS) { | |||
560 | printAfter(T->getAdjustedType(), OS); | |||
561 | } | |||
562 | ||||
563 | void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) { | |||
564 | // Print as though it's a pointer. | |||
565 | printAdjustedBefore(T, OS); | |||
566 | } | |||
567 | ||||
568 | void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) { | |||
569 | printAdjustedAfter(T, OS); | |||
570 | } | |||
571 | ||||
572 | void TypePrinter::printDependentSizedArrayBefore( | |||
573 | const DependentSizedArrayType *T, | |||
574 | raw_ostream &OS) { | |||
575 | IncludeStrongLifetimeRAII Strong(Policy); | |||
576 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
577 | printBefore(T->getElementType(), OS); | |||
578 | } | |||
579 | ||||
580 | void TypePrinter::printDependentSizedArrayAfter( | |||
581 | const DependentSizedArrayType *T, | |||
582 | raw_ostream &OS) { | |||
583 | OS << '['; | |||
584 | if (T->getSizeExpr()) | |||
585 | T->getSizeExpr()->printPretty(OS, nullptr, Policy); | |||
586 | OS << ']'; | |||
587 | printAfter(T->getElementType(), OS); | |||
588 | } | |||
589 | ||||
590 | void TypePrinter::printDependentAddressSpaceBefore( | |||
591 | const DependentAddressSpaceType *T, raw_ostream &OS) { | |||
592 | printBefore(T->getPointeeType(), OS); | |||
593 | } | |||
594 | ||||
595 | void TypePrinter::printDependentAddressSpaceAfter( | |||
596 | const DependentAddressSpaceType *T, raw_ostream &OS) { | |||
597 | OS << " __attribute__((address_space("; | |||
598 | if (T->getAddrSpaceExpr()) | |||
599 | T->getAddrSpaceExpr()->printPretty(OS, nullptr, Policy); | |||
600 | OS << ")))"; | |||
601 | printAfter(T->getPointeeType(), OS); | |||
602 | } | |||
603 | ||||
604 | void TypePrinter::printDependentSizedExtVectorBefore( | |||
605 | const DependentSizedExtVectorType *T, | |||
606 | raw_ostream &OS) { | |||
607 | printBefore(T->getElementType(), OS); | |||
608 | } | |||
609 | ||||
610 | void TypePrinter::printDependentSizedExtVectorAfter( | |||
611 | const DependentSizedExtVectorType *T, | |||
612 | raw_ostream &OS) { | |||
613 | OS << " __attribute__((ext_vector_type("; | |||
614 | if (T->getSizeExpr()) | |||
615 | T->getSizeExpr()->printPretty(OS, nullptr, Policy); | |||
616 | OS << ")))"; | |||
617 | printAfter(T->getElementType(), OS); | |||
618 | } | |||
619 | ||||
620 | void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) { | |||
621 | switch (T->getVectorKind()) { | |||
622 | case VectorType::AltiVecPixel: | |||
623 | OS << "__vector __pixel "; | |||
624 | break; | |||
625 | case VectorType::AltiVecBool: | |||
626 | OS << "__vector __bool "; | |||
627 | printBefore(T->getElementType(), OS); | |||
628 | break; | |||
629 | case VectorType::AltiVecVector: | |||
630 | OS << "__vector "; | |||
631 | printBefore(T->getElementType(), OS); | |||
632 | break; | |||
633 | case VectorType::NeonVector: | |||
634 | OS << "__attribute__((neon_vector_type(" | |||
635 | << T->getNumElements() << "))) "; | |||
636 | printBefore(T->getElementType(), OS); | |||
637 | break; | |||
638 | case VectorType::NeonPolyVector: | |||
639 | OS << "__attribute__((neon_polyvector_type(" << | |||
640 | T->getNumElements() << "))) "; | |||
641 | printBefore(T->getElementType(), OS); | |||
642 | break; | |||
643 | case VectorType::GenericVector: { | |||
644 | // FIXME: We prefer to print the size directly here, but have no way | |||
645 | // to get the size of the type. | |||
646 | OS << "__attribute__((__vector_size__(" | |||
647 | << T->getNumElements() | |||
648 | << " * sizeof("; | |||
649 | print(T->getElementType(), OS, StringRef()); | |||
650 | OS << ")))) "; | |||
651 | printBefore(T->getElementType(), OS); | |||
652 | break; | |||
653 | } | |||
654 | } | |||
655 | } | |||
656 | ||||
657 | void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) { | |||
658 | printAfter(T->getElementType(), OS); | |||
659 | } | |||
660 | ||||
661 | void TypePrinter::printDependentVectorBefore( | |||
662 | const DependentVectorType *T, raw_ostream &OS) { | |||
663 | switch (T->getVectorKind()) { | |||
664 | case VectorType::AltiVecPixel: | |||
665 | OS << "__vector __pixel "; | |||
666 | break; | |||
667 | case VectorType::AltiVecBool: | |||
668 | OS << "__vector __bool "; | |||
669 | printBefore(T->getElementType(), OS); | |||
670 | break; | |||
671 | case VectorType::AltiVecVector: | |||
672 | OS << "__vector "; | |||
673 | printBefore(T->getElementType(), OS); | |||
674 | break; | |||
675 | case VectorType::NeonVector: | |||
676 | OS << "__attribute__((neon_vector_type("; | |||
677 | if (T->getSizeExpr()) | |||
678 | T->getSizeExpr()->printPretty(OS, nullptr, Policy); | |||
679 | OS << "))) "; | |||
680 | printBefore(T->getElementType(), OS); | |||
681 | break; | |||
682 | case VectorType::NeonPolyVector: | |||
683 | OS << "__attribute__((neon_polyvector_type("; | |||
684 | if (T->getSizeExpr()) | |||
685 | T->getSizeExpr()->printPretty(OS, nullptr, Policy); | |||
686 | OS << "))) "; | |||
687 | printBefore(T->getElementType(), OS); | |||
688 | break; | |||
689 | case VectorType::GenericVector: { | |||
690 | // FIXME: We prefer to print the size directly here, but have no way | |||
691 | // to get the size of the type. | |||
692 | OS << "__attribute__((__vector_size__("; | |||
693 | if (T->getSizeExpr()) | |||
694 | T->getSizeExpr()->printPretty(OS, nullptr, Policy); | |||
695 | OS << " * sizeof("; | |||
696 | print(T->getElementType(), OS, StringRef()); | |||
697 | OS << ")))) "; | |||
698 | printBefore(T->getElementType(), OS); | |||
699 | break; | |||
700 | } | |||
701 | } | |||
702 | } | |||
703 | ||||
704 | void TypePrinter::printDependentVectorAfter( | |||
705 | const DependentVectorType *T, raw_ostream &OS) { | |||
706 | printAfter(T->getElementType(), OS); | |||
707 | } | |||
708 | ||||
709 | void TypePrinter::printExtVectorBefore(const ExtVectorType *T, | |||
710 | raw_ostream &OS) { | |||
711 | printBefore(T->getElementType(), OS); | |||
712 | } | |||
713 | ||||
714 | void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) { | |||
715 | printAfter(T->getElementType(), OS); | |||
716 | OS << " __attribute__((ext_vector_type("; | |||
717 | OS << T->getNumElements(); | |||
718 | OS << ")))"; | |||
719 | } | |||
720 | ||||
721 | void | |||
722 | FunctionProtoType::printExceptionSpecification(raw_ostream &OS, | |||
723 | const PrintingPolicy &Policy) | |||
724 | const { | |||
725 | if (hasDynamicExceptionSpec()) { | |||
726 | OS << " throw("; | |||
727 | if (getExceptionSpecType() == EST_MSAny) | |||
728 | OS << "..."; | |||
729 | else | |||
730 | for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) { | |||
731 | if (I) | |||
732 | OS << ", "; | |||
733 | ||||
734 | OS << getExceptionType(I).stream(Policy); | |||
735 | } | |||
736 | OS << ')'; | |||
737 | } else if (EST_NoThrow == getExceptionSpecType()) { | |||
738 | OS << " __attribute__((nothrow))"; | |||
739 | } else if (isNoexceptExceptionSpec(getExceptionSpecType())) { | |||
740 | OS << " noexcept"; | |||
741 | // FIXME:Is it useful to print out the expression for a non-dependent | |||
742 | // noexcept specification? | |||
743 | if (isComputedNoexcept(getExceptionSpecType())) { | |||
744 | OS << '('; | |||
745 | if (getNoexceptExpr()) | |||
746 | getNoexceptExpr()->printPretty(OS, nullptr, Policy); | |||
747 | OS << ')'; | |||
748 | } | |||
749 | } | |||
750 | } | |||
751 | ||||
752 | void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T, | |||
753 | raw_ostream &OS) { | |||
754 | if (T->hasTrailingReturn()) { | |||
755 | OS << "auto "; | |||
756 | if (!HasEmptyPlaceHolder) | |||
757 | OS << '('; | |||
758 | } else { | |||
759 | // If needed for precedence reasons, wrap the inner part in grouping parens. | |||
760 | SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false); | |||
761 | printBefore(T->getReturnType(), OS); | |||
762 | if (!PrevPHIsEmpty.get()) | |||
763 | OS << '('; | |||
764 | } | |||
765 | } | |||
766 | ||||
767 | StringRef clang::getParameterABISpelling(ParameterABI ABI) { | |||
768 | switch (ABI) { | |||
769 | case ParameterABI::Ordinary: | |||
770 | llvm_unreachable("asking for spelling of ordinary parameter ABI")::llvm::llvm_unreachable_internal("asking for spelling of ordinary parameter ABI" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/TypePrinter.cpp" , 770); | |||
771 | case ParameterABI::SwiftContext: | |||
772 | return "swift_context"; | |||
773 | case ParameterABI::SwiftErrorResult: | |||
774 | return "swift_error_result"; | |||
775 | case ParameterABI::SwiftIndirectResult: | |||
776 | return "swift_indirect_result"; | |||
777 | } | |||
778 | llvm_unreachable("bad parameter ABI kind")::llvm::llvm_unreachable_internal("bad parameter ABI kind", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/TypePrinter.cpp" , 778); | |||
779 | } | |||
780 | ||||
781 | void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, | |||
782 | raw_ostream &OS) { | |||
783 | // If needed for precedence reasons, wrap the inner part in grouping parens. | |||
784 | if (!HasEmptyPlaceHolder) | |||
785 | OS << ')'; | |||
786 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
787 | ||||
788 | OS << '('; | |||
789 | { | |||
790 | ParamPolicyRAII ParamPolicy(Policy); | |||
791 | for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) { | |||
792 | if (i) OS << ", "; | |||
793 | ||||
794 | auto EPI = T->getExtParameterInfo(i); | |||
795 | if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) "; | |||
796 | if (EPI.isNoEscape()) | |||
797 | OS << "__attribute__((noescape)) "; | |||
798 | auto ABI = EPI.getABI(); | |||
799 | if (ABI != ParameterABI::Ordinary) | |||
800 | OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) "; | |||
801 | ||||
802 | print(T->getParamType(i), OS, StringRef()); | |||
803 | } | |||
804 | } | |||
805 | ||||
806 | if (T->isVariadic()) { | |||
807 | if (T->getNumParams()) | |||
808 | OS << ", "; | |||
809 | OS << "..."; | |||
810 | } else if (T->getNumParams() == 0 && Policy.UseVoidForZeroParams) { | |||
811 | // Do not emit int() if we have a proto, emit 'int(void)'. | |||
812 | OS << "void"; | |||
813 | } | |||
814 | ||||
815 | OS << ')'; | |||
816 | ||||
817 | FunctionType::ExtInfo Info = T->getExtInfo(); | |||
818 | ||||
819 | printFunctionAfter(Info, OS); | |||
820 | ||||
821 | if (!T->getMethodQuals().empty()) | |||
822 | OS << " " << T->getMethodQuals().getAsString(); | |||
823 | ||||
824 | switch (T->getRefQualifier()) { | |||
825 | case RQ_None: | |||
826 | break; | |||
827 | ||||
828 | case RQ_LValue: | |||
829 | OS << " &"; | |||
830 | break; | |||
831 | ||||
832 | case RQ_RValue: | |||
833 | OS << " &&"; | |||
834 | break; | |||
835 | } | |||
836 | T->printExceptionSpecification(OS, Policy); | |||
837 | ||||
838 | if (T->hasTrailingReturn()) { | |||
839 | OS << " -> "; | |||
840 | print(T->getReturnType(), OS, StringRef()); | |||
841 | } else | |||
842 | printAfter(T->getReturnType(), OS); | |||
843 | } | |||
844 | ||||
845 | void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, | |||
846 | raw_ostream &OS) { | |||
847 | if (!InsideCCAttribute) { | |||
848 | switch (Info.getCC()) { | |||
849 | case CC_C: | |||
850 | // The C calling convention is the default on the vast majority of platforms | |||
851 | // we support. If the user wrote it explicitly, it will usually be printed | |||
852 | // while traversing the AttributedType. If the type has been desugared, let | |||
853 | // the canonical spelling be the implicit calling convention. | |||
854 | // FIXME: It would be better to be explicit in certain contexts, such as a | |||
855 | // cdecl function typedef used to declare a member function with the | |||
856 | // Microsoft C++ ABI. | |||
857 | break; | |||
858 | case CC_X86StdCall: | |||
859 | OS << " __attribute__((stdcall))"; | |||
860 | break; | |||
861 | case CC_X86FastCall: | |||
862 | OS << " __attribute__((fastcall))"; | |||
863 | break; | |||
864 | case CC_X86ThisCall: | |||
865 | OS << " __attribute__((thiscall))"; | |||
866 | break; | |||
867 | case CC_X86VectorCall: | |||
868 | OS << " __attribute__((vectorcall))"; | |||
869 | break; | |||
870 | case CC_X86Pascal: | |||
871 | OS << " __attribute__((pascal))"; | |||
872 | break; | |||
873 | case CC_AAPCS: | |||
874 | OS << " __attribute__((pcs(\"aapcs\")))"; | |||
875 | break; | |||
876 | case CC_AAPCS_VFP: | |||
877 | OS << " __attribute__((pcs(\"aapcs-vfp\")))"; | |||
878 | break; | |||
879 | case CC_AArch64VectorCall: | |||
880 | OS << "__attribute__((aarch64_vector_pcs))"; | |||
881 | break; | |||
882 | case CC_IntelOclBicc: | |||
883 | OS << " __attribute__((intel_ocl_bicc))"; | |||
884 | break; | |||
885 | case CC_Win64: | |||
886 | OS << " __attribute__((ms_abi))"; | |||
887 | break; | |||
888 | case CC_X86_64SysV: | |||
889 | OS << " __attribute__((sysv_abi))"; | |||
890 | break; | |||
891 | case CC_X86RegCall: | |||
892 | OS << " __attribute__((regcall))"; | |||
893 | break; | |||
894 | case CC_SpirFunction: | |||
895 | case CC_OpenCLKernel: | |||
896 | // Do nothing. These CCs are not available as attributes. | |||
897 | break; | |||
898 | case CC_Swift: | |||
899 | OS << " __attribute__((swiftcall))"; | |||
900 | break; | |||
901 | case CC_PreserveMost: | |||
902 | OS << " __attribute__((preserve_most))"; | |||
903 | break; | |||
904 | case CC_PreserveAll: | |||
905 | OS << " __attribute__((preserve_all))"; | |||
906 | break; | |||
907 | } | |||
908 | } | |||
909 | ||||
910 | if (Info.getNoReturn()) | |||
911 | OS << " __attribute__((noreturn))"; | |||
912 | if (Info.getProducesResult()) | |||
913 | OS << " __attribute__((ns_returns_retained))"; | |||
914 | if (Info.getRegParm()) | |||
915 | OS << " __attribute__((regparm (" | |||
916 | << Info.getRegParm() << ")))"; | |||
917 | if (Info.getNoCallerSavedRegs()) | |||
918 | OS << " __attribute__((no_caller_saved_registers))"; | |||
919 | if (Info.getNoCfCheck()) | |||
920 | OS << " __attribute__((nocf_check))"; | |||
921 | } | |||
922 | ||||
923 | void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T, | |||
924 | raw_ostream &OS) { | |||
925 | // If needed for precedence reasons, wrap the inner part in grouping parens. | |||
926 | SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false); | |||
927 | printBefore(T->getReturnType(), OS); | |||
928 | if (!PrevPHIsEmpty.get()) | |||
929 | OS << '('; | |||
930 | } | |||
931 | ||||
932 | void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T, | |||
933 | raw_ostream &OS) { | |||
934 | // If needed for precedence reasons, wrap the inner part in grouping parens. | |||
935 | if (!HasEmptyPlaceHolder) | |||
936 | OS << ')'; | |||
937 | SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); | |||
938 | ||||
939 | OS << "()"; | |||
940 | printFunctionAfter(T->getExtInfo(), OS); | |||
941 | printAfter(T->getReturnType(), OS); | |||
942 | } | |||
943 | ||||
944 | void TypePrinter::printTypeSpec(NamedDecl *D, raw_ostream &OS) { | |||
945 | ||||
946 | // Compute the full nested-name-specifier for this type. | |||
947 | // In C, this will always be empty except when the type | |||
948 | // being printed is anonymous within other Record. | |||
949 | if (!Policy.SuppressScope) | |||
950 | AppendScope(D->getDeclContext(), OS); | |||
951 | ||||
952 | IdentifierInfo *II = D->getIdentifier(); | |||
953 | OS << II->getName(); | |||
954 | spaceBeforePlaceHolder(OS); | |||
955 | } | |||
956 | ||||
957 | void TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T, | |||
958 | raw_ostream &OS) { | |||
959 | printTypeSpec(T->getDecl(), OS); | |||
960 | } | |||
961 | ||||
962 | void TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T, | |||
963 | raw_ostream &OS) {} | |||
964 | ||||
965 | void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) { | |||
966 | printTypeSpec(T->getDecl(), OS); | |||
967 | } | |||
968 | ||||
969 | void TypePrinter::printMacroQualifiedBefore(const MacroQualifiedType *T, | |||
970 | raw_ostream &OS) { | |||
971 | StringRef MacroName = T->getMacroIdentifier()->getName(); | |||
972 | OS << MacroName << " "; | |||
973 | ||||
974 | // Since this type is meant to print the macro instead of the whole attribute, | |||
975 | // we trim any attributes and go directly to the original modified type. | |||
976 | printBefore(T->getModifiedType(), OS); | |||
977 | } | |||
978 | ||||
979 | void TypePrinter::printMacroQualifiedAfter(const MacroQualifiedType *T, | |||
980 | raw_ostream &OS) { | |||
981 | printAfter(T->getModifiedType(), OS); | |||
982 | } | |||
983 | ||||
984 | void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {} | |||
985 | ||||
986 | void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T, | |||
987 | raw_ostream &OS) { | |||
988 | OS << "typeof "; | |||
989 | if (T->getUnderlyingExpr()) | |||
990 | T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy); | |||
991 | spaceBeforePlaceHolder(OS); | |||
992 | } | |||
993 | ||||
994 | void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T, | |||
995 | raw_ostream &OS) {} | |||
996 | ||||
997 | void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) { | |||
998 | OS << "typeof("; | |||
999 | print(T->getUnderlyingType(), OS, StringRef()); | |||
1000 | OS << ')'; | |||
1001 | spaceBeforePlaceHolder(OS); | |||
1002 | } | |||
1003 | ||||
1004 | void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {} | |||
1005 | ||||
1006 | void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) { | |||
1007 | OS << "decltype("; | |||
1008 | if (T->getUnderlyingExpr()) | |||
1009 | T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy); | |||
1010 | OS << ')'; | |||
1011 | spaceBeforePlaceHolder(OS); | |||
1012 | } | |||
1013 | ||||
1014 | void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) {} | |||
1015 | ||||
1016 | void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T, | |||
1017 | raw_ostream &OS) { | |||
1018 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1019 | ||||
1020 | switch (T->getUTTKind()) { | |||
1021 | case UnaryTransformType::EnumUnderlyingType: | |||
1022 | OS << "__underlying_type("; | |||
1023 | print(T->getBaseType(), OS, StringRef()); | |||
1024 | OS << ')'; | |||
1025 | spaceBeforePlaceHolder(OS); | |||
1026 | return; | |||
1027 | } | |||
1028 | ||||
1029 | printBefore(T->getBaseType(), OS); | |||
1030 | } | |||
1031 | ||||
1032 | void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T, | |||
1033 | raw_ostream &OS) { | |||
1034 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1035 | ||||
1036 | switch (T->getUTTKind()) { | |||
1037 | case UnaryTransformType::EnumUnderlyingType: | |||
1038 | return; | |||
1039 | } | |||
1040 | ||||
1041 | printAfter(T->getBaseType(), OS); | |||
1042 | } | |||
1043 | ||||
1044 | void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) { | |||
1045 | // If the type has been deduced, do not print 'auto'. | |||
1046 | if (!T->getDeducedType().isNull()) { | |||
1047 | printBefore(T->getDeducedType(), OS); | |||
1048 | } else { | |||
1049 | switch (T->getKeyword()) { | |||
1050 | case AutoTypeKeyword::Auto: OS << "auto"; break; | |||
1051 | case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break; | |||
1052 | case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break; | |||
1053 | } | |||
1054 | spaceBeforePlaceHolder(OS); | |||
1055 | } | |||
1056 | } | |||
1057 | ||||
1058 | void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) { | |||
1059 | // If the type has been deduced, do not print 'auto'. | |||
1060 | if (!T->getDeducedType().isNull()) | |||
1061 | printAfter(T->getDeducedType(), OS); | |||
1062 | } | |||
1063 | ||||
1064 | void TypePrinter::printDeducedTemplateSpecializationBefore( | |||
1065 | const DeducedTemplateSpecializationType *T, raw_ostream &OS) { | |||
1066 | // If the type has been deduced, print the deduced type. | |||
1067 | if (!T->getDeducedType().isNull()) { | |||
1068 | printBefore(T->getDeducedType(), OS); | |||
1069 | } else { | |||
1070 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1071 | T->getTemplateName().print(OS, Policy); | |||
1072 | spaceBeforePlaceHolder(OS); | |||
1073 | } | |||
1074 | } | |||
1075 | ||||
1076 | void TypePrinter::printDeducedTemplateSpecializationAfter( | |||
1077 | const DeducedTemplateSpecializationType *T, raw_ostream &OS) { | |||
1078 | // If the type has been deduced, print the deduced type. | |||
1079 | if (!T->getDeducedType().isNull()) | |||
1080 | printAfter(T->getDeducedType(), OS); | |||
1081 | } | |||
1082 | ||||
1083 | void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) { | |||
1084 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1085 | ||||
1086 | OS << "_Atomic("; | |||
1087 | print(T->getValueType(), OS, StringRef()); | |||
1088 | OS << ')'; | |||
1089 | spaceBeforePlaceHolder(OS); | |||
1090 | } | |||
1091 | ||||
1092 | void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) {} | |||
1093 | ||||
1094 | void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) { | |||
1095 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1096 | ||||
1097 | if (T->isReadOnly()) | |||
1098 | OS << "read_only "; | |||
1099 | else | |||
1100 | OS << "write_only "; | |||
1101 | OS << "pipe "; | |||
1102 | print(T->getElementType(), OS, StringRef()); | |||
1103 | spaceBeforePlaceHolder(OS); | |||
1104 | } | |||
1105 | ||||
1106 | void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {} | |||
1107 | ||||
1108 | /// Appends the given scope to the end of a string. | |||
1109 | void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) { | |||
1110 | if (DC->isTranslationUnit()) return; | |||
1111 | if (DC->isFunctionOrMethod()) return; | |||
1112 | AppendScope(DC->getParent(), OS); | |||
1113 | ||||
1114 | if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) { | |||
1115 | if (Policy.SuppressUnwrittenScope && | |||
1116 | (NS->isAnonymousNamespace() || NS->isInline())) | |||
1117 | return; | |||
1118 | if (NS->getIdentifier()) | |||
1119 | OS << NS->getName() << "::"; | |||
1120 | else | |||
1121 | OS << "(anonymous namespace)::"; | |||
1122 | } else if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { | |||
1123 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1124 | OS << Spec->getIdentifier()->getName(); | |||
1125 | const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); | |||
1126 | printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); | |||
1127 | OS << "::"; | |||
1128 | } else if (const auto *Tag = dyn_cast<TagDecl>(DC)) { | |||
1129 | if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl()) | |||
1130 | OS << Typedef->getIdentifier()->getName() << "::"; | |||
1131 | else if (Tag->getIdentifier()) | |||
1132 | OS << Tag->getIdentifier()->getName() << "::"; | |||
1133 | else | |||
1134 | return; | |||
1135 | } | |||
1136 | } | |||
1137 | ||||
1138 | void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { | |||
1139 | if (Policy.IncludeTagDefinition) { | |||
1140 | PrintingPolicy SubPolicy = Policy; | |||
1141 | SubPolicy.IncludeTagDefinition = false; | |||
1142 | D->print(OS, SubPolicy, Indentation); | |||
1143 | spaceBeforePlaceHolder(OS); | |||
1144 | return; | |||
1145 | } | |||
1146 | ||||
1147 | bool HasKindDecoration = false; | |||
1148 | ||||
1149 | // We don't print tags unless this is an elaborated type. | |||
1150 | // In C, we just assume every RecordType is an elaborated type. | |||
1151 | if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) { | |||
1152 | HasKindDecoration = true; | |||
1153 | OS << D->getKindName(); | |||
1154 | OS << ' '; | |||
1155 | } | |||
1156 | ||||
1157 | // Compute the full nested-name-specifier for this type. | |||
1158 | // In C, this will always be empty except when the type | |||
1159 | // being printed is anonymous within other Record. | |||
1160 | if (!Policy.SuppressScope) | |||
1161 | AppendScope(D->getDeclContext(), OS); | |||
1162 | ||||
1163 | if (const IdentifierInfo *II = D->getIdentifier()) | |||
1164 | OS << II->getName(); | |||
1165 | else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) { | |||
1166 | assert(Typedef->getIdentifier() && "Typedef without identifier?")((Typedef->getIdentifier() && "Typedef without identifier?" ) ? static_cast<void> (0) : __assert_fail ("Typedef->getIdentifier() && \"Typedef without identifier?\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/TypePrinter.cpp" , 1166, __PRETTY_FUNCTION__)); | |||
1167 | OS << Typedef->getIdentifier()->getName(); | |||
1168 | } else { | |||
1169 | // Make an unambiguous representation for anonymous types, e.g. | |||
1170 | // (anonymous enum at /usr/include/string.h:120:9) | |||
1171 | OS << (Policy.MSVCFormatting ? '`' : '('); | |||
1172 | ||||
1173 | if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) { | |||
1174 | OS << "lambda"; | |||
1175 | HasKindDecoration = true; | |||
1176 | } else { | |||
1177 | OS << "anonymous"; | |||
1178 | } | |||
1179 | ||||
1180 | if (Policy.AnonymousTagLocations) { | |||
1181 | // Suppress the redundant tag keyword if we just printed one. | |||
1182 | // We don't have to worry about ElaboratedTypes here because you can't | |||
1183 | // refer to an anonymous type with one. | |||
1184 | if (!HasKindDecoration) | |||
1185 | OS << " " << D->getKindName(); | |||
1186 | ||||
1187 | PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( | |||
1188 | D->getLocation()); | |||
1189 | if (PLoc.isValid()) { | |||
1190 | OS << " at "; | |||
1191 | StringRef File = PLoc.getFilename(); | |||
1192 | if (Policy.RemapFilePaths) | |||
1193 | OS << Policy.remapPath(File); | |||
1194 | else | |||
1195 | OS << File; | |||
1196 | OS << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); | |||
1197 | } | |||
1198 | } | |||
1199 | ||||
1200 | OS << (Policy.MSVCFormatting ? '\'' : ')'); | |||
1201 | } | |||
1202 | ||||
1203 | // If this is a class template specialization, print the template | |||
1204 | // arguments. | |||
1205 | if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(D)) { | |||
1206 | ArrayRef<TemplateArgument> Args; | |||
1207 | if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) { | |||
1208 | const TemplateSpecializationType *TST = | |||
1209 | cast<TemplateSpecializationType>(TAW->getType()); | |||
1210 | Args = TST->template_arguments(); | |||
1211 | } else { | |||
1212 | const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); | |||
1213 | Args = TemplateArgs.asArray(); | |||
1214 | } | |||
1215 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1216 | printTemplateArgumentList(OS, Args, Policy); | |||
1217 | } | |||
1218 | ||||
1219 | spaceBeforePlaceHolder(OS); | |||
1220 | } | |||
1221 | ||||
1222 | void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) { | |||
1223 | printTag(T->getDecl(), OS); | |||
1224 | } | |||
1225 | ||||
1226 | void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) {} | |||
1227 | ||||
1228 | void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) { | |||
1229 | printTag(T->getDecl(), OS); | |||
1230 | } | |||
1231 | ||||
1232 | void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {} | |||
1233 | ||||
1234 | void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T, | |||
1235 | raw_ostream &OS) { | |||
1236 | if (IdentifierInfo *Id = T->getIdentifier()) | |||
1237 | OS << Id->getName(); | |||
1238 | else { | |||
1239 | bool IsLambdaAutoParam = false; | |||
1240 | if (auto D = T->getDecl()) { | |||
1241 | if (auto M = dyn_cast_or_null<CXXMethodDecl>(D->getDeclContext())) | |||
1242 | IsLambdaAutoParam = D->isImplicit() && M->getParent()->isLambda(); | |||
1243 | } | |||
1244 | ||||
1245 | if (IsLambdaAutoParam) | |||
1246 | OS << "auto"; | |||
1247 | else | |||
1248 | OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex(); | |||
1249 | } | |||
1250 | spaceBeforePlaceHolder(OS); | |||
1251 | } | |||
1252 | ||||
1253 | void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T, | |||
1254 | raw_ostream &OS) {} | |||
1255 | ||||
1256 | void TypePrinter::printSubstTemplateTypeParmBefore( | |||
1257 | const SubstTemplateTypeParmType *T, | |||
1258 | raw_ostream &OS) { | |||
1259 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1260 | printBefore(T->getReplacementType(), OS); | |||
1261 | } | |||
1262 | ||||
1263 | void TypePrinter::printSubstTemplateTypeParmAfter( | |||
1264 | const SubstTemplateTypeParmType *T, | |||
1265 | raw_ostream &OS) { | |||
1266 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1267 | printAfter(T->getReplacementType(), OS); | |||
1268 | } | |||
1269 | ||||
1270 | void TypePrinter::printSubstTemplateTypeParmPackBefore( | |||
1271 | const SubstTemplateTypeParmPackType *T, | |||
1272 | raw_ostream &OS) { | |||
1273 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1274 | printTemplateTypeParmBefore(T->getReplacedParameter(), OS); | |||
1275 | } | |||
1276 | ||||
1277 | void TypePrinter::printSubstTemplateTypeParmPackAfter( | |||
1278 | const SubstTemplateTypeParmPackType *T, | |||
1279 | raw_ostream &OS) { | |||
1280 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1281 | printTemplateTypeParmAfter(T->getReplacedParameter(), OS); | |||
1282 | } | |||
1283 | ||||
1284 | void TypePrinter::printTemplateSpecializationBefore( | |||
1285 | const TemplateSpecializationType *T, | |||
1286 | raw_ostream &OS) { | |||
1287 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1288 | T->getTemplateName().print(OS, Policy); | |||
1289 | ||||
1290 | printTemplateArgumentList(OS, T->template_arguments(), Policy); | |||
1291 | spaceBeforePlaceHolder(OS); | |||
1292 | } | |||
1293 | ||||
1294 | void TypePrinter::printTemplateSpecializationAfter( | |||
1295 | const TemplateSpecializationType *T, | |||
1296 | raw_ostream &OS) {} | |||
1297 | ||||
1298 | void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T, | |||
1299 | raw_ostream &OS) { | |||
1300 | printTemplateSpecializationBefore(T->getInjectedTST(), OS); | |||
1301 | } | |||
1302 | ||||
1303 | void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T, | |||
1304 | raw_ostream &OS) {} | |||
1305 | ||||
1306 | void TypePrinter::printElaboratedBefore(const ElaboratedType *T, | |||
1307 | raw_ostream &OS) { | |||
1308 | if (Policy.IncludeTagDefinition && T->getOwnedTagDecl()) { | |||
1309 | TagDecl *OwnedTagDecl = T->getOwnedTagDecl(); | |||
1310 | assert(OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr() &&((OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr () && "OwnedTagDecl expected to be a declaration for the type" ) ? static_cast<void> (0) : __assert_fail ("OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr() && \"OwnedTagDecl expected to be a declaration for the type\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/TypePrinter.cpp" , 1311, __PRETTY_FUNCTION__)) | |||
1311 | "OwnedTagDecl expected to be a declaration for the type")((OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr () && "OwnedTagDecl expected to be a declaration for the type" ) ? static_cast<void> (0) : __assert_fail ("OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr() && \"OwnedTagDecl expected to be a declaration for the type\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/TypePrinter.cpp" , 1311, __PRETTY_FUNCTION__)); | |||
1312 | PrintingPolicy SubPolicy = Policy; | |||
1313 | SubPolicy.IncludeTagDefinition = false; | |||
1314 | OwnedTagDecl->print(OS, SubPolicy, Indentation); | |||
1315 | spaceBeforePlaceHolder(OS); | |||
1316 | return; | |||
1317 | } | |||
1318 | ||||
1319 | // The tag definition will take care of these. | |||
1320 | if (!Policy.IncludeTagDefinition) | |||
1321 | { | |||
1322 | OS << TypeWithKeyword::getKeywordName(T->getKeyword()); | |||
1323 | if (T->getKeyword() != ETK_None) | |||
1324 | OS << " "; | |||
1325 | NestedNameSpecifier *Qualifier = T->getQualifier(); | |||
1326 | if (Qualifier) | |||
1327 | Qualifier->print(OS, Policy); | |||
1328 | } | |||
1329 | ||||
1330 | ElaboratedTypePolicyRAII PolicyRAII(Policy); | |||
1331 | printBefore(T->getNamedType(), OS); | |||
1332 | } | |||
1333 | ||||
1334 | void TypePrinter::printElaboratedAfter(const ElaboratedType *T, | |||
1335 | raw_ostream &OS) { | |||
1336 | if (Policy.IncludeTagDefinition && T->getOwnedTagDecl()) | |||
1337 | return; | |||
1338 | ElaboratedTypePolicyRAII PolicyRAII(Policy); | |||
1339 | printAfter(T->getNamedType(), OS); | |||
1340 | } | |||
1341 | ||||
1342 | void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) { | |||
1343 | if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) { | |||
1344 | printBefore(T->getInnerType(), OS); | |||
1345 | OS << '('; | |||
1346 | } else | |||
1347 | printBefore(T->getInnerType(), OS); | |||
1348 | } | |||
1349 | ||||
1350 | void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) { | |||
1351 | if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) { | |||
1352 | OS << ')'; | |||
1353 | printAfter(T->getInnerType(), OS); | |||
1354 | } else | |||
1355 | printAfter(T->getInnerType(), OS); | |||
1356 | } | |||
1357 | ||||
1358 | void TypePrinter::printDependentNameBefore(const DependentNameType *T, | |||
1359 | raw_ostream &OS) { | |||
1360 | OS << TypeWithKeyword::getKeywordName(T->getKeyword()); | |||
1361 | if (T->getKeyword() != ETK_None) | |||
1362 | OS << " "; | |||
1363 | ||||
1364 | T->getQualifier()->print(OS, Policy); | |||
1365 | ||||
1366 | OS << T->getIdentifier()->getName(); | |||
1367 | spaceBeforePlaceHolder(OS); | |||
1368 | } | |||
1369 | ||||
1370 | void TypePrinter::printDependentNameAfter(const DependentNameType *T, | |||
1371 | raw_ostream &OS) {} | |||
1372 | ||||
1373 | void TypePrinter::printDependentTemplateSpecializationBefore( | |||
1374 | const DependentTemplateSpecializationType *T, raw_ostream &OS) { | |||
1375 | IncludeStrongLifetimeRAII Strong(Policy); | |||
1376 | ||||
1377 | OS << TypeWithKeyword::getKeywordName(T->getKeyword()); | |||
1378 | if (T->getKeyword() != ETK_None) | |||
1379 | OS << " "; | |||
1380 | ||||
1381 | if (T->getQualifier()) | |||
1382 | T->getQualifier()->print(OS, Policy); | |||
1383 | OS << T->getIdentifier()->getName(); | |||
1384 | printTemplateArgumentList(OS, T->template_arguments(), Policy); | |||
1385 | spaceBeforePlaceHolder(OS); | |||
1386 | } | |||
1387 | ||||
1388 | void TypePrinter::printDependentTemplateSpecializationAfter( | |||
1389 | const DependentTemplateSpecializationType *T, raw_ostream &OS) {} | |||
1390 | ||||
1391 | void TypePrinter::printPackExpansionBefore(const PackExpansionType *T, | |||
1392 | raw_ostream &OS) { | |||
1393 | printBefore(T->getPattern(), OS); | |||
1394 | } | |||
1395 | ||||
1396 | void TypePrinter::printPackExpansionAfter(const PackExpansionType *T, | |||
1397 | raw_ostream &OS) { | |||
1398 | printAfter(T->getPattern(), OS); | |||
1399 | OS << "..."; | |||
1400 | } | |||
1401 | ||||
1402 | void TypePrinter::printAttributedBefore(const AttributedType *T, | |||
1403 | raw_ostream &OS) { | |||
1404 | // FIXME: Generate this with TableGen. | |||
1405 | ||||
1406 | // Prefer the macro forms of the GC and ownership qualifiers. | |||
1407 | if (T->getAttrKind() == attr::ObjCGC || | |||
1408 | T->getAttrKind() == attr::ObjCOwnership) | |||
1409 | return printBefore(T->getEquivalentType(), OS); | |||
1410 | ||||
1411 | if (T->getAttrKind() == attr::ObjCKindOf) | |||
1412 | OS << "__kindof "; | |||
1413 | ||||
1414 | if (T->getAttrKind() == attr::AddressSpace) | |||
1415 | printBefore(T->getEquivalentType(), OS); | |||
1416 | else | |||
1417 | printBefore(T->getModifiedType(), OS); | |||
1418 | ||||
1419 | if (T->isMSTypeSpec()) { | |||
1420 | switch (T->getAttrKind()) { | |||
1421 | default: return; | |||
1422 | case attr::Ptr32: OS << " __ptr32"; break; | |||
1423 | case attr::Ptr64: OS << " __ptr64"; break; | |||
1424 | case attr::SPtr: OS << " __sptr"; break; | |||
1425 | case attr::UPtr: OS << " __uptr"; break; | |||
1426 | } | |||
1427 | spaceBeforePlaceHolder(OS); | |||
1428 | } | |||
1429 | ||||
1430 | // Print nullability type specifiers. | |||
1431 | if (T->getImmediateNullability()) { | |||
1432 | if (T->getAttrKind() == attr::TypeNonNull) | |||
1433 | OS << " _Nonnull"; | |||
1434 | else if (T->getAttrKind() == attr::TypeNullable) | |||
1435 | OS << " _Nullable"; | |||
1436 | else if (T->getAttrKind() == attr::TypeNullUnspecified) | |||
1437 | OS << " _Null_unspecified"; | |||
1438 | else | |||
1439 | llvm_unreachable("unhandled nullability")::llvm::llvm_unreachable_internal("unhandled nullability", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/TypePrinter.cpp" , 1439); | |||
1440 | spaceBeforePlaceHolder(OS); | |||
1441 | } | |||
1442 | } | |||
1443 | ||||
1444 | void TypePrinter::printAttributedAfter(const AttributedType *T, | |||
1445 | raw_ostream &OS) { | |||
1446 | // FIXME: Generate this with TableGen. | |||
1447 | ||||
1448 | // Prefer the macro forms of the GC and ownership qualifiers. | |||
1449 | if (T->getAttrKind() == attr::ObjCGC || | |||
| ||||
1450 | T->getAttrKind() == attr::ObjCOwnership) | |||
1451 | return printAfter(T->getEquivalentType(), OS); | |||
1452 | ||||
1453 | // If this is a calling convention attribute, don't print the implicit CC from | |||
1454 | // the modified type. | |||
1455 | SaveAndRestore<bool> MaybeSuppressCC(InsideCCAttribute, T->isCallingConv()); | |||
1456 | ||||
1457 | printAfter(T->getModifiedType(), OS); | |||
1458 | ||||
1459 | // Some attributes are printed as qualifiers before the type, so we have | |||
1460 | // nothing left to do. | |||
1461 | if (T->getAttrKind() == attr::ObjCKindOf || | |||
1462 | T->isMSTypeSpec() || T->getImmediateNullability()) | |||
1463 | return; | |||
1464 | ||||
1465 | // Don't print the inert __unsafe_unretained attribute at all. | |||
1466 | if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained) | |||
1467 | return; | |||
1468 | ||||
1469 | // Don't print ns_returns_retained unless it had an effect. | |||
1470 | if (T->getAttrKind() == attr::NSReturnsRetained && | |||
1471 | !T->getEquivalentType()->castAs<FunctionType>() | |||
1472 | ->getExtInfo().getProducesResult()) | |||
1473 | return; | |||
1474 | ||||
1475 | if (T->getAttrKind() == attr::LifetimeBound) { | |||
1476 | OS << " [[clang::lifetimebound]]"; | |||
1477 | return; | |||
1478 | } | |||
1479 | ||||
1480 | // The printing of the address_space attribute is handled by the qualifier | |||
1481 | // since it is still stored in the qualifier. Return early to prevent printing | |||
1482 | // this twice. | |||
1483 | if (T->getAttrKind() == attr::AddressSpace) | |||
1484 | return; | |||
1485 | ||||
1486 | OS << " __attribute__(("; | |||
1487 | switch (T->getAttrKind()) { | |||
1488 | #define TYPE_ATTR(NAME) | |||
1489 | #define DECL_OR_TYPE_ATTR(NAME) | |||
1490 | #define ATTR(NAME) case attr::NAME: | |||
1491 | #include "clang/Basic/AttrList.inc" | |||
1492 | llvm_unreachable("non-type attribute attached to type")::llvm::llvm_unreachable_internal("non-type attribute attached to type" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/TypePrinter.cpp" , 1492); | |||
1493 | ||||
1494 | case attr::OpenCLPrivateAddressSpace: | |||
1495 | case attr::OpenCLGlobalAddressSpace: | |||
1496 | case attr::OpenCLLocalAddressSpace: | |||
1497 | case attr::OpenCLConstantAddressSpace: | |||
1498 | case attr::OpenCLGenericAddressSpace: | |||
1499 | // FIXME: Update printAttributedBefore to print these once we generate | |||
1500 | // AttributedType nodes for them. | |||
1501 | break; | |||
1502 | ||||
1503 | case attr::LifetimeBound: | |||
1504 | case attr::TypeNonNull: | |||
1505 | case attr::TypeNullable: | |||
1506 | case attr::TypeNullUnspecified: | |||
1507 | case attr::ObjCGC: | |||
1508 | case attr::ObjCInertUnsafeUnretained: | |||
1509 | case attr::ObjCKindOf: | |||
1510 | case attr::ObjCOwnership: | |||
1511 | case attr::Ptr32: | |||
1512 | case attr::Ptr64: | |||
1513 | case attr::SPtr: | |||
1514 | case attr::UPtr: | |||
1515 | case attr::AddressSpace: | |||
1516 | llvm_unreachable("This attribute should have been handled already")::llvm::llvm_unreachable_internal("This attribute should have been handled already" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/TypePrinter.cpp" , 1516); | |||
1517 | ||||
1518 | case attr::NSReturnsRetained: | |||
1519 | OS << "ns_returns_retained"; | |||
1520 | break; | |||
1521 | ||||
1522 | // FIXME: When Sema learns to form this AttributedType, avoid printing the | |||
1523 | // attribute again in printFunctionProtoAfter. | |||
1524 | case attr::AnyX86NoCfCheck: OS << "nocf_check"; break; | |||
1525 | case attr::CDecl: OS << "cdecl"; break; | |||
1526 | case attr::FastCall: OS << "fastcall"; break; | |||
1527 | case attr::StdCall: OS << "stdcall"; break; | |||
1528 | case attr::ThisCall: OS << "thiscall"; break; | |||
1529 | case attr::SwiftCall: OS << "swiftcall"; break; | |||
1530 | case attr::VectorCall: OS << "vectorcall"; break; | |||
1531 | case attr::Pascal: OS << "pascal"; break; | |||
1532 | case attr::MSABI: OS << "ms_abi"; break; | |||
1533 | case attr::SysVABI: OS << "sysv_abi"; break; | |||
1534 | case attr::RegCall: OS << "regcall"; break; | |||
1535 | case attr::Pcs: { | |||
1536 | OS << "pcs("; | |||
1537 | QualType t = T->getEquivalentType(); | |||
1538 | while (!t->isFunctionType()) | |||
1539 | t = t->getPointeeType(); | |||
1540 | OS << (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ? | |||
| ||||
1541 | "\"aapcs\"" : "\"aapcs-vfp\""); | |||
1542 | OS << ')'; | |||
1543 | break; | |||
1544 | } | |||
1545 | case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break; | |||
1546 | case attr::IntelOclBicc: OS << "inteloclbicc"; break; | |||
1547 | case attr::PreserveMost: | |||
1548 | OS << "preserve_most"; | |||
1549 | break; | |||
1550 | ||||
1551 | case attr::PreserveAll: | |||
1552 | OS << "preserve_all"; | |||
1553 | break; | |||
1554 | case attr::NoDeref: | |||
1555 | OS << "noderef"; | |||
1556 | break; | |||
1557 | } | |||
1558 | OS << "))"; | |||
1559 | } | |||
1560 | ||||
1561 | void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T, | |||
1562 | raw_ostream &OS) { | |||
1563 | OS << T->getDecl()->getName(); | |||
1564 | spaceBeforePlaceHolder(OS); | |||
1565 | } | |||
1566 | ||||
1567 | void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T, | |||
1568 | raw_ostream &OS) {} | |||
1569 | ||||
1570 | void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T, | |||
1571 | raw_ostream &OS) { | |||
1572 | OS << T->getDecl()->getName(); | |||
1573 | if (!T->qual_empty()) { | |||
1574 | bool isFirst = true; | |||
1575 | OS << '<'; | |||
1576 | for (const auto *I : T->quals()) { | |||
1577 | if (isFirst) | |||
1578 | isFirst = false; | |||
1579 | else | |||
1580 | OS << ','; | |||
1581 | OS << I->getName(); | |||
1582 | } | |||
1583 | OS << '>'; | |||
1584 | } | |||
1585 | ||||
1586 | spaceBeforePlaceHolder(OS); | |||
1587 | } | |||
1588 | ||||
1589 | void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T, | |||
1590 | raw_ostream &OS) {} | |||
1591 | ||||
1592 | void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T, | |||
1593 | raw_ostream &OS) { | |||
1594 | if (T->qual_empty() && T->isUnspecializedAsWritten() && | |||
1595 | !T->isKindOfTypeAsWritten()) | |||
1596 | return printBefore(T->getBaseType(), OS); | |||
1597 | ||||
1598 | if (T->isKindOfTypeAsWritten()) | |||
1599 | OS << "__kindof "; | |||
1600 | ||||
1601 | print(T->getBaseType(), OS, StringRef()); | |||
1602 | ||||
1603 | if (T->isSpecializedAsWritten()) { | |||
1604 | bool isFirst = true; | |||
1605 | OS << '<'; | |||
1606 | for (auto typeArg : T->getTypeArgsAsWritten()) { | |||
1607 | if (isFirst) | |||
1608 | isFirst = false; | |||
1609 | else | |||
1610 | OS << ","; | |||
1611 | ||||
1612 | print(typeArg, OS, StringRef()); | |||
1613 | } | |||
1614 | OS << '>'; | |||
1615 | } | |||
1616 | ||||
1617 | if (!T->qual_empty()) { | |||
1618 | bool isFirst = true; | |||
1619 | OS << '<'; | |||
1620 | for (const auto *I : T->quals()) { | |||
1621 | if (isFirst) | |||
1622 | isFirst = false; | |||
1623 | else | |||
1624 | OS << ','; | |||
1625 | OS << I->getName(); | |||
1626 | } | |||
1627 | OS << '>'; | |||
1628 | } | |||
1629 | ||||
1630 | spaceBeforePlaceHolder(OS); | |||
1631 | } | |||
1632 | ||||
1633 | void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T, | |||
1634 | raw_ostream &OS) { | |||
1635 | if (T->qual_empty() && T->isUnspecializedAsWritten() && | |||
1636 | !T->isKindOfTypeAsWritten()) | |||
1637 | return printAfter(T->getBaseType(), OS); | |||
1638 | } | |||
1639 | ||||
1640 | void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T, | |||
1641 | raw_ostream &OS) { | |||
1642 | printBefore(T->getPointeeType(), OS); | |||
1643 | ||||
1644 | // If we need to print the pointer, print it now. | |||
1645 | if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() && | |||
1646 | !T->isObjCClassType() && !T->isObjCQualifiedClassType()) { | |||
1647 | if (HasEmptyPlaceHolder) | |||
1648 | OS << ' '; | |||
1649 | OS << '*'; | |||
1650 | } | |||
1651 | } | |||
1652 | ||||
1653 | void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T, | |||
1654 | raw_ostream &OS) {} | |||
1655 | ||||
1656 | static | |||
1657 | const TemplateArgument &getArgument(const TemplateArgument &A) { return A; } | |||
1658 | ||||
1659 | static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) { | |||
1660 | return A.getArgument(); | |||
1661 | } | |||
1662 | ||||
1663 | static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP, | |||
1664 | llvm::raw_ostream &OS) { | |||
1665 | A.print(PP, OS); | |||
1666 | } | |||
1667 | ||||
1668 | static void printArgument(const TemplateArgumentLoc &A, | |||
1669 | const PrintingPolicy &PP, llvm::raw_ostream &OS) { | |||
1670 | const TemplateArgument::ArgKind &Kind = A.getArgument().getKind(); | |||
1671 | if (Kind == TemplateArgument::ArgKind::Type) | |||
1672 | return A.getTypeSourceInfo()->getType().print(OS, PP); | |||
1673 | return A.getArgument().print(PP, OS); | |||
1674 | } | |||
1675 | ||||
1676 | template<typename TA> | |||
1677 | static void printTo(raw_ostream &OS, ArrayRef<TA> Args, | |||
1678 | const PrintingPolicy &Policy, bool SkipBrackets) { | |||
1679 | const char *Comma = Policy.MSVCFormatting ? "," : ", "; | |||
1680 | if (!SkipBrackets) | |||
1681 | OS << '<'; | |||
1682 | ||||
1683 | bool NeedSpace = false; | |||
1684 | bool FirstArg = true; | |||
1685 | for (const auto &Arg : Args) { | |||
1686 | // Print the argument into a string. | |||
1687 | SmallString<128> Buf; | |||
1688 | llvm::raw_svector_ostream ArgOS(Buf); | |||
1689 | const TemplateArgument &Argument = getArgument(Arg); | |||
1690 | if (Argument.getKind() == TemplateArgument::Pack) { | |||
1691 | if (Argument.pack_size() && !FirstArg) | |||
1692 | OS << Comma; | |||
1693 | printTo(ArgOS, Argument.getPackAsArray(), Policy, true); | |||
1694 | } else { | |||
1695 | if (!FirstArg) | |||
1696 | OS << Comma; | |||
1697 | // Tries to print the argument with location info if exists. | |||
1698 | printArgument(Arg, Policy, ArgOS); | |||
1699 | } | |||
1700 | StringRef ArgString = ArgOS.str(); | |||
1701 | ||||
1702 | // If this is the first argument and its string representation | |||
1703 | // begins with the global scope specifier ('::foo'), add a space | |||
1704 | // to avoid printing the diagraph '<:'. | |||
1705 | if (FirstArg && !ArgString.empty() && ArgString[0] == ':') | |||
1706 | OS << ' '; | |||
1707 | ||||
1708 | OS << ArgString; | |||
1709 | ||||
1710 | NeedSpace = (!ArgString.empty() && ArgString.back() == '>'); | |||
1711 | FirstArg = false; | |||
1712 | } | |||
1713 | ||||
1714 | // If the last character of our string is '>', add another space to | |||
1715 | // keep the two '>''s separate tokens. We don't *have* to do this in | |||
1716 | // C++0x, but it's still good hygiene. | |||
1717 | if (NeedSpace) | |||
1718 | OS << ' '; | |||
1719 | ||||
1720 | if (!SkipBrackets) | |||
1721 | OS << '>'; | |||
1722 | } | |||
1723 | ||||
1724 | void clang::printTemplateArgumentList(raw_ostream &OS, | |||
1725 | const TemplateArgumentListInfo &Args, | |||
1726 | const PrintingPolicy &Policy) { | |||
1727 | return printTo(OS, Args.arguments(), Policy, false); | |||
1728 | } | |||
1729 | ||||
1730 | void clang::printTemplateArgumentList(raw_ostream &OS, | |||
1731 | ArrayRef<TemplateArgument> Args, | |||
1732 | const PrintingPolicy &Policy) { | |||
1733 | printTo(OS, Args, Policy, false); | |||
1734 | } | |||
1735 | ||||
1736 | void clang::printTemplateArgumentList(raw_ostream &OS, | |||
1737 | ArrayRef<TemplateArgumentLoc> Args, | |||
1738 | const PrintingPolicy &Policy) { | |||
1739 | printTo(OS, Args, Policy, false); | |||
1740 | } | |||
1741 | ||||
1742 | std::string Qualifiers::getAsString() const { | |||
1743 | LangOptions LO; | |||
1744 | return getAsString(PrintingPolicy(LO)); | |||
1745 | } | |||
1746 | ||||
1747 | // Appends qualifiers to the given string, separated by spaces. Will | |||
1748 | // prefix a space if the string is non-empty. Will not append a final | |||
1749 | // space. | |||
1750 | std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const { | |||
1751 | SmallString<64> Buf; | |||
1752 | llvm::raw_svector_ostream StrOS(Buf); | |||
1753 | print(StrOS, Policy); | |||
1754 | return StrOS.str(); | |||
1755 | } | |||
1756 | ||||
1757 | bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const { | |||
1758 | if (getCVRQualifiers()) | |||
1759 | return false; | |||
1760 | ||||
1761 | if (getAddressSpace() != LangAS::Default) | |||
1762 | return false; | |||
1763 | ||||
1764 | if (getObjCGCAttr()) | |||
1765 | return false; | |||
1766 | ||||
1767 | if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) | |||
1768 | if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)) | |||
1769 | return false; | |||
1770 | ||||
1771 | return true; | |||
1772 | } | |||
1773 | ||||
1774 | // Appends qualifiers to the given string, separated by spaces. Will | |||
1775 | // prefix a space if the string is non-empty. Will not append a final | |||
1776 | // space. | |||
1777 | void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, | |||
1778 | bool appendSpaceIfNonEmpty) const { | |||
1779 | bool addSpace = false; | |||
1780 | ||||
1781 | unsigned quals = getCVRQualifiers(); | |||
1782 | if (quals) { | |||
1783 | AppendTypeQualList(OS, quals, Policy.Restrict); | |||
1784 | addSpace = true; | |||
1785 | } | |||
1786 | if (hasUnaligned()) { | |||
1787 | if (addSpace) | |||
1788 | OS << ' '; | |||
1789 | OS << "__unaligned"; | |||
1790 | addSpace = true; | |||
1791 | } | |||
1792 | LangAS addrspace = getAddressSpace(); | |||
1793 | if (addrspace != LangAS::Default) { | |||
1794 | if (addrspace != LangAS::opencl_private) { | |||
1795 | if (addSpace) | |||
1796 | OS << ' '; | |||
1797 | addSpace = true; | |||
1798 | switch (addrspace) { | |||
1799 | case LangAS::opencl_global: | |||
1800 | OS << "__global"; | |||
1801 | break; | |||
1802 | case LangAS::opencl_local: | |||
1803 | OS << "__local"; | |||
1804 | break; | |||
1805 | case LangAS::opencl_private: | |||
1806 | break; | |||
1807 | case LangAS::opencl_constant: | |||
1808 | OS << "__constant"; | |||
1809 | break; | |||
1810 | case LangAS::opencl_generic: | |||
1811 | OS << "__generic"; | |||
1812 | break; | |||
1813 | case LangAS::cuda_device: | |||
1814 | OS << "__device__"; | |||
1815 | break; | |||
1816 | case LangAS::cuda_constant: | |||
1817 | OS << "__constant__"; | |||
1818 | break; | |||
1819 | case LangAS::cuda_shared: | |||
1820 | OS << "__shared__"; | |||
1821 | break; | |||
1822 | default: | |||
1823 | OS << "__attribute__((address_space("; | |||
1824 | OS << toTargetAddressSpace(addrspace); | |||
1825 | OS << ")))"; | |||
1826 | } | |||
1827 | } | |||
1828 | } | |||
1829 | if (Qualifiers::GC gc = getObjCGCAttr()) { | |||
1830 | if (addSpace) | |||
1831 | OS << ' '; | |||
1832 | addSpace = true; | |||
1833 | if (gc == Qualifiers::Weak) | |||
1834 | OS << "__weak"; | |||
1835 | else | |||
1836 | OS << "__strong"; | |||
1837 | } | |||
1838 | if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) { | |||
1839 | if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){ | |||
1840 | if (addSpace) | |||
1841 | OS << ' '; | |||
1842 | addSpace = true; | |||
1843 | } | |||
1844 | ||||
1845 | switch (lifetime) { | |||
1846 | case Qualifiers::OCL_None: llvm_unreachable("none but true")::llvm::llvm_unreachable_internal("none but true", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/AST/TypePrinter.cpp" , 1846); | |||
1847 | case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break; | |||
1848 | case Qualifiers::OCL_Strong: | |||
1849 | if (!Policy.SuppressStrongLifetime) | |||
1850 | OS << "__strong"; | |||
1851 | break; | |||
1852 | ||||
1853 | case Qualifiers::OCL_Weak: OS << "__weak"; break; | |||
1854 | case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break; | |||
1855 | } | |||
1856 | } | |||
1857 | ||||
1858 | if (appendSpaceIfNonEmpty && addSpace) | |||
1859 | OS << ' '; | |||
1860 | } | |||
1861 | ||||
1862 | std::string QualType::getAsString() const { | |||
1863 | return getAsString(split(), LangOptions()); | |||
1864 | } | |||
1865 | ||||
1866 | std::string QualType::getAsString(const PrintingPolicy &Policy) const { | |||
1867 | std::string S; | |||
1868 | getAsStringInternal(S, Policy); | |||
1869 | return S; | |||
1870 | } | |||
1871 | ||||
1872 | std::string QualType::getAsString(const Type *ty, Qualifiers qs, | |||
1873 | const PrintingPolicy &Policy) { | |||
1874 | std::string buffer; | |||
1875 | getAsStringInternal(ty, qs, buffer, Policy); | |||
1876 | return buffer; | |||
1877 | } | |||
1878 | ||||
1879 | void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy, | |||
1880 | const Twine &PlaceHolder, unsigned Indentation) const { | |||
1881 | print(splitAccordingToPolicy(*this, Policy), OS, Policy, PlaceHolder, | |||
1882 | Indentation); | |||
1883 | } | |||
1884 | ||||
1885 | void QualType::print(const Type *ty, Qualifiers qs, | |||
1886 | raw_ostream &OS, const PrintingPolicy &policy, | |||
1887 | const Twine &PlaceHolder, unsigned Indentation) { | |||
1888 | SmallString<128> PHBuf; | |||
1889 | StringRef PH = PlaceHolder.toStringRef(PHBuf); | |||
1890 | ||||
1891 | TypePrinter(policy, Indentation).print(ty, qs, OS, PH); | |||
1892 | } | |||
1893 | ||||
1894 | void QualType::getAsStringInternal(std::string &Str, | |||
1895 | const PrintingPolicy &Policy) const { | |||
1896 | return getAsStringInternal(splitAccordingToPolicy(*this, Policy), Str, | |||
1897 | Policy); | |||
1898 | } | |||
1899 | ||||
1900 | void QualType::getAsStringInternal(const Type *ty, Qualifiers qs, | |||
1901 | std::string &buffer, | |||
1902 | const PrintingPolicy &policy) { | |||
1903 | SmallString<256> Buf; | |||
1904 | llvm::raw_svector_ostream StrOS(Buf); | |||
1905 | TypePrinter(policy).print(ty, qs, StrOS, buffer); | |||
1906 | std::string str = StrOS.str(); | |||
1907 | buffer.swap(str); | |||
1908 | } |