1 | #include "clang/AST/JSONNodeDumper.h" |
---|---|
2 | #include "clang/AST/Type.h" |
3 | #include "clang/Basic/SourceManager.h" |
4 | #include "clang/Basic/Specifiers.h" |
5 | #include "clang/Lex/Lexer.h" |
6 | #include "llvm/ADT/StringExtras.h" |
7 | |
8 | using namespace clang; |
9 | |
10 | void JSONNodeDumper::addPreviousDeclaration(const Decl *D) { |
11 | switch (D->getKind()) { |
12 | #define DECL(DERIVED, BASE) \ |
13 | case Decl::DERIVED: \ |
14 | return writePreviousDeclImpl(cast<DERIVED##Decl>(D)); |
15 | #define ABSTRACT_DECL(DECL) |
16 | #include "clang/AST/DeclNodes.inc" |
17 | #undef ABSTRACT_DECL |
18 | #undef DECL |
19 | } |
20 | llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); |
21 | } |
22 | |
23 | void JSONNodeDumper::Visit(const Attr *A) { |
24 | const char *AttrName = nullptr; |
25 | switch (A->getKind()) { |
26 | #define ATTR(X) \ |
27 | case attr::X: \ |
28 | AttrName = #X"Attr"; \ |
29 | break; |
30 | #include "clang/Basic/AttrList.inc" |
31 | #undef ATTR |
32 | } |
33 | JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: A)); |
34 | JOS.attribute(Key: "kind", Contents: AttrName); |
35 | JOS.attributeObject("range", [A, this] { writeSourceRange(R: A->getRange()); }); |
36 | attributeOnlyIfTrue(Key: "inherited", Value: A->isInherited()); |
37 | attributeOnlyIfTrue(Key: "implicit", Value: A->isImplicit()); |
38 | |
39 | // FIXME: it would be useful for us to output the spelling kind as well as |
40 | // the actual spelling. This would allow us to distinguish between the |
41 | // various attribute syntaxes, but we don't currently track that information |
42 | // within the AST. |
43 | //JOS.attribute("spelling", A->getSpelling()); |
44 | |
45 | InnerAttrVisitor::Visit(A); |
46 | } |
47 | |
48 | void JSONNodeDumper::Visit(const Stmt *S) { |
49 | if (!S) |
50 | return; |
51 | |
52 | JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: S)); |
53 | JOS.attribute(Key: "kind", Contents: S->getStmtClassName()); |
54 | JOS.attributeObject(Key: "range", |
55 | Contents: [S, this] { writeSourceRange(R: S->getSourceRange()); }); |
56 | |
57 | if (const auto *E = dyn_cast<Expr>(Val: S)) { |
58 | JOS.attribute(Key: "type", Contents: createQualType(QT: E->getType())); |
59 | const char *Category = nullptr; |
60 | switch (E->getValueKind()) { |
61 | case VK_LValue: Category = "lvalue"; break; |
62 | case VK_XValue: Category = "xvalue"; break; |
63 | case VK_PRValue: |
64 | Category = "prvalue"; |
65 | break; |
66 | } |
67 | JOS.attribute(Key: "valueCategory", Contents: Category); |
68 | } |
69 | InnerStmtVisitor::Visit(S); |
70 | } |
71 | |
72 | void JSONNodeDumper::Visit(const Type *T) { |
73 | JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: T)); |
74 | |
75 | if (!T) |
76 | return; |
77 | |
78 | JOS.attribute(Key: "kind", Contents: (llvm::Twine(T->getTypeClassName()) + "Type").str()); |
79 | JOS.attribute(Key: "type", Contents: createQualType(QT: QualType(T, 0), /*Desugar=*/false)); |
80 | attributeOnlyIfTrue(Key: "containsErrors", Value: T->containsErrors()); |
81 | attributeOnlyIfTrue(Key: "isDependent", Value: T->isDependentType()); |
82 | attributeOnlyIfTrue(Key: "isInstantiationDependent", |
83 | Value: T->isInstantiationDependentType()); |
84 | attributeOnlyIfTrue(Key: "isVariablyModified", Value: T->isVariablyModifiedType()); |
85 | attributeOnlyIfTrue(Key: "containsUnexpandedPack", |
86 | Value: T->containsUnexpandedParameterPack()); |
87 | attributeOnlyIfTrue(Key: "isImported", Value: T->isFromAST()); |
88 | InnerTypeVisitor::Visit(T); |
89 | } |
90 | |
91 | void JSONNodeDumper::Visit(QualType T) { |
92 | JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: T.getAsOpaquePtr())); |
93 | JOS.attribute(Key: "kind", Contents: "QualType"); |
94 | JOS.attribute(Key: "type", Contents: createQualType(QT: T)); |
95 | JOS.attribute(Key: "qualifiers", Contents: T.split().Quals.getAsString()); |
96 | } |
97 | |
98 | void JSONNodeDumper::Visit(TypeLoc TL) { |
99 | if (TL.isNull()) |
100 | return; |
101 | JOS.attribute(Key: "kind", |
102 | Contents: (llvm::Twine(TL.getTypeLocClass() == TypeLoc::Qualified |
103 | ? "Qualified" |
104 | : TL.getTypePtr()->getTypeClassName()) + |
105 | "TypeLoc") |
106 | .str()); |
107 | JOS.attribute(Key: "type", |
108 | Contents: createQualType(QT: QualType(TL.getType()), /*Desugar=*/false)); |
109 | JOS.attributeObject(Key: "range", |
110 | Contents: [TL, this] { writeSourceRange(R: TL.getSourceRange()); }); |
111 | } |
112 | |
113 | void JSONNodeDumper::Visit(const Decl *D) { |
114 | JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: D)); |
115 | |
116 | if (!D) |
117 | return; |
118 | |
119 | JOS.attribute(Key: "kind", Contents: (llvm::Twine(D->getDeclKindName()) + "Decl").str()); |
120 | JOS.attributeObject(Key: "loc", |
121 | Contents: [D, this] { writeSourceLocation(Loc: D->getLocation()); }); |
122 | JOS.attributeObject(Key: "range", |
123 | Contents: [D, this] { writeSourceRange(R: D->getSourceRange()); }); |
124 | attributeOnlyIfTrue(Key: "isImplicit", Value: D->isImplicit()); |
125 | attributeOnlyIfTrue(Key: "isInvalid", Value: D->isInvalidDecl()); |
126 | |
127 | if (D->isUsed()) |
128 | JOS.attribute(Key: "isUsed", Contents: true); |
129 | else if (D->isThisDeclarationReferenced()) |
130 | JOS.attribute(Key: "isReferenced", Contents: true); |
131 | |
132 | if (const auto *ND = dyn_cast<NamedDecl>(Val: D)) |
133 | attributeOnlyIfTrue(Key: "isHidden", Value: !ND->isUnconditionallyVisible()); |
134 | |
135 | if (D->getLexicalDeclContext() != D->getDeclContext()) { |
136 | // Because of multiple inheritance, a DeclContext pointer does not produce |
137 | // the same pointer representation as a Decl pointer that references the |
138 | // same AST Node. |
139 | const auto *ParentDeclContextDecl = dyn_cast<Decl>(Val: D->getDeclContext()); |
140 | JOS.attribute(Key: "parentDeclContextId", |
141 | Contents: createPointerRepresentation(Ptr: ParentDeclContextDecl)); |
142 | } |
143 | |
144 | addPreviousDeclaration(D); |
145 | InnerDeclVisitor::Visit(D); |
146 | } |
147 | |
148 | void JSONNodeDumper::Visit(const comments::Comment *C, |
149 | const comments::FullComment *FC) { |
150 | if (!C) |
151 | return; |
152 | |
153 | JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: C)); |
154 | JOS.attribute(Key: "kind", Contents: C->getCommentKindName()); |
155 | JOS.attributeObject(Key: "loc", |
156 | Contents: [C, this] { writeSourceLocation(Loc: C->getLocation()); }); |
157 | JOS.attributeObject(Key: "range", |
158 | Contents: [C, this] { writeSourceRange(R: C->getSourceRange()); }); |
159 | |
160 | InnerCommentVisitor::visit(C, FC); |
161 | } |
162 | |
163 | void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R, |
164 | const Decl *From, StringRef Label) { |
165 | JOS.attribute(Key: "kind", Contents: "TemplateArgument"); |
166 | if (R.isValid()) |
167 | JOS.attributeObject(Key: "range", Contents: [R, this] { writeSourceRange(R); }); |
168 | |
169 | if (From) |
170 | JOS.attribute(Key: Label.empty() ? "fromDecl": Label, Contents: createBareDeclRef(D: From)); |
171 | |
172 | InnerTemplateArgVisitor::Visit(TA); |
173 | } |
174 | |
175 | void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) { |
176 | JOS.attribute(Key: "kind", Contents: "CXXCtorInitializer"); |
177 | if (Init->isAnyMemberInitializer()) |
178 | JOS.attribute(Key: "anyInit", Contents: createBareDeclRef(Init->getAnyMember())); |
179 | else if (Init->isBaseInitializer()) |
180 | JOS.attribute(Key: "baseInit", |
181 | Contents: createQualType(QT: QualType(Init->getBaseClass(), 0))); |
182 | else if (Init->isDelegatingInitializer()) |
183 | JOS.attribute(Key: "delegatingInit", |
184 | Contents: createQualType(QT: Init->getTypeSourceInfo()->getType())); |
185 | else |
186 | llvm_unreachable("Unknown initializer type"); |
187 | } |
188 | |
189 | void JSONNodeDumper::Visit(const OpenACCClause *C) {} |
190 | |
191 | void JSONNodeDumper::Visit(const OMPClause *C) {} |
192 | |
193 | void JSONNodeDumper::Visit(const BlockDecl::Capture &C) { |
194 | JOS.attribute(Key: "kind", Contents: "Capture"); |
195 | attributeOnlyIfTrue(Key: "byref", Value: C.isByRef()); |
196 | attributeOnlyIfTrue(Key: "nested", Value: C.isNested()); |
197 | if (C.getVariable()) |
198 | JOS.attribute(Key: "var", Contents: createBareDeclRef(C.getVariable())); |
199 | } |
200 | |
201 | void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) { |
202 | JOS.attribute(Key: "associationKind", Contents: A.getTypeSourceInfo() ? "case": "default"); |
203 | attributeOnlyIfTrue(Key: "selected", Value: A.isSelected()); |
204 | } |
205 | |
206 | void JSONNodeDumper::Visit(const concepts::Requirement *R) { |
207 | if (!R) |
208 | return; |
209 | |
210 | switch (R->getKind()) { |
211 | case concepts::Requirement::RK_Type: |
212 | JOS.attribute(Key: "kind", Contents: "TypeRequirement"); |
213 | break; |
214 | case concepts::Requirement::RK_Simple: |
215 | JOS.attribute(Key: "kind", Contents: "SimpleRequirement"); |
216 | break; |
217 | case concepts::Requirement::RK_Compound: |
218 | JOS.attribute(Key: "kind", Contents: "CompoundRequirement"); |
219 | break; |
220 | case concepts::Requirement::RK_Nested: |
221 | JOS.attribute(Key: "kind", Contents: "NestedRequirement"); |
222 | break; |
223 | } |
224 | |
225 | if (auto *ER = dyn_cast<concepts::ExprRequirement>(Val: R)) |
226 | attributeOnlyIfTrue(Key: "noexcept", Value: ER->hasNoexceptRequirement()); |
227 | |
228 | attributeOnlyIfTrue(Key: "isDependent", Value: R->isDependent()); |
229 | if (!R->isDependent()) |
230 | JOS.attribute(Key: "satisfied", Contents: R->isSatisfied()); |
231 | attributeOnlyIfTrue(Key: "containsUnexpandedPack", |
232 | Value: R->containsUnexpandedParameterPack()); |
233 | } |
234 | |
235 | void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) { |
236 | std::string Str; |
237 | llvm::raw_string_ostream OS(Str); |
238 | Value.printPretty(OS, Ctx, Ty); |
239 | JOS.attribute(Key: "value", Contents: Str); |
240 | } |
241 | |
242 | void JSONNodeDumper::Visit(const ConceptReference *CR) { |
243 | JOS.attribute(Key: "kind", Contents: "ConceptReference"); |
244 | JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: CR->getNamedConcept())); |
245 | if (const auto *Args = CR->getTemplateArgsAsWritten()) { |
246 | JOS.attributeArray(Key: "templateArgsAsWritten", Contents: [Args, this] { |
247 | for (const TemplateArgumentLoc &TAL : Args->arguments()) |
248 | JOS.object( |
249 | Contents: [&TAL, this] { Visit(TA: TAL.getArgument(), R: TAL.getSourceRange()); }); |
250 | }); |
251 | } |
252 | JOS.attributeObject(Key: "loc", |
253 | Contents: [CR, this] { writeSourceLocation(Loc: CR->getLocation()); }); |
254 | JOS.attributeObject(Key: "range", |
255 | Contents: [CR, this] { writeSourceRange(R: CR->getSourceRange()); }); |
256 | } |
257 | |
258 | void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) { |
259 | if (Loc.isInvalid()) |
260 | return; |
261 | |
262 | JOS.attributeBegin(Key: "includedFrom"); |
263 | JOS.objectBegin(); |
264 | |
265 | if (!JustFirst) { |
266 | // Walk the stack recursively, then print out the presumed location. |
267 | writeIncludeStack(Loc: SM.getPresumedLoc(Loc: Loc.getIncludeLoc())); |
268 | } |
269 | |
270 | JOS.attribute(Key: "file", Contents: Loc.getFilename()); |
271 | JOS.objectEnd(); |
272 | JOS.attributeEnd(); |
273 | } |
274 | |
275 | void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc, |
276 | bool IsSpelling) { |
277 | PresumedLoc Presumed = SM.getPresumedLoc(Loc); |
278 | unsigned ActualLine = IsSpelling ? SM.getSpellingLineNumber(Loc) |
279 | : SM.getExpansionLineNumber(Loc); |
280 | StringRef ActualFile = SM.getBufferName(Loc); |
281 | |
282 | if (Presumed.isValid()) { |
283 | JOS.attribute(Key: "offset", Contents: SM.getDecomposedLoc(Loc).second); |
284 | if (LastLocFilename != ActualFile) { |
285 | JOS.attribute(Key: "file", Contents: ActualFile); |
286 | JOS.attribute(Key: "line", Contents: ActualLine); |
287 | } else if (LastLocLine != ActualLine) |
288 | JOS.attribute(Key: "line", Contents: ActualLine); |
289 | |
290 | StringRef PresumedFile = Presumed.getFilename(); |
291 | if (PresumedFile != ActualFile && LastLocPresumedFilename != PresumedFile) |
292 | JOS.attribute(Key: "presumedFile", Contents: PresumedFile); |
293 | |
294 | unsigned PresumedLine = Presumed.getLine(); |
295 | if (ActualLine != PresumedLine && LastLocPresumedLine != PresumedLine) |
296 | JOS.attribute(Key: "presumedLine", Contents: PresumedLine); |
297 | |
298 | JOS.attribute(Key: "col", Contents: Presumed.getColumn()); |
299 | JOS.attribute(Key: "tokLen", |
300 | Contents: Lexer::MeasureTokenLength(Loc, SM, LangOpts: Ctx.getLangOpts())); |
301 | LastLocFilename = ActualFile; |
302 | LastLocPresumedFilename = PresumedFile; |
303 | LastLocPresumedLine = PresumedLine; |
304 | LastLocLine = ActualLine; |
305 | |
306 | // Orthogonal to the file, line, and column de-duplication is whether the |
307 | // given location was a result of an include. If so, print where the |
308 | // include location came from. |
309 | writeIncludeStack(Loc: SM.getPresumedLoc(Loc: Presumed.getIncludeLoc()), |
310 | /*JustFirst*/ true); |
311 | } |
312 | } |
313 | |
314 | void JSONNodeDumper::writeSourceLocation(SourceLocation Loc) { |
315 | SourceLocation Spelling = SM.getSpellingLoc(Loc); |
316 | SourceLocation Expansion = SM.getExpansionLoc(Loc); |
317 | |
318 | if (Expansion != Spelling) { |
319 | // If the expansion and the spelling are different, output subobjects |
320 | // describing both locations. |
321 | JOS.attributeObject(Key: "spellingLoc", Contents: [Spelling, this] { |
322 | writeBareSourceLocation(Loc: Spelling, /*IsSpelling*/ true); |
323 | }); |
324 | JOS.attributeObject(Key: "expansionLoc", Contents: [Expansion, Loc, this] { |
325 | writeBareSourceLocation(Loc: Expansion, /*IsSpelling*/ false); |
326 | // If there is a macro expansion, add extra information if the interesting |
327 | // bit is the macro arg expansion. |
328 | if (SM.isMacroArgExpansion(Loc)) |
329 | JOS.attribute(Key: "isMacroArgExpansion", Contents: true); |
330 | }); |
331 | } else |
332 | writeBareSourceLocation(Loc: Spelling, /*IsSpelling*/ true); |
333 | } |
334 | |
335 | void JSONNodeDumper::writeSourceRange(SourceRange R) { |
336 | JOS.attributeObject(Key: "begin", |
337 | Contents: [R, this] { writeSourceLocation(Loc: R.getBegin()); }); |
338 | JOS.attributeObject(Key: "end", Contents: [R, this] { writeSourceLocation(Loc: R.getEnd()); }); |
339 | } |
340 | |
341 | std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) { |
342 | // Because JSON stores integer values as signed 64-bit integers, trying to |
343 | // represent them as such makes for very ugly pointer values in the resulting |
344 | // output. Instead, we convert the value to hex and treat it as a string. |
345 | return "0x"+ llvm::utohexstr(X: reinterpret_cast<uint64_t>(Ptr), LowerCase: true); |
346 | } |
347 | |
348 | llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) { |
349 | SplitQualType SQT = QT.split(); |
350 | std::string SQTS = QualType::getAsString(split: SQT, Policy: PrintPolicy); |
351 | llvm::json::Object Ret{{.K: "qualType", .V: SQTS}}; |
352 | |
353 | if (Desugar && !QT.isNull()) { |
354 | SplitQualType DSQT = QT.getSplitDesugaredType(); |
355 | if (DSQT != SQT) { |
356 | std::string DSQTS = QualType::getAsString(split: DSQT, Policy: PrintPolicy); |
357 | if (DSQTS != SQTS) |
358 | Ret["desugaredQualType"] = DSQTS; |
359 | } |
360 | if (const auto *TT = QT->getAs<TypedefType>()) |
361 | Ret["typeAliasDeclId"] = createPointerRepresentation(Ptr: TT->getDecl()); |
362 | } |
363 | return Ret; |
364 | } |
365 | |
366 | void JSONNodeDumper::writeBareDeclRef(const Decl *D) { |
367 | JOS.attribute(Key: "id", Contents: createPointerRepresentation(Ptr: D)); |
368 | if (!D) |
369 | return; |
370 | |
371 | JOS.attribute(Key: "kind", Contents: (llvm::Twine(D->getDeclKindName()) + "Decl").str()); |
372 | if (const auto *ND = dyn_cast<NamedDecl>(Val: D)) |
373 | JOS.attribute(Key: "name", Contents: ND->getDeclName().getAsString()); |
374 | if (const auto *VD = dyn_cast<ValueDecl>(Val: D)) |
375 | JOS.attribute(Key: "type", Contents: createQualType(QT: VD->getType())); |
376 | } |
377 | |
378 | llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) { |
379 | llvm::json::Object Ret{{.K: "id", .V: createPointerRepresentation(Ptr: D)}}; |
380 | if (!D) |
381 | return Ret; |
382 | |
383 | Ret["kind"] = (llvm::Twine(D->getDeclKindName()) + "Decl").str(); |
384 | if (const auto *ND = dyn_cast<NamedDecl>(Val: D)) |
385 | Ret["name"] = ND->getDeclName().getAsString(); |
386 | if (const auto *VD = dyn_cast<ValueDecl>(Val: D)) |
387 | Ret["type"] = createQualType(QT: VD->getType()); |
388 | return Ret; |
389 | } |
390 | |
391 | llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) { |
392 | llvm::json::Array Ret; |
393 | if (C->path_empty()) |
394 | return Ret; |
395 | |
396 | for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) { |
397 | const CXXBaseSpecifier *Base = *I; |
398 | const auto *RD = |
399 | cast<CXXRecordDecl>(Val: Base->getType()->castAs<RecordType>()->getDecl()); |
400 | |
401 | llvm::json::Object Val{{"name", RD->getName()}}; |
402 | if (Base->isVirtual()) |
403 | Val["isVirtual"] = true; |
404 | Ret.push_back(E: std::move(Val)); |
405 | } |
406 | return Ret; |
407 | } |
408 | |
409 | #define FIELD2(Name, Flag) if (RD->Flag()) Ret[Name] = true |
410 | #define FIELD1(Flag) FIELD2(#Flag, Flag) |
411 | |
412 | static llvm::json::Object |
413 | createDefaultConstructorDefinitionData(const CXXRecordDecl *RD) { |
414 | llvm::json::Object Ret; |
415 | |
416 | FIELD2("exists", hasDefaultConstructor); |
417 | FIELD2("trivial", hasTrivialDefaultConstructor); |
418 | FIELD2("nonTrivial", hasNonTrivialDefaultConstructor); |
419 | FIELD2("userProvided", hasUserProvidedDefaultConstructor); |
420 | FIELD2("isConstexpr", hasConstexprDefaultConstructor); |
421 | FIELD2("needsImplicit", needsImplicitDefaultConstructor); |
422 | FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr); |
423 | |
424 | return Ret; |
425 | } |
426 | |
427 | static llvm::json::Object |
428 | createCopyConstructorDefinitionData(const CXXRecordDecl *RD) { |
429 | llvm::json::Object Ret; |
430 | |
431 | FIELD2("simple", hasSimpleCopyConstructor); |
432 | FIELD2("trivial", hasTrivialCopyConstructor); |
433 | FIELD2("nonTrivial", hasNonTrivialCopyConstructor); |
434 | FIELD2("userDeclared", hasUserDeclaredCopyConstructor); |
435 | FIELD2("hasConstParam", hasCopyConstructorWithConstParam); |
436 | FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam); |
437 | FIELD2("needsImplicit", needsImplicitCopyConstructor); |
438 | FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor); |
439 | if (!RD->needsOverloadResolutionForCopyConstructor()) |
440 | FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted); |
441 | |
442 | return Ret; |
443 | } |
444 | |
445 | static llvm::json::Object |
446 | createMoveConstructorDefinitionData(const CXXRecordDecl *RD) { |
447 | llvm::json::Object Ret; |
448 | |
449 | FIELD2("exists", hasMoveConstructor); |
450 | FIELD2("simple", hasSimpleMoveConstructor); |
451 | FIELD2("trivial", hasTrivialMoveConstructor); |
452 | FIELD2("nonTrivial", hasNonTrivialMoveConstructor); |
453 | FIELD2("userDeclared", hasUserDeclaredMoveConstructor); |
454 | FIELD2("needsImplicit", needsImplicitMoveConstructor); |
455 | FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor); |
456 | if (!RD->needsOverloadResolutionForMoveConstructor()) |
457 | FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted); |
458 | |
459 | return Ret; |
460 | } |
461 | |
462 | static llvm::json::Object |
463 | createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) { |
464 | llvm::json::Object Ret; |
465 | |
466 | FIELD2("simple", hasSimpleCopyAssignment); |
467 | FIELD2("trivial", hasTrivialCopyAssignment); |
468 | FIELD2("nonTrivial", hasNonTrivialCopyAssignment); |
469 | FIELD2("hasConstParam", hasCopyAssignmentWithConstParam); |
470 | FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam); |
471 | FIELD2("userDeclared", hasUserDeclaredCopyAssignment); |
472 | FIELD2("needsImplicit", needsImplicitCopyAssignment); |
473 | FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment); |
474 | |
475 | return Ret; |
476 | } |
477 | |
478 | static llvm::json::Object |
479 | createMoveAssignmentDefinitionData(const CXXRecordDecl *RD) { |
480 | llvm::json::Object Ret; |
481 | |
482 | FIELD2("exists", hasMoveAssignment); |
483 | FIELD2("simple", hasSimpleMoveAssignment); |
484 | FIELD2("trivial", hasTrivialMoveAssignment); |
485 | FIELD2("nonTrivial", hasNonTrivialMoveAssignment); |
486 | FIELD2("userDeclared", hasUserDeclaredMoveAssignment); |
487 | FIELD2("needsImplicit", needsImplicitMoveAssignment); |
488 | FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment); |
489 | |
490 | return Ret; |
491 | } |
492 | |
493 | static llvm::json::Object |
494 | createDestructorDefinitionData(const CXXRecordDecl *RD) { |
495 | llvm::json::Object Ret; |
496 | |
497 | FIELD2("simple", hasSimpleDestructor); |
498 | FIELD2("irrelevant", hasIrrelevantDestructor); |
499 | FIELD2("trivial", hasTrivialDestructor); |
500 | FIELD2("nonTrivial", hasNonTrivialDestructor); |
501 | FIELD2("userDeclared", hasUserDeclaredDestructor); |
502 | FIELD2("needsImplicit", needsImplicitDestructor); |
503 | FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor); |
504 | if (!RD->needsOverloadResolutionForDestructor()) |
505 | FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted); |
506 | |
507 | return Ret; |
508 | } |
509 | |
510 | llvm::json::Object |
511 | JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl *RD) { |
512 | llvm::json::Object Ret; |
513 | |
514 | // This data is common to all C++ classes. |
515 | FIELD1(isGenericLambda); |
516 | FIELD1(isLambda); |
517 | FIELD1(isEmpty); |
518 | FIELD1(isAggregate); |
519 | FIELD1(isStandardLayout); |
520 | FIELD1(isTriviallyCopyable); |
521 | FIELD1(isPOD); |
522 | FIELD1(isTrivial); |
523 | FIELD1(isPolymorphic); |
524 | FIELD1(isAbstract); |
525 | FIELD1(isLiteral); |
526 | FIELD1(canPassInRegisters); |
527 | FIELD1(hasUserDeclaredConstructor); |
528 | FIELD1(hasConstexprNonCopyMoveConstructor); |
529 | FIELD1(hasMutableFields); |
530 | FIELD1(hasVariantMembers); |
531 | FIELD2("canConstDefaultInit", allowConstDefaultInit); |
532 | |
533 | Ret["defaultCtor"] = createDefaultConstructorDefinitionData(RD); |
534 | Ret["copyCtor"] = createCopyConstructorDefinitionData(RD); |
535 | Ret["moveCtor"] = createMoveConstructorDefinitionData(RD); |
536 | Ret["copyAssign"] = createCopyAssignmentDefinitionData(RD); |
537 | Ret["moveAssign"] = createMoveAssignmentDefinitionData(RD); |
538 | Ret["dtor"] = createDestructorDefinitionData(RD); |
539 | |
540 | return Ret; |
541 | } |
542 | |
543 | #undef FIELD1 |
544 | #undef FIELD2 |
545 | |
546 | std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) { |
547 | const auto AccessSpelling = getAccessSpelling(AS); |
548 | if (AccessSpelling.empty()) |
549 | return "none"; |
550 | return AccessSpelling.str(); |
551 | } |
552 | |
553 | llvm::json::Object |
554 | JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier &BS) { |
555 | llvm::json::Object Ret; |
556 | |
557 | Ret["type"] = createQualType(QT: BS.getType()); |
558 | Ret["access"] = createAccessSpecifier(AS: BS.getAccessSpecifier()); |
559 | Ret["writtenAccess"] = |
560 | createAccessSpecifier(AS: BS.getAccessSpecifierAsWritten()); |
561 | if (BS.isVirtual()) |
562 | Ret["isVirtual"] = true; |
563 | if (BS.isPackExpansion()) |
564 | Ret["isPackExpansion"] = true; |
565 | |
566 | return Ret; |
567 | } |
568 | |
569 | void JSONNodeDumper::VisitAliasAttr(const AliasAttr *AA) { |
570 | JOS.attribute(Key: "aliasee", Contents: AA->getAliasee()); |
571 | } |
572 | |
573 | void JSONNodeDumper::VisitCleanupAttr(const CleanupAttr *CA) { |
574 | JOS.attribute(Key: "cleanup_function", Contents: createBareDeclRef(D: CA->getFunctionDecl())); |
575 | } |
576 | |
577 | void JSONNodeDumper::VisitDeprecatedAttr(const DeprecatedAttr *DA) { |
578 | if (!DA->getMessage().empty()) |
579 | JOS.attribute(Key: "message", Contents: DA->getMessage()); |
580 | if (!DA->getReplacement().empty()) |
581 | JOS.attribute(Key: "replacement", Contents: DA->getReplacement()); |
582 | } |
583 | |
584 | void JSONNodeDumper::VisitUnavailableAttr(const UnavailableAttr *UA) { |
585 | if (!UA->getMessage().empty()) |
586 | JOS.attribute(Key: "message", Contents: UA->getMessage()); |
587 | } |
588 | |
589 | void JSONNodeDumper::VisitSectionAttr(const SectionAttr *SA) { |
590 | JOS.attribute(Key: "section_name", Contents: SA->getName()); |
591 | } |
592 | |
593 | void JSONNodeDumper::VisitVisibilityAttr(const VisibilityAttr *VA) { |
594 | JOS.attribute("visibility", VisibilityAttr::ConvertVisibilityTypeToStr( |
595 | VA->getVisibility())); |
596 | } |
597 | |
598 | void JSONNodeDumper::VisitTLSModelAttr(const TLSModelAttr *TA) { |
599 | JOS.attribute(Key: "tls_model", Contents: TA->getModel()); |
600 | } |
601 | |
602 | void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) { |
603 | JOS.attribute(Key: "decl", Contents: createBareDeclRef(TT->getDecl())); |
604 | if (!TT->typeMatchesDecl()) |
605 | JOS.attribute(Key: "type", Contents: createQualType(QT: TT->desugar())); |
606 | } |
607 | |
608 | void JSONNodeDumper::VisitUsingType(const UsingType *TT) { |
609 | JOS.attribute(Key: "decl", Contents: createBareDeclRef(TT->getFoundDecl())); |
610 | if (!TT->typeMatchesDecl()) |
611 | JOS.attribute(Key: "type", Contents: createQualType(QT: TT->desugar())); |
612 | } |
613 | |
614 | void JSONNodeDumper::VisitFunctionType(const FunctionType *T) { |
615 | FunctionType::ExtInfo E = T->getExtInfo(); |
616 | attributeOnlyIfTrue(Key: "noreturn", Value: E.getNoReturn()); |
617 | attributeOnlyIfTrue(Key: "producesResult", Value: E.getProducesResult()); |
618 | if (E.getHasRegParm()) |
619 | JOS.attribute(Key: "regParm", Contents: E.getRegParm()); |
620 | JOS.attribute(Key: "cc", Contents: FunctionType::getNameForCallConv(CC: E.getCC())); |
621 | } |
622 | |
623 | void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) { |
624 | FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo(); |
625 | attributeOnlyIfTrue(Key: "trailingReturn", Value: E.HasTrailingReturn); |
626 | attributeOnlyIfTrue(Key: "const", Value: T->isConst()); |
627 | attributeOnlyIfTrue(Key: "volatile", Value: T->isVolatile()); |
628 | attributeOnlyIfTrue(Key: "restrict", Value: T->isRestrict()); |
629 | attributeOnlyIfTrue(Key: "variadic", Value: E.Variadic); |
630 | switch (E.RefQualifier) { |
631 | case RQ_LValue: JOS.attribute(Key: "refQualifier", Contents: "&"); break; |
632 | case RQ_RValue: JOS.attribute(Key: "refQualifier", Contents: "&&"); break; |
633 | case RQ_None: break; |
634 | } |
635 | switch (E.ExceptionSpec.Type) { |
636 | case EST_DynamicNone: |
637 | case EST_Dynamic: { |
638 | JOS.attribute(Key: "exceptionSpec", Contents: "throw"); |
639 | llvm::json::Array Types; |
640 | for (QualType QT : E.ExceptionSpec.Exceptions) |
641 | Types.push_back(createQualType(QT)); |
642 | JOS.attribute(Key: "exceptionTypes", Contents: std::move(Types)); |
643 | } break; |
644 | case EST_MSAny: |
645 | JOS.attribute(Key: "exceptionSpec", Contents: "throw"); |
646 | JOS.attribute(Key: "throwsAny", Contents: true); |
647 | break; |
648 | case EST_BasicNoexcept: |
649 | JOS.attribute(Key: "exceptionSpec", Contents: "noexcept"); |
650 | break; |
651 | case EST_NoexceptTrue: |
652 | case EST_NoexceptFalse: |
653 | JOS.attribute(Key: "exceptionSpec", Contents: "noexcept"); |
654 | JOS.attribute(Key: "conditionEvaluatesTo", |
655 | Contents: E.ExceptionSpec.Type == EST_NoexceptTrue); |
656 | //JOS.attributeWithCall("exceptionSpecExpr", |
657 | // [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); }); |
658 | break; |
659 | case EST_NoThrow: |
660 | JOS.attribute(Key: "exceptionSpec", Contents: "nothrow"); |
661 | break; |
662 | // FIXME: I cannot find a way to trigger these cases while dumping the AST. I |
663 | // suspect you can only run into them when executing an AST dump from within |
664 | // the debugger, which is not a use case we worry about for the JSON dumping |
665 | // feature. |
666 | case EST_DependentNoexcept: |
667 | case EST_Unevaluated: |
668 | case EST_Uninstantiated: |
669 | case EST_Unparsed: |
670 | case EST_None: break; |
671 | } |
672 | VisitFunctionType(T); |
673 | } |
674 | |
675 | void JSONNodeDumper::VisitRValueReferenceType(const ReferenceType *RT) { |
676 | attributeOnlyIfTrue(Key: "spelledAsLValue", Value: RT->isSpelledAsLValue()); |
677 | } |
678 | |
679 | void JSONNodeDumper::VisitArrayType(const ArrayType *AT) { |
680 | switch (AT->getSizeModifier()) { |
681 | case ArraySizeModifier::Star: |
682 | JOS.attribute(Key: "sizeModifier", Contents: "*"); |
683 | break; |
684 | case ArraySizeModifier::Static: |
685 | JOS.attribute(Key: "sizeModifier", Contents: "static"); |
686 | break; |
687 | case ArraySizeModifier::Normal: |
688 | break; |
689 | } |
690 | |
691 | std::string Str = AT->getIndexTypeQualifiers().getAsString(); |
692 | if (!Str.empty()) |
693 | JOS.attribute(Key: "indexTypeQualifiers", Contents: Str); |
694 | } |
695 | |
696 | void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) { |
697 | // FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a |
698 | // narrowing conversion to int64_t so it cannot be expressed. |
699 | JOS.attribute(Key: "size", Contents: CAT->getSExtSize()); |
700 | VisitArrayType(CAT); |
701 | } |
702 | |
703 | void JSONNodeDumper::VisitDependentSizedExtVectorType( |
704 | const DependentSizedExtVectorType *VT) { |
705 | JOS.attributeObject( |
706 | Key: "attrLoc", Contents: [VT, this] { writeSourceLocation(Loc: VT->getAttributeLoc()); }); |
707 | } |
708 | |
709 | void JSONNodeDumper::VisitVectorType(const VectorType *VT) { |
710 | JOS.attribute(Key: "numElements", Contents: VT->getNumElements()); |
711 | switch (VT->getVectorKind()) { |
712 | case VectorKind::Generic: |
713 | break; |
714 | case VectorKind::AltiVecVector: |
715 | JOS.attribute(Key: "vectorKind", Contents: "altivec"); |
716 | break; |
717 | case VectorKind::AltiVecPixel: |
718 | JOS.attribute(Key: "vectorKind", Contents: "altivec pixel"); |
719 | break; |
720 | case VectorKind::AltiVecBool: |
721 | JOS.attribute(Key: "vectorKind", Contents: "altivec bool"); |
722 | break; |
723 | case VectorKind::Neon: |
724 | JOS.attribute(Key: "vectorKind", Contents: "neon"); |
725 | break; |
726 | case VectorKind::NeonPoly: |
727 | JOS.attribute(Key: "vectorKind", Contents: "neon poly"); |
728 | break; |
729 | case VectorKind::SveFixedLengthData: |
730 | JOS.attribute(Key: "vectorKind", Contents: "fixed-length sve data vector"); |
731 | break; |
732 | case VectorKind::SveFixedLengthPredicate: |
733 | JOS.attribute(Key: "vectorKind", Contents: "fixed-length sve predicate vector"); |
734 | break; |
735 | case VectorKind::RVVFixedLengthData: |
736 | JOS.attribute(Key: "vectorKind", Contents: "fixed-length rvv data vector"); |
737 | break; |
738 | case VectorKind::RVVFixedLengthMask: |
739 | case VectorKind::RVVFixedLengthMask_1: |
740 | case VectorKind::RVVFixedLengthMask_2: |
741 | case VectorKind::RVVFixedLengthMask_4: |
742 | JOS.attribute(Key: "vectorKind", Contents: "fixed-length rvv mask vector"); |
743 | break; |
744 | } |
745 | } |
746 | |
747 | void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) { |
748 | JOS.attribute(Key: "decl", Contents: createBareDeclRef(UUT->getDecl())); |
749 | } |
750 | |
751 | void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) { |
752 | switch (UTT->getUTTKind()) { |
753 | #define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ |
754 | case UnaryTransformType::Enum: \ |
755 | JOS.attribute("transformKind", #Trait); \ |
756 | break; |
757 | #include "clang/Basic/TransformTypeTraits.def" |
758 | } |
759 | } |
760 | |
761 | void JSONNodeDumper::VisitTagType(const TagType *TT) { |
762 | JOS.attribute(Key: "decl", Contents: createBareDeclRef(TT->getDecl())); |
763 | } |
764 | |
765 | void JSONNodeDumper::VisitTemplateTypeParmType( |
766 | const TemplateTypeParmType *TTPT) { |
767 | JOS.attribute(Key: "depth", Contents: TTPT->getDepth()); |
768 | JOS.attribute(Key: "index", Contents: TTPT->getIndex()); |
769 | attributeOnlyIfTrue(Key: "isPack", Value: TTPT->isParameterPack()); |
770 | JOS.attribute(Key: "decl", Contents: createBareDeclRef(TTPT->getDecl())); |
771 | } |
772 | |
773 | void JSONNodeDumper::VisitSubstTemplateTypeParmType( |
774 | const SubstTemplateTypeParmType *STTPT) { |
775 | JOS.attribute(Key: "index", Contents: STTPT->getIndex()); |
776 | if (auto PackIndex = STTPT->getPackIndex()) |
777 | JOS.attribute(Key: "pack_index", Contents: *PackIndex); |
778 | } |
779 | |
780 | void JSONNodeDumper::VisitSubstTemplateTypeParmPackType( |
781 | const SubstTemplateTypeParmPackType *T) { |
782 | JOS.attribute(Key: "index", Contents: T->getIndex()); |
783 | } |
784 | |
785 | void JSONNodeDumper::VisitAutoType(const AutoType *AT) { |
786 | JOS.attribute(Key: "undeduced", Contents: !AT->isDeduced()); |
787 | switch (AT->getKeyword()) { |
788 | case AutoTypeKeyword::Auto: |
789 | JOS.attribute(Key: "typeKeyword", Contents: "auto"); |
790 | break; |
791 | case AutoTypeKeyword::DecltypeAuto: |
792 | JOS.attribute(Key: "typeKeyword", Contents: "decltype(auto)"); |
793 | break; |
794 | case AutoTypeKeyword::GNUAutoType: |
795 | JOS.attribute(Key: "typeKeyword", Contents: "__auto_type"); |
796 | break; |
797 | } |
798 | } |
799 | |
800 | void JSONNodeDumper::VisitTemplateSpecializationType( |
801 | const TemplateSpecializationType *TST) { |
802 | attributeOnlyIfTrue(Key: "isAlias", Value: TST->isTypeAlias()); |
803 | |
804 | std::string Str; |
805 | llvm::raw_string_ostream OS(Str); |
806 | TST->getTemplateName().print(OS, Policy: PrintPolicy); |
807 | JOS.attribute(Key: "templateName", Contents: Str); |
808 | } |
809 | |
810 | void JSONNodeDumper::VisitInjectedClassNameType( |
811 | const InjectedClassNameType *ICNT) { |
812 | JOS.attribute(Key: "decl", Contents: createBareDeclRef(ICNT->getDecl())); |
813 | } |
814 | |
815 | void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *OIT) { |
816 | JOS.attribute(Key: "decl", Contents: createBareDeclRef(OIT->getDecl())); |
817 | } |
818 | |
819 | void JSONNodeDumper::VisitPackExpansionType(const PackExpansionType *PET) { |
820 | if (UnsignedOrNone N = PET->getNumExpansions()) |
821 | JOS.attribute(Key: "numExpansions", Contents: *N); |
822 | } |
823 | |
824 | void JSONNodeDumper::VisitElaboratedType(const ElaboratedType *ET) { |
825 | if (const NestedNameSpecifier *NNS = ET->getQualifier()) { |
826 | std::string Str; |
827 | llvm::raw_string_ostream OS(Str); |
828 | NNS->print(OS, Policy: PrintPolicy, /*ResolveTemplateArgs*/ ResolveTemplateArguments: true); |
829 | JOS.attribute(Key: "qualifier", Contents: Str); |
830 | } |
831 | if (const TagDecl *TD = ET->getOwnedTagDecl()) |
832 | JOS.attribute(Key: "ownedTagDecl", Contents: createBareDeclRef(TD)); |
833 | } |
834 | |
835 | void JSONNodeDumper::VisitMacroQualifiedType(const MacroQualifiedType *MQT) { |
836 | JOS.attribute(Key: "macroName", Contents: MQT->getMacroIdentifier()->getName()); |
837 | } |
838 | |
839 | void JSONNodeDumper::VisitMemberPointerType(const MemberPointerType *MPT) { |
840 | attributeOnlyIfTrue(Key: "isData", Value: MPT->isMemberDataPointer()); |
841 | attributeOnlyIfTrue(Key: "isFunction", Value: MPT->isMemberFunctionPointer()); |
842 | } |
843 | |
844 | void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) { |
845 | if (ND && ND->getDeclName()) { |
846 | JOS.attribute(Key: "name", Contents: ND->getNameAsString()); |
847 | // FIXME: There are likely other contexts in which it makes no sense to ask |
848 | // for a mangled name. |
849 | if (isa<RequiresExprBodyDecl>(ND->getDeclContext())) |
850 | return; |
851 | |
852 | // If the declaration is dependent or is in a dependent context, then the |
853 | // mangling is unlikely to be meaningful (and in some cases may cause |
854 | // "don't know how to mangle this" assertion failures. |
855 | if (ND->isTemplated()) |
856 | return; |
857 | |
858 | // Mangled names are not meaningful for locals, and may not be well-defined |
859 | // in the case of VLAs. |
860 | auto *VD = dyn_cast<VarDecl>(Val: ND); |
861 | if (VD && VD->hasLocalStorage()) |
862 | return; |
863 | |
864 | // Do not mangle template deduction guides. |
865 | if (isa<CXXDeductionGuideDecl>(Val: ND)) |
866 | return; |
867 | |
868 | std::string MangledName = ASTNameGen.getName(ND); |
869 | if (!MangledName.empty()) |
870 | JOS.attribute(Key: "mangledName", Contents: MangledName); |
871 | } |
872 | } |
873 | |
874 | void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) { |
875 | VisitNamedDecl(TD); |
876 | JOS.attribute(Key: "type", Contents: createQualType(QT: TD->getUnderlyingType())); |
877 | } |
878 | |
879 | void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) { |
880 | VisitNamedDecl(TAD); |
881 | JOS.attribute(Key: "type", Contents: createQualType(QT: TAD->getUnderlyingType())); |
882 | } |
883 | |
884 | void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) { |
885 | VisitNamedDecl(ND); |
886 | attributeOnlyIfTrue(Key: "isInline", Value: ND->isInline()); |
887 | attributeOnlyIfTrue(Key: "isNested", Value: ND->isNested()); |
888 | if (!ND->isFirstDecl()) |
889 | JOS.attribute(Key: "originalNamespace", Contents: createBareDeclRef(D: ND->getFirstDecl())); |
890 | } |
891 | |
892 | void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) { |
893 | JOS.attribute(Key: "nominatedNamespace", |
894 | Contents: createBareDeclRef(UDD->getNominatedNamespace())); |
895 | } |
896 | |
897 | void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) { |
898 | VisitNamedDecl(NAD); |
899 | JOS.attribute(Key: "aliasedNamespace", |
900 | Contents: createBareDeclRef(NAD->getAliasedNamespace())); |
901 | } |
902 | |
903 | void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) { |
904 | std::string Name; |
905 | if (const NestedNameSpecifier *NNS = UD->getQualifier()) { |
906 | llvm::raw_string_ostream SOS(Name); |
907 | NNS->print(OS&: SOS, Policy: UD->getASTContext().getPrintingPolicy()); |
908 | } |
909 | Name += UD->getNameAsString(); |
910 | JOS.attribute(Key: "name", Contents: Name); |
911 | } |
912 | |
913 | void JSONNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *UED) { |
914 | JOS.attribute(Key: "target", Contents: createBareDeclRef(UED->getEnumDecl())); |
915 | } |
916 | |
917 | void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) { |
918 | JOS.attribute(Key: "target", Contents: createBareDeclRef(USD->getTargetDecl())); |
919 | } |
920 | |
921 | void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) { |
922 | VisitNamedDecl(VD); |
923 | JOS.attribute(Key: "type", Contents: createQualType(QT: VD->getType())); |
924 | if (const auto *P = dyn_cast<ParmVarDecl>(Val: VD)) |
925 | attributeOnlyIfTrue(Key: "explicitObjectParameter", |
926 | Value: P->isExplicitObjectParameter()); |
927 | |
928 | StorageClass SC = VD->getStorageClass(); |
929 | if (SC != SC_None) |
930 | JOS.attribute(Key: "storageClass", Contents: VarDecl::getStorageClassSpecifierString(SC)); |
931 | switch (VD->getTLSKind()) { |
932 | case VarDecl::TLS_Dynamic: JOS.attribute(Key: "tls", Contents: "dynamic"); break; |
933 | case VarDecl::TLS_Static: JOS.attribute(Key: "tls", Contents: "static"); break; |
934 | case VarDecl::TLS_None: break; |
935 | } |
936 | attributeOnlyIfTrue(Key: "nrvo", Value: VD->isNRVOVariable()); |
937 | attributeOnlyIfTrue(Key: "inline", Value: VD->isInline()); |
938 | attributeOnlyIfTrue(Key: "constexpr", Value: VD->isConstexpr()); |
939 | attributeOnlyIfTrue(Key: "modulePrivate", Value: VD->isModulePrivate()); |
940 | if (VD->hasInit()) { |
941 | switch (VD->getInitStyle()) { |
942 | case VarDecl::CInit: JOS.attribute(Key: "init", Contents: "c"); break; |
943 | case VarDecl::CallInit: JOS.attribute(Key: "init", Contents: "call"); break; |
944 | case VarDecl::ListInit: JOS.attribute(Key: "init", Contents: "list"); break; |
945 | case VarDecl::ParenListInit: |
946 | JOS.attribute(Key: "init", Contents: "paren-list"); |
947 | break; |
948 | } |
949 | } |
950 | attributeOnlyIfTrue(Key: "isParameterPack", Value: VD->isParameterPack()); |
951 | } |
952 | |
953 | void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) { |
954 | VisitNamedDecl(FD); |
955 | JOS.attribute(Key: "type", Contents: createQualType(QT: FD->getType())); |
956 | attributeOnlyIfTrue(Key: "mutable", Value: FD->isMutable()); |
957 | attributeOnlyIfTrue(Key: "modulePrivate", Value: FD->isModulePrivate()); |
958 | attributeOnlyIfTrue(Key: "isBitfield", Value: FD->isBitField()); |
959 | attributeOnlyIfTrue(Key: "hasInClassInitializer", Value: FD->hasInClassInitializer()); |
960 | } |
961 | |
962 | void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) { |
963 | VisitNamedDecl(FD); |
964 | JOS.attribute(Key: "type", Contents: createQualType(QT: FD->getType())); |
965 | StorageClass SC = FD->getStorageClass(); |
966 | if (SC != SC_None) |
967 | JOS.attribute(Key: "storageClass", Contents: VarDecl::getStorageClassSpecifierString(SC)); |
968 | attributeOnlyIfTrue(Key: "inline", Value: FD->isInlineSpecified()); |
969 | attributeOnlyIfTrue(Key: "virtual", Value: FD->isVirtualAsWritten()); |
970 | attributeOnlyIfTrue(Key: "pure", Value: FD->isPureVirtual()); |
971 | attributeOnlyIfTrue(Key: "explicitlyDeleted", Value: FD->isDeletedAsWritten()); |
972 | attributeOnlyIfTrue(Key: "constexpr", Value: FD->isConstexpr()); |
973 | attributeOnlyIfTrue(Key: "variadic", Value: FD->isVariadic()); |
974 | attributeOnlyIfTrue(Key: "immediate", Value: FD->isImmediateFunction()); |
975 | |
976 | if (FD->isDefaulted()) |
977 | JOS.attribute(Key: "explicitlyDefaulted", |
978 | Contents: FD->isDeleted() ? "deleted": "default"); |
979 | |
980 | if (StringLiteral *Msg = FD->getDeletedMessage()) |
981 | JOS.attribute(Key: "deletedMessage", Contents: Msg->getString()); |
982 | } |
983 | |
984 | void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) { |
985 | VisitNamedDecl(ED); |
986 | if (ED->isFixed()) |
987 | JOS.attribute(Key: "fixedUnderlyingType", Contents: createQualType(QT: ED->getIntegerType())); |
988 | if (ED->isScoped()) |
989 | JOS.attribute(Key: "scopedEnumTag", |
990 | Contents: ED->isScopedUsingClassTag() ? "class": "struct"); |
991 | } |
992 | void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) { |
993 | VisitNamedDecl(ECD); |
994 | JOS.attribute(Key: "type", Contents: createQualType(QT: ECD->getType())); |
995 | } |
996 | |
997 | void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) { |
998 | VisitNamedDecl(RD); |
999 | JOS.attribute(Key: "tagUsed", Contents: RD->getKindName()); |
1000 | attributeOnlyIfTrue(Key: "completeDefinition", Value: RD->isCompleteDefinition()); |
1001 | } |
1002 | void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) { |
1003 | VisitRecordDecl(RD); |
1004 | |
1005 | if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Val: RD)) { |
1006 | if (CTSD->hasStrictPackMatch()) |
1007 | JOS.attribute(Key: "strict-pack-match", Contents: true); |
1008 | } |
1009 | |
1010 | // All other information requires a complete definition. |
1011 | if (!RD->isCompleteDefinition()) |
1012 | return; |
1013 | |
1014 | JOS.attribute(Key: "definitionData", Contents: createCXXRecordDefinitionData(RD)); |
1015 | if (RD->getNumBases()) { |
1016 | JOS.attributeArray(Key: "bases", Contents: [this, RD] { |
1017 | for (const auto &Spec : RD->bases()) |
1018 | JOS.value(V: createCXXBaseSpecifier(BS: Spec)); |
1019 | }); |
1020 | } |
1021 | } |
1022 | |
1023 | void JSONNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) { |
1024 | VisitNamedDecl(D); |
1025 | JOS.attribute(Key: "bufferKind", Contents: D->isCBuffer() ? "cbuffer": "tbuffer"); |
1026 | } |
1027 | |
1028 | void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { |
1029 | VisitNamedDecl(D); |
1030 | JOS.attribute(Key: "tagUsed", Contents: D->wasDeclaredWithTypename() ? "typename": "class"); |
1031 | JOS.attribute(Key: "depth", Contents: D->getDepth()); |
1032 | JOS.attribute(Key: "index", Contents: D->getIndex()); |
1033 | attributeOnlyIfTrue(Key: "isParameterPack", Value: D->isParameterPack()); |
1034 | |
1035 | if (D->hasDefaultArgument()) |
1036 | JOS.attributeObject(Key: "defaultArg", Contents: [=] { |
1037 | Visit(D->getDefaultArgument().getArgument(), SourceRange(), |
1038 | D->getDefaultArgStorage().getInheritedFrom(), |
1039 | D->defaultArgumentWasInherited() ? "inherited from": "previous"); |
1040 | }); |
1041 | } |
1042 | |
1043 | void JSONNodeDumper::VisitNonTypeTemplateParmDecl( |
1044 | const NonTypeTemplateParmDecl *D) { |
1045 | VisitNamedDecl(D); |
1046 | JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType())); |
1047 | JOS.attribute(Key: "depth", Contents: D->getDepth()); |
1048 | JOS.attribute(Key: "index", Contents: D->getIndex()); |
1049 | attributeOnlyIfTrue(Key: "isParameterPack", Value: D->isParameterPack()); |
1050 | |
1051 | if (D->hasDefaultArgument()) |
1052 | JOS.attributeObject(Key: "defaultArg", Contents: [=] { |
1053 | Visit(D->getDefaultArgument().getArgument(), SourceRange(), |
1054 | D->getDefaultArgStorage().getInheritedFrom(), |
1055 | D->defaultArgumentWasInherited() ? "inherited from": "previous"); |
1056 | }); |
1057 | } |
1058 | |
1059 | void JSONNodeDumper::VisitTemplateTemplateParmDecl( |
1060 | const TemplateTemplateParmDecl *D) { |
1061 | VisitNamedDecl(D); |
1062 | JOS.attribute(Key: "depth", Contents: D->getDepth()); |
1063 | JOS.attribute(Key: "index", Contents: D->getIndex()); |
1064 | attributeOnlyIfTrue(Key: "isParameterPack", Value: D->isParameterPack()); |
1065 | |
1066 | if (D->hasDefaultArgument()) |
1067 | JOS.attributeObject(Key: "defaultArg", Contents: [=] { |
1068 | const auto *InheritedFrom = D->getDefaultArgStorage().getInheritedFrom(); |
1069 | Visit(D->getDefaultArgument().getArgument(), |
1070 | InheritedFrom ? InheritedFrom->getSourceRange() : SourceLocation{}, |
1071 | InheritedFrom, |
1072 | D->defaultArgumentWasInherited() ? "inherited from": "previous"); |
1073 | }); |
1074 | } |
1075 | |
1076 | void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) { |
1077 | StringRef Lang; |
1078 | switch (LSD->getLanguage()) { |
1079 | case LinkageSpecLanguageIDs::C: |
1080 | Lang = "C"; |
1081 | break; |
1082 | case LinkageSpecLanguageIDs::CXX: |
1083 | Lang = "C++"; |
1084 | break; |
1085 | } |
1086 | JOS.attribute(Key: "language", Contents: Lang); |
1087 | attributeOnlyIfTrue(Key: "hasBraces", Value: LSD->hasBraces()); |
1088 | } |
1089 | |
1090 | void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) { |
1091 | JOS.attribute(Key: "access", Contents: createAccessSpecifier(AS: ASD->getAccess())); |
1092 | } |
1093 | |
1094 | void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) { |
1095 | if (const TypeSourceInfo *T = FD->getFriendType()) |
1096 | JOS.attribute(Key: "type", Contents: createQualType(QT: T->getType())); |
1097 | attributeOnlyIfTrue(Key: "isPackExpansion", Value: FD->isPackExpansion()); |
1098 | } |
1099 | |
1100 | void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { |
1101 | VisitNamedDecl(D); |
1102 | JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType())); |
1103 | attributeOnlyIfTrue(Key: "synthesized", Value: D->getSynthesize()); |
1104 | switch (D->getAccessControl()) { |
1105 | case ObjCIvarDecl::None: JOS.attribute(Key: "access", Contents: "none"); break; |
1106 | case ObjCIvarDecl::Private: JOS.attribute(Key: "access", Contents: "private"); break; |
1107 | case ObjCIvarDecl::Protected: JOS.attribute(Key: "access", Contents: "protected"); break; |
1108 | case ObjCIvarDecl::Public: JOS.attribute(Key: "access", Contents: "public"); break; |
1109 | case ObjCIvarDecl::Package: JOS.attribute(Key: "access", Contents: "package"); break; |
1110 | } |
1111 | } |
1112 | |
1113 | void JSONNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { |
1114 | VisitNamedDecl(D); |
1115 | JOS.attribute(Key: "returnType", Contents: createQualType(QT: D->getReturnType())); |
1116 | JOS.attribute(Key: "instance", Contents: D->isInstanceMethod()); |
1117 | attributeOnlyIfTrue(Key: "variadic", Value: D->isVariadic()); |
1118 | } |
1119 | |
1120 | void JSONNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) { |
1121 | VisitNamedDecl(D); |
1122 | JOS.attribute(Key: "type", Contents: createQualType(QT: D->getUnderlyingType())); |
1123 | attributeOnlyIfTrue(Key: "bounded", Value: D->hasExplicitBound()); |
1124 | switch (D->getVariance()) { |
1125 | case ObjCTypeParamVariance::Invariant: |
1126 | break; |
1127 | case ObjCTypeParamVariance::Covariant: |
1128 | JOS.attribute(Key: "variance", Contents: "covariant"); |
1129 | break; |
1130 | case ObjCTypeParamVariance::Contravariant: |
1131 | JOS.attribute(Key: "variance", Contents: "contravariant"); |
1132 | break; |
1133 | } |
1134 | } |
1135 | |
1136 | void JSONNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { |
1137 | VisitNamedDecl(D); |
1138 | JOS.attribute(Key: "interface", Contents: createBareDeclRef(D->getClassInterface())); |
1139 | JOS.attribute(Key: "implementation", Contents: createBareDeclRef(D->getImplementation())); |
1140 | |
1141 | llvm::json::Array Protocols; |
1142 | for (const auto* P : D->protocols()) |
1143 | Protocols.push_back(E: createBareDeclRef(P)); |
1144 | if (!Protocols.empty()) |
1145 | JOS.attribute(Key: "protocols", Contents: std::move(Protocols)); |
1146 | } |
1147 | |
1148 | void JSONNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { |
1149 | VisitNamedDecl(D); |
1150 | JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface())); |
1151 | JOS.attribute(Key: "categoryDecl", Contents: createBareDeclRef(D->getCategoryDecl())); |
1152 | } |
1153 | |
1154 | void JSONNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { |
1155 | VisitNamedDecl(D); |
1156 | |
1157 | llvm::json::Array Protocols; |
1158 | for (const auto *P : D->protocols()) |
1159 | Protocols.push_back(E: createBareDeclRef(P)); |
1160 | if (!Protocols.empty()) |
1161 | JOS.attribute(Key: "protocols", Contents: std::move(Protocols)); |
1162 | } |
1163 | |
1164 | void JSONNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { |
1165 | VisitNamedDecl(D); |
1166 | JOS.attribute(Key: "super", Contents: createBareDeclRef(D->getSuperClass())); |
1167 | JOS.attribute(Key: "implementation", Contents: createBareDeclRef(D->getImplementation())); |
1168 | |
1169 | llvm::json::Array Protocols; |
1170 | for (const auto* P : D->protocols()) |
1171 | Protocols.push_back(E: createBareDeclRef(P)); |
1172 | if (!Protocols.empty()) |
1173 | JOS.attribute(Key: "protocols", Contents: std::move(Protocols)); |
1174 | } |
1175 | |
1176 | void JSONNodeDumper::VisitObjCImplementationDecl( |
1177 | const ObjCImplementationDecl *D) { |
1178 | VisitNamedDecl(D); |
1179 | JOS.attribute(Key: "super", Contents: createBareDeclRef(D->getSuperClass())); |
1180 | JOS.attribute(Key: "interface", Contents: createBareDeclRef(D: D->getClassInterface())); |
1181 | } |
1182 | |
1183 | void JSONNodeDumper::VisitObjCCompatibleAliasDecl( |
1184 | const ObjCCompatibleAliasDecl *D) { |
1185 | VisitNamedDecl(D); |
1186 | JOS.attribute(Key: "interface", Contents: createBareDeclRef(D->getClassInterface())); |
1187 | } |
1188 | |
1189 | void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { |
1190 | VisitNamedDecl(D); |
1191 | JOS.attribute(Key: "type", Contents: createQualType(QT: D->getType())); |
1192 | |
1193 | switch (D->getPropertyImplementation()) { |
1194 | case ObjCPropertyDecl::None: break; |
1195 | case ObjCPropertyDecl::Required: JOS.attribute(Key: "control", Contents: "required"); break; |
1196 | case ObjCPropertyDecl::Optional: JOS.attribute(Key: "control", Contents: "optional"); break; |
1197 | } |
1198 | |
1199 | ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes(); |
1200 | if (Attrs != ObjCPropertyAttribute::kind_noattr) { |
1201 | if (Attrs & ObjCPropertyAttribute::kind_getter) |
1202 | JOS.attribute(Key: "getter", Contents: createBareDeclRef(D->getGetterMethodDecl())); |
1203 | if (Attrs & ObjCPropertyAttribute::kind_setter) |
1204 | JOS.attribute(Key: "setter", Contents: createBareDeclRef(D->getSetterMethodDecl())); |
1205 | attributeOnlyIfTrue(Key: "readonly", |
1206 | Value: Attrs & ObjCPropertyAttribute::kind_readonly); |
1207 | attributeOnlyIfTrue(Key: "assign", Value: Attrs & ObjCPropertyAttribute::kind_assign); |
1208 | attributeOnlyIfTrue(Key: "readwrite", |
1209 | Value: Attrs & ObjCPropertyAttribute::kind_readwrite); |
1210 | attributeOnlyIfTrue(Key: "retain", Value: Attrs & ObjCPropertyAttribute::kind_retain); |
1211 | attributeOnlyIfTrue(Key: "copy", Value: Attrs & ObjCPropertyAttribute::kind_copy); |
1212 | attributeOnlyIfTrue(Key: "nonatomic", |
1213 | Value: Attrs & ObjCPropertyAttribute::kind_nonatomic); |
1214 | attributeOnlyIfTrue(Key: "atomic", Value: Attrs & ObjCPropertyAttribute::kind_atomic); |
1215 | attributeOnlyIfTrue(Key: "weak", Value: Attrs & ObjCPropertyAttribute::kind_weak); |
1216 | attributeOnlyIfTrue(Key: "strong", Value: Attrs & ObjCPropertyAttribute::kind_strong); |
1217 | attributeOnlyIfTrue(Key: "unsafe_unretained", |
1218 | Value: Attrs & ObjCPropertyAttribute::kind_unsafe_unretained); |
1219 | attributeOnlyIfTrue(Key: "class", Value: Attrs & ObjCPropertyAttribute::kind_class); |
1220 | attributeOnlyIfTrue(Key: "direct", Value: Attrs & ObjCPropertyAttribute::kind_direct); |
1221 | attributeOnlyIfTrue(Key: "nullability", |
1222 | Value: Attrs & ObjCPropertyAttribute::kind_nullability); |
1223 | attributeOnlyIfTrue(Key: "null_resettable", |
1224 | Value: Attrs & ObjCPropertyAttribute::kind_null_resettable); |
1225 | } |
1226 | } |
1227 | |
1228 | void JSONNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { |
1229 | VisitNamedDecl(D->getPropertyDecl()); |
1230 | JOS.attribute(Key: "implKind", Contents: D->getPropertyImplementation() == |
1231 | ObjCPropertyImplDecl::Synthesize |
1232 | ? "synthesize" |
1233 | : "dynamic"); |
1234 | JOS.attribute(Key: "propertyDecl", Contents: createBareDeclRef(D->getPropertyDecl())); |
1235 | JOS.attribute(Key: "ivarDecl", Contents: createBareDeclRef(D->getPropertyIvarDecl())); |
1236 | } |
1237 | |
1238 | void JSONNodeDumper::VisitBlockDecl(const BlockDecl *D) { |
1239 | attributeOnlyIfTrue(Key: "variadic", Value: D->isVariadic()); |
1240 | attributeOnlyIfTrue(Key: "capturesThis", Value: D->capturesCXXThis()); |
1241 | } |
1242 | |
1243 | void JSONNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) { |
1244 | JOS.attribute(Key: "name", Contents: AE->getOpAsString()); |
1245 | } |
1246 | |
1247 | void JSONNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE) { |
1248 | JOS.attribute(Key: "encodedType", Contents: createQualType(QT: OEE->getEncodedType())); |
1249 | } |
1250 | |
1251 | void JSONNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *OME) { |
1252 | std::string Str; |
1253 | llvm::raw_string_ostream OS(Str); |
1254 | |
1255 | OME->getSelector().print(OS); |
1256 | JOS.attribute(Key: "selector", Contents: Str); |
1257 | |
1258 | switch (OME->getReceiverKind()) { |
1259 | case ObjCMessageExpr::Instance: |
1260 | JOS.attribute(Key: "receiverKind", Contents: "instance"); |
1261 | break; |
1262 | case ObjCMessageExpr::Class: |
1263 | JOS.attribute(Key: "receiverKind", Contents: "class"); |
1264 | JOS.attribute(Key: "classType", Contents: createQualType(QT: OME->getClassReceiver())); |
1265 | break; |
1266 | case ObjCMessageExpr::SuperInstance: |
1267 | JOS.attribute(Key: "receiverKind", Contents: "super (instance)"); |
1268 | JOS.attribute(Key: "superType", Contents: createQualType(QT: OME->getSuperType())); |
1269 | break; |
1270 | case ObjCMessageExpr::SuperClass: |
1271 | JOS.attribute(Key: "receiverKind", Contents: "super (class)"); |
1272 | JOS.attribute(Key: "superType", Contents: createQualType(QT: OME->getSuperType())); |
1273 | break; |
1274 | } |
1275 | |
1276 | QualType CallReturnTy = OME->getCallReturnType(Ctx); |
1277 | if (OME->getType() != CallReturnTy) |
1278 | JOS.attribute(Key: "callReturnType", Contents: createQualType(QT: CallReturnTy)); |
1279 | } |
1280 | |
1281 | void JSONNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE) { |
1282 | if (const ObjCMethodDecl *MD = OBE->getBoxingMethod()) { |
1283 | std::string Str; |
1284 | llvm::raw_string_ostream OS(Str); |
1285 | |
1286 | MD->getSelector().print(OS); |
1287 | JOS.attribute(Key: "selector", Contents: Str); |
1288 | } |
1289 | } |
1290 | |
1291 | void JSONNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE) { |
1292 | std::string Str; |
1293 | llvm::raw_string_ostream OS(Str); |
1294 | |
1295 | OSE->getSelector().print(OS); |
1296 | JOS.attribute(Key: "selector", Contents: Str); |
1297 | } |
1298 | |
1299 | void JSONNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) { |
1300 | JOS.attribute(Key: "protocol", Contents: createBareDeclRef(OPE->getProtocol())); |
1301 | } |
1302 | |
1303 | void JSONNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) { |
1304 | if (OPRE->isImplicitProperty()) { |
1305 | JOS.attribute(Key: "propertyKind", Contents: "implicit"); |
1306 | if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertyGetter()) |
1307 | JOS.attribute(Key: "getter", Contents: createBareDeclRef(MD)); |
1308 | if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertySetter()) |
1309 | JOS.attribute(Key: "setter", Contents: createBareDeclRef(MD)); |
1310 | } else { |
1311 | JOS.attribute(Key: "propertyKind", Contents: "explicit"); |
1312 | JOS.attribute(Key: "property", Contents: createBareDeclRef(OPRE->getExplicitProperty())); |
1313 | } |
1314 | |
1315 | attributeOnlyIfTrue(Key: "isSuperReceiver", Value: OPRE->isSuperReceiver()); |
1316 | attributeOnlyIfTrue(Key: "isMessagingGetter", Value: OPRE->isMessagingGetter()); |
1317 | attributeOnlyIfTrue(Key: "isMessagingSetter", Value: OPRE->isMessagingSetter()); |
1318 | } |
1319 | |
1320 | void JSONNodeDumper::VisitObjCSubscriptRefExpr( |
1321 | const ObjCSubscriptRefExpr *OSRE) { |
1322 | JOS.attribute(Key: "subscriptKind", |
1323 | Contents: OSRE->isArraySubscriptRefExpr() ? "array": "dictionary"); |
1324 | |
1325 | if (const ObjCMethodDecl *MD = OSRE->getAtIndexMethodDecl()) |
1326 | JOS.attribute(Key: "getter", Contents: createBareDeclRef(MD)); |
1327 | if (const ObjCMethodDecl *MD = OSRE->setAtIndexMethodDecl()) |
1328 | JOS.attribute(Key: "setter", Contents: createBareDeclRef(MD)); |
1329 | } |
1330 | |
1331 | void JSONNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) { |
1332 | JOS.attribute(Key: "decl", Contents: createBareDeclRef(OIRE->getDecl())); |
1333 | attributeOnlyIfTrue(Key: "isFreeIvar", Value: OIRE->isFreeIvar()); |
1334 | JOS.attribute(Key: "isArrow", Contents: OIRE->isArrow()); |
1335 | } |
1336 | |
1337 | void JSONNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE) { |
1338 | JOS.attribute(Key: "value", Contents: OBLE->getValue() ? "__objc_yes": "__objc_no"); |
1339 | } |
1340 | |
1341 | void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) { |
1342 | JOS.attribute(Key: "referencedDecl", Contents: createBareDeclRef(DRE->getDecl())); |
1343 | if (DRE->getDecl() != DRE->getFoundDecl()) |
1344 | JOS.attribute(Key: "foundReferencedDecl", |
1345 | Contents: createBareDeclRef(DRE->getFoundDecl())); |
1346 | switch (DRE->isNonOdrUse()) { |
1347 | case NOUR_None: break; |
1348 | case NOUR_Unevaluated: JOS.attribute(Key: "nonOdrUseReason", Contents: "unevaluated"); break; |
1349 | case NOUR_Constant: JOS.attribute(Key: "nonOdrUseReason", Contents: "constant"); break; |
1350 | case NOUR_Discarded: JOS.attribute(Key: "nonOdrUseReason", Contents: "discarded"); break; |
1351 | } |
1352 | attributeOnlyIfTrue(Key: "isImmediateEscalating", Value: DRE->isImmediateEscalating()); |
1353 | } |
1354 | |
1355 | void JSONNodeDumper::VisitSYCLUniqueStableNameExpr( |
1356 | const SYCLUniqueStableNameExpr *E) { |
1357 | JOS.attribute(Key: "typeSourceInfo", |
1358 | Contents: createQualType(QT: E->getTypeSourceInfo()->getType())); |
1359 | } |
1360 | |
1361 | void JSONNodeDumper::VisitOpenACCAsteriskSizeExpr( |
1362 | const OpenACCAsteriskSizeExpr *E) {} |
1363 | |
1364 | void JSONNodeDumper::VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D) {} |
1365 | void JSONNodeDumper::VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D) {} |
1366 | |
1367 | void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) { |
1368 | JOS.attribute(Key: "name", Contents: PredefinedExpr::getIdentKindName(IK: PE->getIdentKind())); |
1369 | } |
1370 | |
1371 | void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) { |
1372 | JOS.attribute(Key: "isPostfix", Contents: UO->isPostfix()); |
1373 | JOS.attribute(Key: "opcode", Contents: UnaryOperator::getOpcodeStr(Op: UO->getOpcode())); |
1374 | if (!UO->canOverflow()) |
1375 | JOS.attribute(Key: "canOverflow", Contents: false); |
1376 | } |
1377 | |
1378 | void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) { |
1379 | JOS.attribute(Key: "opcode", Contents: BinaryOperator::getOpcodeStr(Op: BO->getOpcode())); |
1380 | } |
1381 | |
1382 | void JSONNodeDumper::VisitCompoundAssignOperator( |
1383 | const CompoundAssignOperator *CAO) { |
1384 | VisitBinaryOperator(CAO); |
1385 | JOS.attribute(Key: "computeLHSType", Contents: createQualType(QT: CAO->getComputationLHSType())); |
1386 | JOS.attribute(Key: "computeResultType", |
1387 | Contents: createQualType(QT: CAO->getComputationResultType())); |
1388 | } |
1389 | |
1390 | void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) { |
1391 | // Note, we always write this Boolean field because the information it conveys |
1392 | // is critical to understanding the AST node. |
1393 | ValueDecl *VD = ME->getMemberDecl(); |
1394 | JOS.attribute(Key: "name", Contents: VD && VD->getDeclName() ? VD->getNameAsString() : ""); |
1395 | JOS.attribute(Key: "isArrow", Contents: ME->isArrow()); |
1396 | JOS.attribute(Key: "referencedMemberDecl", Contents: createPointerRepresentation(Ptr: VD)); |
1397 | switch (ME->isNonOdrUse()) { |
1398 | case NOUR_None: break; |
1399 | case NOUR_Unevaluated: JOS.attribute(Key: "nonOdrUseReason", Contents: "unevaluated"); break; |
1400 | case NOUR_Constant: JOS.attribute(Key: "nonOdrUseReason", Contents: "constant"); break; |
1401 | case NOUR_Discarded: JOS.attribute(Key: "nonOdrUseReason", Contents: "discarded"); break; |
1402 | } |
1403 | } |
1404 | |
1405 | void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) { |
1406 | attributeOnlyIfTrue(Key: "isGlobal", Value: NE->isGlobalNew()); |
1407 | attributeOnlyIfTrue(Key: "isArray", Value: NE->isArray()); |
1408 | attributeOnlyIfTrue(Key: "isPlacement", Value: NE->getNumPlacementArgs() != 0); |
1409 | switch (NE->getInitializationStyle()) { |
1410 | case CXXNewInitializationStyle::None: |
1411 | break; |
1412 | case CXXNewInitializationStyle::Parens: |
1413 | JOS.attribute(Key: "initStyle", Contents: "call"); |
1414 | break; |
1415 | case CXXNewInitializationStyle::Braces: |
1416 | JOS.attribute(Key: "initStyle", Contents: "list"); |
1417 | break; |
1418 | } |
1419 | if (const FunctionDecl *FD = NE->getOperatorNew()) |
1420 | JOS.attribute(Key: "operatorNewDecl", Contents: createBareDeclRef(FD)); |
1421 | if (const FunctionDecl *FD = NE->getOperatorDelete()) |
1422 | JOS.attribute(Key: "operatorDeleteDecl", Contents: createBareDeclRef(FD)); |
1423 | } |
1424 | void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) { |
1425 | attributeOnlyIfTrue(Key: "isGlobal", Value: DE->isGlobalDelete()); |
1426 | attributeOnlyIfTrue(Key: "isArray", Value: DE->isArrayForm()); |
1427 | attributeOnlyIfTrue(Key: "isArrayAsWritten", Value: DE->isArrayFormAsWritten()); |
1428 | if (const FunctionDecl *FD = DE->getOperatorDelete()) |
1429 | JOS.attribute(Key: "operatorDeleteDecl", Contents: createBareDeclRef(FD)); |
1430 | } |
1431 | |
1432 | void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) { |
1433 | attributeOnlyIfTrue(Key: "implicit", Value: TE->isImplicit()); |
1434 | } |
1435 | |
1436 | void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) { |
1437 | JOS.attribute(Key: "castKind", Contents: CE->getCastKindName()); |
1438 | llvm::json::Array Path = createCastPath(C: CE); |
1439 | if (!Path.empty()) |
1440 | JOS.attribute(Key: "path", Contents: std::move(Path)); |
1441 | // FIXME: This may not be useful information as it can be obtusely gleaned |
1442 | // from the inner[] array. |
1443 | if (const NamedDecl *ND = CE->getConversionFunction()) |
1444 | JOS.attribute(Key: "conversionFunc", Contents: createBareDeclRef(ND)); |
1445 | } |
1446 | |
1447 | void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) { |
1448 | VisitCastExpr(ICE); |
1449 | attributeOnlyIfTrue(Key: "isPartOfExplicitCast", Value: ICE->isPartOfExplicitCast()); |
1450 | } |
1451 | |
1452 | void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) { |
1453 | attributeOnlyIfTrue(Key: "adl", Value: CE->usesADL()); |
1454 | } |
1455 | |
1456 | void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr( |
1457 | const UnaryExprOrTypeTraitExpr *TTE) { |
1458 | JOS.attribute(Key: "name", Contents: getTraitSpelling(T: TTE->getKind())); |
1459 | if (TTE->isArgumentType()) |
1460 | JOS.attribute(Key: "argType", Contents: createQualType(QT: TTE->getArgumentType())); |
1461 | } |
1462 | |
1463 | void JSONNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE) { |
1464 | VisitNamedDecl(ND: SOPE->getPack()); |
1465 | } |
1466 | |
1467 | void JSONNodeDumper::VisitUnresolvedLookupExpr( |
1468 | const UnresolvedLookupExpr *ULE) { |
1469 | JOS.attribute(Key: "usesADL", Contents: ULE->requiresADL()); |
1470 | JOS.attribute(Key: "name", Contents: ULE->getName().getAsString()); |
1471 | |
1472 | JOS.attributeArray(Key: "lookups", Contents: [this, ULE] { |
1473 | for (const NamedDecl *D : ULE->decls()) |
1474 | JOS.value(createBareDeclRef(D)); |
1475 | }); |
1476 | } |
1477 | |
1478 | void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) { |
1479 | JOS.attribute(Key: "name", Contents: ALE->getLabel()->getName()); |
1480 | JOS.attribute(Key: "labelDeclId", Contents: createPointerRepresentation(Ptr: ALE->getLabel())); |
1481 | } |
1482 | |
1483 | void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) { |
1484 | if (CTE->isTypeOperand()) { |
1485 | QualType Adjusted = CTE->getTypeOperand(Context: Ctx); |
1486 | QualType Unadjusted = CTE->getTypeOperandSourceInfo()->getType(); |
1487 | JOS.attribute(Key: "typeArg", Contents: createQualType(QT: Unadjusted)); |
1488 | if (Adjusted != Unadjusted) |
1489 | JOS.attribute(Key: "adjustedTypeArg", Contents: createQualType(QT: Adjusted)); |
1490 | } |
1491 | } |
1492 | |
1493 | void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) { |
1494 | if (CE->getResultAPValueKind() != APValue::None) |
1495 | Visit(CE->getAPValueResult(), CE->getType()); |
1496 | } |
1497 | |
1498 | void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) { |
1499 | if (const FieldDecl *FD = ILE->getInitializedFieldInUnion()) |
1500 | JOS.attribute(Key: "field", Contents: createBareDeclRef(FD)); |
1501 | } |
1502 | |
1503 | void JSONNodeDumper::VisitGenericSelectionExpr( |
1504 | const GenericSelectionExpr *GSE) { |
1505 | attributeOnlyIfTrue(Key: "resultDependent", Value: GSE->isResultDependent()); |
1506 | } |
1507 | |
1508 | void JSONNodeDumper::VisitCXXUnresolvedConstructExpr( |
1509 | const CXXUnresolvedConstructExpr *UCE) { |
1510 | if (UCE->getType() != UCE->getTypeAsWritten()) |
1511 | JOS.attribute(Key: "typeAsWritten", Contents: createQualType(QT: UCE->getTypeAsWritten())); |
1512 | attributeOnlyIfTrue(Key: "list", Value: UCE->isListInitialization()); |
1513 | } |
1514 | |
1515 | void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *CE) { |
1516 | CXXConstructorDecl *Ctor = CE->getConstructor(); |
1517 | JOS.attribute(Key: "ctorType", Contents: createQualType(QT: Ctor->getType())); |
1518 | attributeOnlyIfTrue(Key: "elidable", Value: CE->isElidable()); |
1519 | attributeOnlyIfTrue(Key: "list", Value: CE->isListInitialization()); |
1520 | attributeOnlyIfTrue(Key: "initializer_list", Value: CE->isStdInitListInitialization()); |
1521 | attributeOnlyIfTrue(Key: "zeroing", Value: CE->requiresZeroInitialization()); |
1522 | attributeOnlyIfTrue(Key: "hadMultipleCandidates", Value: CE->hadMultipleCandidates()); |
1523 | attributeOnlyIfTrue(Key: "isImmediateEscalating", Value: CE->isImmediateEscalating()); |
1524 | |
1525 | switch (CE->getConstructionKind()) { |
1526 | case CXXConstructionKind::Complete: |
1527 | JOS.attribute(Key: "constructionKind", Contents: "complete"); |
1528 | break; |
1529 | case CXXConstructionKind::Delegating: |
1530 | JOS.attribute(Key: "constructionKind", Contents: "delegating"); |
1531 | break; |
1532 | case CXXConstructionKind::NonVirtualBase: |
1533 | JOS.attribute(Key: "constructionKind", Contents: "non-virtual base"); |
1534 | break; |
1535 | case CXXConstructionKind::VirtualBase: |
1536 | JOS.attribute(Key: "constructionKind", Contents: "virtual base"); |
1537 | break; |
1538 | } |
1539 | } |
1540 | |
1541 | void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *EWC) { |
1542 | attributeOnlyIfTrue(Key: "cleanupsHaveSideEffects", |
1543 | Value: EWC->cleanupsHaveSideEffects()); |
1544 | if (EWC->getNumObjects()) { |
1545 | JOS.attributeArray(Key: "cleanups", Contents: [this, EWC] { |
1546 | for (const ExprWithCleanups::CleanupObject &CO : EWC->getObjects()) |
1547 | if (auto *BD = dyn_cast<BlockDecl *>(Val: CO)) { |
1548 | JOS.value(V: createBareDeclRef(BD)); |
1549 | } else if (auto *CLE = dyn_cast<CompoundLiteralExpr *>(Val: CO)) { |
1550 | llvm::json::Object Obj; |
1551 | Obj["id"] = createPointerRepresentation(Ptr: CLE); |
1552 | Obj["kind"] = CLE->getStmtClassName(); |
1553 | JOS.value(V: std::move(Obj)); |
1554 | } else { |
1555 | llvm_unreachable("unexpected cleanup object type"); |
1556 | } |
1557 | }); |
1558 | } |
1559 | } |
1560 | |
1561 | void JSONNodeDumper::VisitCXXBindTemporaryExpr( |
1562 | const CXXBindTemporaryExpr *BTE) { |
1563 | const CXXTemporary *Temp = BTE->getTemporary(); |
1564 | JOS.attribute(Key: "temp", Contents: createPointerRepresentation(Ptr: Temp)); |
1565 | if (const CXXDestructorDecl *Dtor = Temp->getDestructor()) |
1566 | JOS.attribute(Key: "dtor", Contents: createBareDeclRef(Dtor)); |
1567 | } |
1568 | |
1569 | void JSONNodeDumper::VisitMaterializeTemporaryExpr( |
1570 | const MaterializeTemporaryExpr *MTE) { |
1571 | if (const ValueDecl *VD = MTE->getExtendingDecl()) |
1572 | JOS.attribute(Key: "extendingDecl", Contents: createBareDeclRef(VD)); |
1573 | |
1574 | switch (MTE->getStorageDuration()) { |
1575 | case SD_Automatic: |
1576 | JOS.attribute(Key: "storageDuration", Contents: "automatic"); |
1577 | break; |
1578 | case SD_Dynamic: |
1579 | JOS.attribute(Key: "storageDuration", Contents: "dynamic"); |
1580 | break; |
1581 | case SD_FullExpression: |
1582 | JOS.attribute(Key: "storageDuration", Contents: "full expression"); |
1583 | break; |
1584 | case SD_Static: |
1585 | JOS.attribute(Key: "storageDuration", Contents: "static"); |
1586 | break; |
1587 | case SD_Thread: |
1588 | JOS.attribute(Key: "storageDuration", Contents: "thread"); |
1589 | break; |
1590 | } |
1591 | |
1592 | attributeOnlyIfTrue(Key: "boundToLValueRef", Value: MTE->isBoundToLvalueReference()); |
1593 | } |
1594 | |
1595 | void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) { |
1596 | attributeOnlyIfTrue(Key: "hasRewrittenInit", Value: Node->hasRewrittenInit()); |
1597 | } |
1598 | |
1599 | void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) { |
1600 | attributeOnlyIfTrue(Key: "hasRewrittenInit", Value: Node->hasRewrittenInit()); |
1601 | } |
1602 | |
1603 | void JSONNodeDumper::VisitCXXDependentScopeMemberExpr( |
1604 | const CXXDependentScopeMemberExpr *DSME) { |
1605 | JOS.attribute(Key: "isArrow", Contents: DSME->isArrow()); |
1606 | JOS.attribute(Key: "member", Contents: DSME->getMember().getAsString()); |
1607 | attributeOnlyIfTrue(Key: "hasTemplateKeyword", Value: DSME->hasTemplateKeyword()); |
1608 | attributeOnlyIfTrue(Key: "hasExplicitTemplateArgs", |
1609 | Value: DSME->hasExplicitTemplateArgs()); |
1610 | |
1611 | if (DSME->getNumTemplateArgs()) { |
1612 | JOS.attributeArray(Key: "explicitTemplateArgs", Contents: [DSME, this] { |
1613 | for (const TemplateArgumentLoc &TAL : DSME->template_arguments()) |
1614 | JOS.object( |
1615 | Contents: [&TAL, this] { Visit(TA: TAL.getArgument(), R: TAL.getSourceRange()); }); |
1616 | }); |
1617 | } |
1618 | } |
1619 | |
1620 | void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr *RE) { |
1621 | if (!RE->isValueDependent()) |
1622 | JOS.attribute(Key: "satisfied", Contents: RE->isSatisfied()); |
1623 | } |
1624 | |
1625 | void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) { |
1626 | llvm::SmallString<16> Buffer; |
1627 | IL->getValue().toString(Buffer, |
1628 | /*Radix=*/10, IL->getType()->isSignedIntegerType()); |
1629 | JOS.attribute(Key: "value", Contents: Buffer); |
1630 | } |
1631 | void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) { |
1632 | // FIXME: This should probably print the character literal as a string, |
1633 | // rather than as a numerical value. It would be nice if the behavior matched |
1634 | // what we do to print a string literal; right now, it is impossible to tell |
1635 | // the difference between 'a' and L'a' in C from the JSON output. |
1636 | JOS.attribute(Key: "value", Contents: CL->getValue()); |
1637 | } |
1638 | void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) { |
1639 | JOS.attribute(Key: "value", Contents: FPL->getValueAsString(/*Radix=*/10)); |
1640 | } |
1641 | void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) { |
1642 | llvm::SmallString<16> Buffer; |
1643 | FL->getValue().toString(Str&: Buffer); |
1644 | JOS.attribute(Key: "value", Contents: Buffer); |
1645 | } |
1646 | void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) { |
1647 | std::string Buffer; |
1648 | llvm::raw_string_ostream SS(Buffer); |
1649 | SL->outputString(OS&: SS); |
1650 | JOS.attribute(Key: "value", Contents: Buffer); |
1651 | } |
1652 | void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) { |
1653 | JOS.attribute(Key: "value", Contents: BLE->getValue()); |
1654 | } |
1655 | |
1656 | void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) { |
1657 | attributeOnlyIfTrue(Key: "hasInit", Value: IS->hasInitStorage()); |
1658 | attributeOnlyIfTrue(Key: "hasVar", Value: IS->hasVarStorage()); |
1659 | attributeOnlyIfTrue(Key: "hasElse", Value: IS->hasElseStorage()); |
1660 | attributeOnlyIfTrue(Key: "isConstexpr", Value: IS->isConstexpr()); |
1661 | attributeOnlyIfTrue(Key: "isConsteval", Value: IS->isConsteval()); |
1662 | attributeOnlyIfTrue(Key: "constevalIsNegated", Value: IS->isNegatedConsteval()); |
1663 | } |
1664 | |
1665 | void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) { |
1666 | attributeOnlyIfTrue(Key: "hasInit", Value: SS->hasInitStorage()); |
1667 | attributeOnlyIfTrue(Key: "hasVar", Value: SS->hasVarStorage()); |
1668 | } |
1669 | void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) { |
1670 | attributeOnlyIfTrue(Key: "isGNURange", Value: CS->caseStmtIsGNURange()); |
1671 | } |
1672 | |
1673 | void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) { |
1674 | JOS.attribute(Key: "name", Contents: LS->getName()); |
1675 | JOS.attribute(Key: "declId", Contents: createPointerRepresentation(Ptr: LS->getDecl())); |
1676 | attributeOnlyIfTrue(Key: "sideEntry", Value: LS->isSideEntry()); |
1677 | } |
1678 | void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) { |
1679 | JOS.attribute(Key: "targetLabelDeclId", |
1680 | Contents: createPointerRepresentation(Ptr: GS->getLabel())); |
1681 | } |
1682 | |
1683 | void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) { |
1684 | attributeOnlyIfTrue(Key: "hasVar", Value: WS->hasVarStorage()); |
1685 | } |
1686 | |
1687 | void JSONNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt* OACS) { |
1688 | // FIXME: it would be nice for the ASTNodeTraverser would handle the catch |
1689 | // parameter the same way for C++ and ObjC rather. In this case, C++ gets a |
1690 | // null child node and ObjC gets no child node. |
1691 | attributeOnlyIfTrue(Key: "isCatchAll", Value: OACS->getCatchParamDecl() == nullptr); |
1692 | } |
1693 | |
1694 | void JSONNodeDumper::VisitNullTemplateArgument(const TemplateArgument &TA) { |
1695 | JOS.attribute(Key: "isNull", Contents: true); |
1696 | } |
1697 | void JSONNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) { |
1698 | JOS.attribute(Key: "type", Contents: createQualType(QT: TA.getAsType())); |
1699 | } |
1700 | void JSONNodeDumper::VisitDeclarationTemplateArgument( |
1701 | const TemplateArgument &TA) { |
1702 | JOS.attribute(Key: "decl", Contents: createBareDeclRef(TA.getAsDecl())); |
1703 | } |
1704 | void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) { |
1705 | JOS.attribute(Key: "isNullptr", Contents: true); |
1706 | } |
1707 | void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) { |
1708 | JOS.attribute(Key: "value", Contents: TA.getAsIntegral().getSExtValue()); |
1709 | } |
1710 | void JSONNodeDumper::VisitStructuralValueTemplateArgument( |
1711 | const TemplateArgument &TA) { |
1712 | Visit(Value: TA.getAsStructuralValue(), Ty: TA.getStructuralValueType()); |
1713 | } |
1714 | void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) { |
1715 | // FIXME: cannot just call dump() on the argument, as that doesn't specify |
1716 | // the output format. |
1717 | } |
1718 | void JSONNodeDumper::VisitTemplateExpansionTemplateArgument( |
1719 | const TemplateArgument &TA) { |
1720 | // FIXME: cannot just call dump() on the argument, as that doesn't specify |
1721 | // the output format. |
1722 | } |
1723 | void JSONNodeDumper::VisitExpressionTemplateArgument( |
1724 | const TemplateArgument &TA) { |
1725 | JOS.attribute(Key: "isExpr", Contents: true); |
1726 | if (TA.isCanonicalExpr()) |
1727 | JOS.attribute(Key: "isCanonical", Contents: true); |
1728 | } |
1729 | void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) { |
1730 | JOS.attribute(Key: "isPack", Contents: true); |
1731 | } |
1732 | |
1733 | StringRef JSONNodeDumper::getCommentCommandName(unsigned CommandID) const { |
1734 | if (Traits) |
1735 | return Traits->getCommandInfo(CommandID)->Name; |
1736 | if (const comments::CommandInfo *Info = |
1737 | comments::CommandTraits::getBuiltinCommandInfo(CommandID)) |
1738 | return Info->Name; |
1739 | return "<invalid>"; |
1740 | } |
1741 | |
1742 | void JSONNodeDumper::visitTextComment(const comments::TextComment *C, |
1743 | const comments::FullComment *) { |
1744 | JOS.attribute(Key: "text", Contents: C->getText()); |
1745 | } |
1746 | |
1747 | void JSONNodeDumper::visitInlineCommandComment( |
1748 | const comments::InlineCommandComment *C, const comments::FullComment *) { |
1749 | JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID())); |
1750 | |
1751 | switch (C->getRenderKind()) { |
1752 | case comments::InlineCommandRenderKind::Normal: |
1753 | JOS.attribute(Key: "renderKind", Contents: "normal"); |
1754 | break; |
1755 | case comments::InlineCommandRenderKind::Bold: |
1756 | JOS.attribute(Key: "renderKind", Contents: "bold"); |
1757 | break; |
1758 | case comments::InlineCommandRenderKind::Emphasized: |
1759 | JOS.attribute(Key: "renderKind", Contents: "emphasized"); |
1760 | break; |
1761 | case comments::InlineCommandRenderKind::Monospaced: |
1762 | JOS.attribute(Key: "renderKind", Contents: "monospaced"); |
1763 | break; |
1764 | case comments::InlineCommandRenderKind::Anchor: |
1765 | JOS.attribute(Key: "renderKind", Contents: "anchor"); |
1766 | break; |
1767 | } |
1768 | |
1769 | llvm::json::Array Args; |
1770 | for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) |
1771 | Args.push_back(E: C->getArgText(Idx: I)); |
1772 | |
1773 | if (!Args.empty()) |
1774 | JOS.attribute(Key: "args", Contents: std::move(Args)); |
1775 | } |
1776 | |
1777 | void JSONNodeDumper::visitHTMLStartTagComment( |
1778 | const comments::HTMLStartTagComment *C, const comments::FullComment *) { |
1779 | JOS.attribute(Key: "name", Contents: C->getTagName()); |
1780 | attributeOnlyIfTrue(Key: "selfClosing", Value: C->isSelfClosing()); |
1781 | attributeOnlyIfTrue(Key: "malformed", Value: C->isMalformed()); |
1782 | |
1783 | llvm::json::Array Attrs; |
1784 | for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) |
1785 | Attrs.push_back( |
1786 | E: {{"name", C->getAttr(Idx: I).Name}, { "value", C->getAttr(Idx: I).Value}}); |
1787 | |
1788 | if (!Attrs.empty()) |
1789 | JOS.attribute(Key: "attrs", Contents: std::move(Attrs)); |
1790 | } |
1791 | |
1792 | void JSONNodeDumper::visitHTMLEndTagComment( |
1793 | const comments::HTMLEndTagComment *C, const comments::FullComment *) { |
1794 | JOS.attribute(Key: "name", Contents: C->getTagName()); |
1795 | } |
1796 | |
1797 | void JSONNodeDumper::visitBlockCommandComment( |
1798 | const comments::BlockCommandComment *C, const comments::FullComment *) { |
1799 | JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID())); |
1800 | |
1801 | llvm::json::Array Args; |
1802 | for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) |
1803 | Args.push_back(E: C->getArgText(Idx: I)); |
1804 | |
1805 | if (!Args.empty()) |
1806 | JOS.attribute(Key: "args", Contents: std::move(Args)); |
1807 | } |
1808 | |
1809 | void JSONNodeDumper::visitParamCommandComment( |
1810 | const comments::ParamCommandComment *C, const comments::FullComment *FC) { |
1811 | switch (C->getDirection()) { |
1812 | case comments::ParamCommandPassDirection::In: |
1813 | JOS.attribute(Key: "direction", Contents: "in"); |
1814 | break; |
1815 | case comments::ParamCommandPassDirection::Out: |
1816 | JOS.attribute(Key: "direction", Contents: "out"); |
1817 | break; |
1818 | case comments::ParamCommandPassDirection::InOut: |
1819 | JOS.attribute(Key: "direction", Contents: "in,out"); |
1820 | break; |
1821 | } |
1822 | attributeOnlyIfTrue(Key: "explicit", Value: C->isDirectionExplicit()); |
1823 | |
1824 | if (C->hasParamName()) |
1825 | JOS.attribute(Key: "param", Contents: C->isParamIndexValid() ? C->getParamName(FC) |
1826 | : C->getParamNameAsWritten()); |
1827 | |
1828 | if (C->isParamIndexValid() && !C->isVarArgParam()) |
1829 | JOS.attribute(Key: "paramIdx", Contents: C->getParamIndex()); |
1830 | } |
1831 | |
1832 | void JSONNodeDumper::visitTParamCommandComment( |
1833 | const comments::TParamCommandComment *C, const comments::FullComment *FC) { |
1834 | if (C->hasParamName()) |
1835 | JOS.attribute(Key: "param", Contents: C->isPositionValid() ? C->getParamName(FC) |
1836 | : C->getParamNameAsWritten()); |
1837 | if (C->isPositionValid()) { |
1838 | llvm::json::Array Positions; |
1839 | for (unsigned I = 0, E = C->getDepth(); I < E; ++I) |
1840 | Positions.push_back(E: C->getIndex(Depth: I)); |
1841 | |
1842 | if (!Positions.empty()) |
1843 | JOS.attribute(Key: "positions", Contents: std::move(Positions)); |
1844 | } |
1845 | } |
1846 | |
1847 | void JSONNodeDumper::visitVerbatimBlockComment( |
1848 | const comments::VerbatimBlockComment *C, const comments::FullComment *) { |
1849 | JOS.attribute(Key: "name", Contents: getCommentCommandName(CommandID: C->getCommandID())); |
1850 | JOS.attribute(Key: "closeName", Contents: C->getCloseName()); |
1851 | } |
1852 | |
1853 | void JSONNodeDumper::visitVerbatimBlockLineComment( |
1854 | const comments::VerbatimBlockLineComment *C, |
1855 | const comments::FullComment *) { |
1856 | JOS.attribute(Key: "text", Contents: C->getText()); |
1857 | } |
1858 | |
1859 | void JSONNodeDumper::visitVerbatimLineComment( |
1860 | const comments::VerbatimLineComment *C, const comments::FullComment *) { |
1861 | JOS.attribute(Key: "text", Contents: C->getText()); |
1862 | } |
1863 | |
1864 | llvm::json::Object JSONNodeDumper::createFPOptions(FPOptionsOverride FPO) { |
1865 | llvm::json::Object Ret; |
1866 | #define FP_OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ |
1867 | if (FPO.has##NAME##Override()) \ |
1868 | Ret.try_emplace(#NAME, static_cast<unsigned>(FPO.get##NAME##Override())); |
1869 | #include "clang/Basic/FPOptions.def" |
1870 | return Ret; |
1871 | } |
1872 | |
1873 | void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt *S) { |
1874 | VisitStmt(S); |
1875 | if (S->hasStoredFPFeatures()) |
1876 | JOS.attribute(Key: "fpoptions", Contents: createFPOptions(FPO: S->getStoredFPFeatures())); |
1877 | } |
1878 |
Definitions
- addPreviousDeclaration
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- Visit
- writeIncludeStack
- writeBareSourceLocation
- writeSourceLocation
- writeSourceRange
- createPointerRepresentation
- createQualType
- writeBareDeclRef
- createBareDeclRef
- createCastPath
- createDefaultConstructorDefinitionData
- createCopyConstructorDefinitionData
- createMoveConstructorDefinitionData
- createCopyAssignmentDefinitionData
- createMoveAssignmentDefinitionData
- createDestructorDefinitionData
- createCXXRecordDefinitionData
- createAccessSpecifier
- createCXXBaseSpecifier
- VisitAliasAttr
- VisitCleanupAttr
- VisitDeprecatedAttr
- VisitUnavailableAttr
- VisitSectionAttr
- VisitVisibilityAttr
- VisitTLSModelAttr
- VisitTypedefType
- VisitUsingType
- VisitFunctionType
- VisitFunctionProtoType
- VisitRValueReferenceType
- VisitArrayType
- VisitConstantArrayType
- VisitDependentSizedExtVectorType
- VisitVectorType
- VisitUnresolvedUsingType
- VisitUnaryTransformType
- VisitTagType
- VisitTemplateTypeParmType
- VisitSubstTemplateTypeParmType
- VisitSubstTemplateTypeParmPackType
- VisitAutoType
- VisitTemplateSpecializationType
- VisitInjectedClassNameType
- VisitObjCInterfaceType
- VisitPackExpansionType
- VisitElaboratedType
- VisitMacroQualifiedType
- VisitMemberPointerType
- VisitNamedDecl
- VisitTypedefDecl
- VisitTypeAliasDecl
- VisitNamespaceDecl
- VisitUsingDirectiveDecl
- VisitNamespaceAliasDecl
- VisitUsingDecl
- VisitUsingEnumDecl
- VisitUsingShadowDecl
- VisitVarDecl
- VisitFieldDecl
- VisitFunctionDecl
- VisitEnumDecl
- VisitEnumConstantDecl
- VisitRecordDecl
- VisitCXXRecordDecl
- VisitHLSLBufferDecl
- VisitTemplateTypeParmDecl
- VisitNonTypeTemplateParmDecl
- VisitTemplateTemplateParmDecl
- VisitLinkageSpecDecl
- VisitAccessSpecDecl
- VisitFriendDecl
- VisitObjCIvarDecl
- VisitObjCMethodDecl
- VisitObjCTypeParamDecl
- VisitObjCCategoryDecl
- VisitObjCCategoryImplDecl
- VisitObjCProtocolDecl
- VisitObjCInterfaceDecl
- VisitObjCImplementationDecl
- VisitObjCCompatibleAliasDecl
- VisitObjCPropertyDecl
- VisitObjCPropertyImplDecl
- VisitBlockDecl
- VisitAtomicExpr
- VisitObjCEncodeExpr
- VisitObjCMessageExpr
- VisitObjCBoxedExpr
- VisitObjCSelectorExpr
- VisitObjCProtocolExpr
- VisitObjCPropertyRefExpr
- VisitObjCSubscriptRefExpr
- VisitObjCIvarRefExpr
- VisitObjCBoolLiteralExpr
- VisitDeclRefExpr
- VisitSYCLUniqueStableNameExpr
- VisitOpenACCAsteriskSizeExpr
- VisitOpenACCDeclareDecl
- VisitOpenACCRoutineDecl
- VisitPredefinedExpr
- VisitUnaryOperator
- VisitBinaryOperator
- VisitCompoundAssignOperator
- VisitMemberExpr
- VisitCXXNewExpr
- VisitCXXDeleteExpr
- VisitCXXThisExpr
- VisitCastExpr
- VisitImplicitCastExpr
- VisitCallExpr
- VisitUnaryExprOrTypeTraitExpr
- VisitSizeOfPackExpr
- VisitUnresolvedLookupExpr
- VisitAddrLabelExpr
- VisitCXXTypeidExpr
- VisitConstantExpr
- VisitInitListExpr
- VisitGenericSelectionExpr
- VisitCXXUnresolvedConstructExpr
- VisitCXXConstructExpr
- VisitExprWithCleanups
- VisitCXXBindTemporaryExpr
- VisitMaterializeTemporaryExpr
- VisitCXXDefaultArgExpr
- VisitCXXDefaultInitExpr
- VisitCXXDependentScopeMemberExpr
- VisitRequiresExpr
- VisitIntegerLiteral
- VisitCharacterLiteral
- VisitFixedPointLiteral
- VisitFloatingLiteral
- VisitStringLiteral
- VisitCXXBoolLiteralExpr
- VisitIfStmt
- VisitSwitchStmt
- VisitCaseStmt
- VisitLabelStmt
- VisitGotoStmt
- VisitWhileStmt
- VisitObjCAtCatchStmt
- VisitNullTemplateArgument
- VisitTypeTemplateArgument
- VisitDeclarationTemplateArgument
- VisitNullPtrTemplateArgument
- VisitIntegralTemplateArgument
- VisitStructuralValueTemplateArgument
- VisitTemplateTemplateArgument
- VisitTemplateExpansionTemplateArgument
- VisitExpressionTemplateArgument
- VisitPackTemplateArgument
- getCommentCommandName
- visitTextComment
- visitInlineCommandComment
- visitHTMLStartTagComment
- visitHTMLEndTagComment
- visitBlockCommandComment
- visitParamCommandComment
- visitTParamCommandComment
- visitVerbatimBlockComment
- visitVerbatimBlockLineComment
- visitVerbatimLineComment
- createFPOptions
Learn to use CMake with our Intro Training
Find out more