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