28#include <clang/AST/ASTContext.h>
29#include <clang/AST/Attr.h>
30#include <clang/AST/Comment.h>
31#include <clang/AST/CommentVisitor.h>
32#include <clang/AST/Decl.h>
33#include <clang/AST/DeclCXX.h>
34#include <clang/AST/DeclContextInternals.h>
35#include <clang/AST/DeclTemplate.h>
36#include <clang/AST/Expr.h>
37#include <clang/AST/ExprCXX.h>
38#include <clang/AST/NestedNameSpecifier.h>
39#include <clang/AST/RecursiveASTVisitor.h>
40#include <clang/AST/TemplateBase.h>
41#include <clang/AST/TemplateName.h>
42#include <clang/AST/Type.h>
43#include <clang/AST/TypeLoc.h>
44#include <clang/Frontend/ASTUnit.h>
45#include <llvm/ADT/DenseMap.h>
46#include <llvm/Config/llvm-config.h>
47#include <llvm/ADT/SmallPtrSet.h>
48#include <llvm/Support/raw_ostream.h>
49#include <unordered_map>
57 case clang::VK_PRValue:
59 case clang::VK_LValue:
61 case clang::VK_XValue:
69 case clang::OK_Ordinary:
71 case clang::OK_BitField:
73 case clang::OK_VectorComponent:
75 case clang::OK_ObjCProperty:
77 case clang::OK_ObjCSubscript:
79 case clang::OK_MatrixComponent:
85InternedString varDeclInitStyleName(clang::VarDecl::InitializationStyle style) {
87 case clang::VarDecl::CInit:
89 case clang::VarDecl::CallInit:
91 case clang::VarDecl::ListInit:
93 case clang::VarDecl::ParenListInit:
100 switch (storageClass) {
103 case clang::SC_Extern:
105 case clang::SC_Static:
107 case clang::SC_PrivateExtern:
111 case clang::SC_Register:
119 case clang::Linkage::Invalid:
121 case clang::Linkage::None:
123 case clang::Linkage::Internal:
125 case clang::Linkage::UniqueExternal:
127 case clang::Linkage::VisibleNone:
129 case clang::Linkage::Module:
131 case clang::Linkage::External:
139 obj[
"fileId"] =
static_cast<uint64_t
>(loc.fileID());
140 obj[
"line"] =
static_cast<uint64_t
>(loc.line());
141 obj[
"column"] =
static_cast<uint64_t
>(loc.column());
147 obj[
"begin"] = sourceLocationToJson(range.begin());
148 obj[
"end"] = sourceLocationToJson(range.end());
152void maybeAddMacroSpellingRange(
AcavJson &properties,
153 const clang::SourceRange &range,
154 const clang::SourceManager &sm,
156 if (!range.isValid()) {
159 if (!range.getBegin().isMacroID() && !range.getEnd().isMacroID()) {
163 clang::SourceLocation spellingBegin = sm.getSpellingLoc(range.getBegin());
164 clang::SourceLocation spellingEnd = sm.getSpellingLoc(range.getEnd());
165 if (spellingBegin.isInvalid() || spellingEnd.isInvalid()) {
169 clang::SourceRange spellingRange(spellingBegin, spellingEnd);
172 if (!auroraRange.begin().isValid()) {
176 properties[
"macroSpellingRange"] = sourceRangeToJson(auroraRange);
179const char *getFullDeclClassName(
const clang::Decl *decl) {
182 switch (decl->getKind()) {
183#define DECL(DERIVED, BASE) \
184 case clang::Decl::DERIVED: \
185 return #DERIVED "Decl";
186#define ABSTRACT_DECL(DECL)
187#include "clang/AST/DeclNodes.inc"
192const char *getFullTypeClassName(
const clang::Type *type) {
195 switch (type->getTypeClass()) {
196#define ABSTRACT_TYPE(DERIVED, BASE)
197#define TYPE(DERIVED, BASE) \
198 case clang::Type::DERIVED: \
199 return #DERIVED "Type";
200#include "clang/AST/TypeNodes.inc"
207TypeInfoExtractor::TypeInfoExtractor(clang::ASTContext &ctx)
208 : ctx_(ctx), policy_(ctx.getLangOpts()) {
210 policy_.SuppressTagKeyword =
false;
212 policy_.UseVoidForZeroParams =
true;
213 policy_.TerseOutput =
false;
214 policy_.PolishForDeclaration =
true;
215 policy_.SuppressUnwrittenScope =
false;
225 std::string spelledType = qt.getAsString(policy_);
229 clang::QualType canonicalType = qt.getCanonicalType();
230 if (canonicalType != qt) {
231 std::string canonicalStr = canonicalType.getAsString(policy_);
236 clang::QualType desugared = qt.getDesugaredType(ctx_);
237 if (desugared != qt && desugared != canonicalType) {
238 std::string desugaredStr = desugared.getAsString(policy_);
243 clang::Qualifiers quals = qt.getQualifiers();
244 if (quals.hasConst()) {
245 properties[
"isConst"] =
true;
247 if (quals.hasVolatile()) {
248 properties[
"isVolatile"] =
true;
250 if (quals.hasRestrict()) {
251 properties[
"isRestrict"] =
true;
255 const clang::Type *typePtr = qt.getTypePtr();
257 properties[
"typeClass"] =
InternedString(getFullTypeClassName(typePtr));
261 if (
const auto *ptrType = typePtr->getAs<clang::PointerType>()) {
262 clang::QualType pointee = ptrType->getPointeeType();
263 properties[
"pointeeType"] =
InternedString(pointee.getAsString(policy_));
264 }
else if (
const auto *refType = typePtr->getAs<clang::ReferenceType>()) {
265 clang::QualType pointee = refType->getPointeeType();
266 properties[
"referencedType"] =
InternedString(pointee.getAsString(policy_));
267 properties[
"isLValueReference"] =
268 llvm::isa<clang::LValueReferenceType>(refType);
269 properties[
"isRValueReference"] =
270 llvm::isa<clang::RValueReferenceType>(refType);
271 }
else if (
const auto *arrType = typePtr->getAsArrayTypeUnsafe()) {
272 clang::QualType elemType = arrType->getElementType();
273 properties[
"elementType"] =
InternedString(elemType.getAsString(policy_));
276 if (
const auto *constArrType =
277 llvm::dyn_cast<clang::ConstantArrayType>(arrType)) {
278 properties[
"arraySize"] =
279 static_cast<int64_t
>(constArrType->getSize().getZExtValue());
281 }
else if (
const auto *funcType =
282 typePtr->getAs<clang::FunctionProtoType>()) {
284 clang::QualType returnType = funcType->getReturnType();
285 properties[
"returnType"] =
InternedString(returnType.getAsString(policy_));
286 properties[
"numParams"] =
static_cast<int64_t
>(funcType->getNumParams());
289 switch (funcType->getExceptionSpecType()) {
290 case clang::EST_None:
292 case clang::EST_NoThrow:
293 case clang::EST_NoexceptTrue:
294 properties[
"noexcept"] =
true;
296 case clang::EST_NoexceptFalse:
297 properties[
"noexcept"] =
false;
300 properties[
"exceptionSpec"] =
301 static_cast<int64_t
>(funcType->getExceptionSpecType());
306 switch (funcType->getRefQualifier()) {
309 case clang::RQ_LValue:
312 case clang::RQ_RValue:
316 }
else if (
const auto *recordType = typePtr->getAs<clang::RecordType>()) {
317 if (
auto *recordDecl = recordType->getDecl()) {
318 properties[
"recordName"] =
InternedString(recordDecl->getNameAsString());
320 }
else if (
const auto *enumType = typePtr->getAs<clang::EnumType>()) {
321 if (
auto *enumDecl = enumType->getDecl()) {
322 properties[
"enumName"] =
InternedString(enumDecl->getNameAsString());
324 }
else if (
const auto *typedefType = typePtr->getAs<clang::TypedefType>()) {
325 if (
auto *typedefDecl = typedefType->getDecl()) {
326 clang::QualType underlying = typedefDecl->getUnderlyingType();
327 properties[
"underlyingType"] =
330 }
else if (
const auto *autoType = typePtr->getAs<clang::AutoType>()) {
331 if (autoType->isDeduced()) {
332 clang::QualType deducedType = autoType->getDeducedType();
333 properties[
"deducedType"] =
336 properties[
"isDecltypeAuto"] = autoType->isDecltypeAuto();
347 const clang::Type *typePtr = tl.getTypePtr();
349 properties[
"typeLocClass"] =
InternedString(getFullTypeClassName(typePtr));
353 clang::SourceRange localRange = tl.getLocalSourceRange();
354 properties[
"hasLocalSourceRange"] = localRange.isValid();
358 const clang::TemplateArgumentList *args,
AcavJson &properties)
const {
359 if (!args || args->size() == 0) {
363 AcavJson argArray = AcavJson::array();
364 for (
unsigned i = 0; i < args->size(); ++i) {
365 const clang::TemplateArgument &arg = args->get(i);
369 properties[
"templateArgs"] = argArray;
370 properties[
"numTemplateArgs"] =
static_cast<int64_t
>(args->size());
374 const clang::TemplateArgument &arg)
const {
378 argInfo[
"kind"] =
static_cast<int64_t
>(arg.getKind());
380 switch (arg.getKind()) {
381 case clang::TemplateArgument::Null:
385 case clang::TemplateArgument::Type:
388 clang::QualType argType = arg.getAsType();
389 if (!argType.isNull() && argType.getTypePtr()) {
395 case clang::TemplateArgument::Declaration:
397 if (
auto *decl = arg.getAsDecl()) {
398 if (
auto *namedDecl = llvm::dyn_cast<clang::NamedDecl>(decl)) {
399 argInfo[
"declName"] =
InternedString(namedDecl->getNameAsString());
404 case clang::TemplateArgument::NullPtr:
409 case clang::TemplateArgument::Integral:
413 argInfo[
"value"] = arg.getAsIntegral().getSExtValue();
415 clang::QualType integralType = arg.getIntegralType();
416 if (!integralType.isNull() && integralType.getTypePtr()) {
417 argInfo[
"integralType"] =
423 case clang::TemplateArgument::Template:
426 clang::TemplateName templateName = arg.getAsTemplate();
427 if (!templateName.isNull()) {
428 std::string templateNameStr;
429 llvm::raw_string_ostream os(templateNameStr);
430 templateName.print(os, policy_);
432 if (!templateNameStr.empty()) {
439 case clang::TemplateArgument::TemplateExpansion:
442 clang::TemplateName templateName = arg.getAsTemplateOrTemplatePattern();
443 if (!templateName.isNull()) {
444 std::string templateNameStr;
445 llvm::raw_string_ostream os(templateNameStr);
446 templateName.print(os, policy_);
448 if (!templateNameStr.empty()) {
455 case clang::TemplateArgument::Expression:
460 case clang::TemplateArgument::Pack:
463 unsigned packSize = arg.pack_size();
464 argInfo[
"packSize"] =
static_cast<int64_t
>(packSize);
467 if (packSize > 0 && packSize < 1000) {
468 AcavJson packArgs = AcavJson::array();
469 for (
const auto &packArg : arg.pack_elements()) {
473 argInfo[
"packElements"] = packArgs;
478 case clang::TemplateArgument::StructuralValue:
489TypeInfoExtractor::getQualifierString(clang::Qualifiers quals)
const {
491 if (quals.hasConst())
493 if (quals.hasVolatile())
494 result +=
"volatile ";
495 if (quals.hasRestrict())
496 result +=
"restrict ";
502std::string_view toStringView(llvm::StringRef ref) {
503 return std::string_view(ref.data(), ref.size());
506void maybeSetNamedDeclProperty(AcavJson &properties,
const char *key,
507 const clang::NamedDecl *decl) {
512 if (
const clang::IdentifierInfo *identifier = decl->getIdentifier()) {
513 properties[key] = InternedString(toStringView(identifier->getName()));
517 std::string nameStr = decl->getNameAsString();
518 if (!nameStr.empty()) {
519 properties[key] = InternedString(std::move(nameStr));
523AcavJson makeDeclContextEntry(
const clang::Decl *decl,
524 AstViewNode *node =
nullptr) {
526 entry[
"kind"] = InternedString(getFullDeclClassName(decl));
530 if (
auto *namedDecl = llvm::dyn_cast<clang::NamedDecl>(decl)) {
531 maybeSetNamedDeclProperty(entry,
"name", namedDecl);
534 entry[
"nodePtr"] =
reinterpret_cast<uint64_t
>(node);
540 const clang::DeclContext *start,
const clang::Decl *self,
541 const std::unordered_map<const clang::DeclContext *, AstViewNode *>
543 AstViewNode *selfNode) {
545 std::vector<const clang::DeclContext *> contexts;
547 const clang::DeclContext *current = start;
549 contexts.push_back(current);
550 current = current->getParent();
553 const clang::Decl *innermostContextDecl =
nullptr;
554 if (!contexts.empty()) {
555 innermostContextDecl = llvm::dyn_cast<clang::Decl>(contexts.front());
558 for (
auto it = contexts.rbegin(); it != contexts.rend(); ++it) {
559 const clang::DeclContext *ctx = *it;
560 if (
auto *ctxDecl = llvm::dyn_cast<clang::Decl>(ctx)) {
562 AstViewNode *ctxNode =
nullptr;
563 auto nodeIt = contextMap.find(ctx);
564 if (nodeIt != contextMap.end()) {
565 ctxNode = nodeIt->second;
567 chain.push_back(makeDeclContextEntry(ctxDecl, ctxNode));
570 entry[
"kind"] = InternedString(
"DeclContext");
571 chain.push_back(entry);
575 if (self && self != innermostContextDecl) {
576 chain.push_back(makeDeclContextEntry(self, selfNode));
582static void appendWithSpacing(std::string &out, llvm::StringRef text) {
587 char last = out.back();
588 char first = text.front();
589 if (!std::isspace(
static_cast<unsigned char>(last)) &&
590 !std::isspace(
static_cast<unsigned char>(first))) {
594 out.append(text.begin(), text.end());
597static void collectCommentText(
const clang::comments::Comment *comment,
603 if (
const auto *text =
604 llvm::dyn_cast<clang::comments::TextComment>(comment)) {
605 appendWithSpacing(out, text->getText());
609 if (
const auto *verbatim =
610 llvm::dyn_cast<clang::comments::VerbatimBlockLineComment>(comment)) {
611 appendWithSpacing(out, verbatim->getText());
615 if (
const auto *verbatimLine =
616 llvm::dyn_cast<clang::comments::VerbatimLineComment>(comment)) {
617 appendWithSpacing(out, verbatimLine->getText());
621 for (
auto it = comment->child_begin(); it != comment->child_end(); ++it) {
622 collectCommentText(*it, out);
625 if (llvm::isa<clang::comments::ParagraphComment>(comment)) {
626 if (!out.empty() && out.back() !=
'\n') {
632class AcavAstVisitor :
public clang::RecursiveASTVisitor<AcavAstVisitor> {
634 AcavAstVisitor(AstContext *context, FileManager &fm, clang::ASTContext &ctx,
635 clang::Preprocessor *preprocessor,
bool extractComments)
636 : context_(context), fileManager_(fm), astContext_(ctx),
637 preprocessor_(preprocessor), extractComments_(extractComments),
638 typeExtractor_(ctx) {}
640 bool shouldVisitImplicitCode()
const {
return true; }
641 bool shouldVisitTemplateInstantiations()
const {
return true; }
642 bool shouldWalkTypesOfTypeLocs()
const {
return true; }
643 bool shouldTraversePostOrder()
const {
return false; }
645 bool TraverseDecl(clang::Decl *decl);
646 bool TraverseStmt(clang::Stmt *stmt);
647#if LLVM_VERSION_MAJOR >= 22
648 bool TraverseType(clang::QualType qualType,
bool TraverseQualifier =
true);
649 bool TraverseTypeLoc(clang::TypeLoc typeLoc,
bool TraverseQualifier =
true);
651 bool TraverseType(clang::QualType qualType);
652 bool TraverseTypeLoc(clang::TypeLoc typeLoc);
654 bool TraverseAttr(clang::Attr *attr);
655 bool TraverseConceptReference(clang::ConceptReference *cr);
656 bool TraverseCXXBaseSpecifier(
const clang::CXXBaseSpecifier &spec);
657 bool TraverseConstructorInitializer(clang::CXXCtorInitializer *init);
658 bool TraverseLambdaCapture(clang::LambdaExpr *lambda,
659 const clang::LambdaCapture *capture,
661#if LLVM_VERSION_MAJOR >= 22
662 bool TraverseNestedNameSpecifier(clang::NestedNameSpecifier nns);
664 bool TraverseNestedNameSpecifier(clang::NestedNameSpecifier *nns);
666 bool TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc loc);
667 bool TraverseTemplateArgument(clang::TemplateArgument arg);
668 bool TraverseTemplateArgumentLoc(clang::TemplateArgumentLoc loc);
669 bool TraverseTemplateName(clang::TemplateName name);
672 bool VisitDecl(clang::Decl *decl);
673 bool VisitStmt(clang::Stmt *stmt);
674 bool VisitType(clang::Type *type);
675 bool VisitTypeLoc(clang::TypeLoc typeLoc);
676 bool VisitAttr(clang::Attr *attr);
677 bool VisitConceptReference(clang::ConceptReference *cr);
678 bool VisitCXXBaseSpecifier(
const clang::CXXBaseSpecifier &spec);
679 bool VisitCXXCtorInitializer(clang::CXXCtorInitializer *init);
680 bool VisitLambdaCapture(
const clang::LambdaCapture *capture);
681 bool VisitNestedNameSpecifier(clang::NestedNameSpecifier *nns);
682 bool VisitNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc loc);
683 bool VisitTemplateArgument(clang::TemplateArgument arg);
684 bool VisitTemplateArgumentLoc(clang::TemplateArgumentLoc loc);
685 bool VisitTemplateName(clang::TemplateName name);
687 AstViewNode *getRootNode()
const {
return root_; }
688 const AstExtractionStats &getStats()
const {
return stats_; }
691 const InternedString &getCachedTypeString(clang::QualType type) {
692 const void *key = type.getAsOpaquePtr();
693 auto it = typeStringCache_.find(key);
694 if (it != typeStringCache_.end()) {
697 auto [insertIt, inserted] =
698 typeStringCache_.try_emplace(key, InternedString(type.getAsString()));
699 return insertIt->second;
702 void pushNode(AstViewNode *node) {
708 }
else if (!parentStack_.empty()) {
709 parentStack_.back()->addChild(node);
711 parentStack_.push_back(node);
715 if (!parentStack_.empty()) {
716 parentStack_.pop_back();
721 return parentStack_.back()->getNode()->getProperties();
724 AstViewNode *createNodeFromDecl(clang::Decl *decl);
725 AstViewNode *createNodeFromStmt(clang::Stmt *stmt);
726 AstViewNode *createNodeFromType(
const clang::Type *type);
727 AstViewNode *createNodeFromTypeLoc(clang::TypeLoc typeLoc);
728 AstViewNode *createNodeFromAttr(clang::Attr *attr);
729 AstViewNode *createNodeFromConceptRef(clang::ConceptReference *cr);
730 AstViewNode *createNodeFromCXXBaseSpec(
const clang::CXXBaseSpecifier &spec);
731 AstViewNode *createNodeFromCtorInit(clang::CXXCtorInitializer *init);
732 AstViewNode *createNodeFromLambdaCapture(
const clang::LambdaCapture *capture);
733#if LLVM_VERSION_MAJOR >= 22
734 AstViewNode *createNodeFromNestedNameSpec(clang::NestedNameSpecifier nns);
736 AstViewNode *createNodeFromNestedNameSpec(clang::NestedNameSpecifier *nns);
739 createNodeFromNestedNameSpecLoc(clang::NestedNameSpecifierLoc loc);
740 AstViewNode *createNodeFromTemplateArg(clang::TemplateArgument arg);
741 AstViewNode *createNodeFromTemplateArgLoc(clang::TemplateArgumentLoc loc);
742 AstViewNode *createNodeFromTemplateName(clang::TemplateName name);
744 AstContext *context_;
745 FileManager &fileManager_;
746 clang::ASTContext &astContext_;
747 clang::Preprocessor *preprocessor_;
748 bool extractComments_;
749 TypeInfoExtractor typeExtractor_;
750 AstViewNode *root_ =
nullptr;
751 std::vector<AstViewNode *> parentStack_;
752 AstExtractionStats stats_;
753 llvm::DenseMap<const void *, InternedString> typeStringCache_;
755 std::unordered_map<const clang::DeclContext *, AstViewNode *>
762bool AcavAstVisitor::TraverseDecl(clang::Decl *decl) {
766 AstViewNode *node = createNodeFromDecl(decl);
771 if (extractComments_ && preprocessor_) {
772 if (
const auto *comment =
773 astContext_.getCommentForDecl(decl, preprocessor_)) {
775 collectCommentText(comment, text);
777 node->getNode()->getProperties()[
"comment"] = InternedString(text);
778 ++stats_.commentCount;
783 if (
auto *dc = llvm::dyn_cast<clang::DeclContext>(decl)) {
784 declContextToNode_[dc] = node;
787 bool result = RecursiveASTVisitor::TraverseDecl(decl);
792bool AcavAstVisitor::TraverseStmt(clang::Stmt *stmt) {
796 AstViewNode *node = createNodeFromStmt(stmt);
801 bool result = RecursiveASTVisitor::TraverseStmt(stmt);
806#if LLVM_VERSION_MAJOR >= 22
807bool AcavAstVisitor::TraverseType(clang::QualType qualType,
808 bool TraverseQualifier) {
809 if (qualType.isNull()) {
812 const clang::Type *type = qualType.getTypePtr();
813 AstViewNode *node = createNodeFromType(type);
818 bool result = RecursiveASTVisitor::TraverseType(qualType, TraverseQualifier);
823bool AcavAstVisitor::TraverseTypeLoc(clang::TypeLoc typeLoc,
824 bool TraverseQualifier) {
825 if (typeLoc.isNull()) {
828 AstViewNode *node = createNodeFromTypeLoc(typeLoc);
834 RecursiveASTVisitor::TraverseTypeLoc(typeLoc, TraverseQualifier);
839bool AcavAstVisitor::TraverseType(clang::QualType qualType) {
840 if (qualType.isNull()) {
843 const clang::Type *type = qualType.getTypePtr();
844 AstViewNode *node = createNodeFromType(type);
849 bool result = RecursiveASTVisitor::TraverseType(qualType);
854bool AcavAstVisitor::TraverseTypeLoc(clang::TypeLoc typeLoc) {
855 if (typeLoc.isNull()) {
858 AstViewNode *node = createNodeFromTypeLoc(typeLoc);
863 bool result = RecursiveASTVisitor::TraverseTypeLoc(typeLoc);
869bool AcavAstVisitor::TraverseAttr(clang::Attr *attr) {
873 AstViewNode *node = createNodeFromAttr(attr);
878 bool result = RecursiveASTVisitor::TraverseAttr(attr);
883bool AcavAstVisitor::TraverseConceptReference(clang::ConceptReference *cr) {
887 AstViewNode *node = createNodeFromConceptRef(cr);
892 bool result = RecursiveASTVisitor::TraverseConceptReference(cr);
897bool AcavAstVisitor::TraverseCXXBaseSpecifier(
898 const clang::CXXBaseSpecifier &spec) {
899 AstViewNode *node = createNodeFromCXXBaseSpec(spec);
904 bool result = RecursiveASTVisitor::TraverseCXXBaseSpecifier(spec);
909bool AcavAstVisitor::TraverseConstructorInitializer(
910 clang::CXXCtorInitializer *init) {
914 AstViewNode *node = createNodeFromCtorInit(init);
919 bool result = RecursiveASTVisitor::TraverseConstructorInitializer(init);
924bool AcavAstVisitor::TraverseLambdaCapture(
925 clang::LambdaExpr *lambda,
const clang::LambdaCapture *capture,
930 AstViewNode *node = createNodeFromLambdaCapture(capture);
936 RecursiveASTVisitor::TraverseLambdaCapture(lambda, capture, init);
941#if LLVM_VERSION_MAJOR >= 22
942bool AcavAstVisitor::TraverseNestedNameSpecifier(
943 clang::NestedNameSpecifier nns) {
947 AstViewNode *node = createNodeFromNestedNameSpec(nns);
952 bool result = RecursiveASTVisitor::TraverseNestedNameSpecifier(nns);
957bool AcavAstVisitor::TraverseNestedNameSpecifier(
958 clang::NestedNameSpecifier *nns) {
962 AstViewNode *node = createNodeFromNestedNameSpec(nns);
967 bool result = RecursiveASTVisitor::TraverseNestedNameSpecifier(nns);
973bool AcavAstVisitor::TraverseNestedNameSpecifierLoc(
974 clang::NestedNameSpecifierLoc loc) {
978 AstViewNode *node = createNodeFromNestedNameSpecLoc(loc);
983 bool result = RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(loc);
988bool AcavAstVisitor::TraverseTemplateArgument(clang::TemplateArgument arg) {
989 AstViewNode *node = createNodeFromTemplateArg(arg);
994 bool result = RecursiveASTVisitor::TraverseTemplateArgument(arg);
999bool AcavAstVisitor::TraverseTemplateArgumentLoc(
1000 clang::TemplateArgumentLoc loc) {
1001 AstViewNode *node = createNodeFromTemplateArgLoc(loc);
1006 bool result = RecursiveASTVisitor::TraverseTemplateArgumentLoc(loc);
1011bool AcavAstVisitor::TraverseTemplateName(clang::TemplateName name) {
1012 AstViewNode *node = createNodeFromTemplateName(name);
1017 bool result = RecursiveASTVisitor::TraverseTemplateName(name);
1022bool AcavAstVisitor::VisitDecl(clang::Decl *decl) {
1023 if (!decl || parentStack_.empty()) {
1026 AcavJson &properties = currentProperties();
1027 properties[
"isDeclContext"] = llvm::isa<clang::DeclContext>(decl);
1028 if (
auto *namedDecl = llvm::dyn_cast<clang::NamedDecl>(decl)) {
1029 maybeSetNamedDeclProperty(properties,
"name", namedDecl);
1030 if (namedDecl->hasLinkage()) {
1031 properties[
"linkage"] =
1032 static_cast<int64_t
>(namedDecl->getLinkageInternal());
1033 properties[
"linkageName"] = linkageName(namedDecl->getLinkageInternal());
1036 if (
auto *valueDecl = llvm::dyn_cast<clang::ValueDecl>(decl)) {
1037 clang::QualType type = valueDecl->getType();
1038 if (!type.isNull()) {
1039 properties[
"type"] = getCachedTypeString(type);
1042 if (
auto *funcDecl = llvm::dyn_cast<clang::FunctionDecl>(decl)) {
1043 properties[
"isDefined"] = funcDecl->isDefined();
1044 properties[
"isInlined"] = funcDecl->isInlined();
1045 properties[
"isConstexpr"] = funcDecl->isConstexpr();
1046 properties[
"isDeleted"] = funcDecl->isDeleted();
1047 properties[
"isDefaulted"] = funcDecl->isDefaulted();
1048 clang::QualType returnType = funcDecl->getReturnType();
1049 if (!returnType.isNull()) {
1050 properties[
"returnType"] = getCachedTypeString(returnType);
1052 unsigned numParams = funcDecl->getNumParams();
1053 properties[
"numParams"] =
static_cast<int64_t
>(numParams);
1054 if (numParams > 0) {
1055 AcavJson params = AcavJson::array();
1056 for (
unsigned i = 0; i < numParams; ++i) {
1057 const clang::ParmVarDecl *param = funcDecl->getParamDecl(i);
1059 maybeSetNamedDeclProperty(paramInfo,
"name", param);
1060 paramInfo[
"type"] = getCachedTypeString(param->getType());
1061 params.push_back(paramInfo);
1063 properties[
"params"] = params;
1065 if (
auto *cxxMethod = llvm::dyn_cast<clang::CXXMethodDecl>(funcDecl)) {
1066 properties[
"isVirtual"] = cxxMethod->isVirtual();
1067 properties[
"isPure"] = cxxMethod->isPureVirtual();
1068 properties[
"isConst"] = cxxMethod->isConst();
1069 properties[
"isStatic"] = cxxMethod->isStatic();
1070 properties[
"isOverride"] = cxxMethod->size_overridden_methods() > 0;
1071 switch (cxxMethod->getRefQualifier()) {
1072 case clang::RQ_None:
1074 case clang::RQ_LValue:
1075 properties[
"refQualifier"] = InternedString(
"&");
1077 case clang::RQ_RValue:
1078 properties[
"refQualifier"] = InternedString(
"&&");
1083 if (
auto *varDecl = llvm::dyn_cast<clang::VarDecl>(decl)) {
1084 properties[
"isUsed"] = varDecl->isUsed();
1085 properties[
"isReferenced"] = varDecl->isReferenced();
1086 properties[
"hasInit"] = varDecl->hasInit();
1087 properties[
"isConstexpr"] = varDecl->isConstexpr();
1088 if (varDecl->hasInit()) {
1089 properties[
"initStyle"] =
static_cast<int64_t
>(varDecl->getInitStyle());
1090 properties[
"initStyleName"] =
1091 varDeclInitStyleName(varDecl->getInitStyle());
1093 properties[
"storageClass"] =
1094 static_cast<int64_t
>(varDecl->getStorageClass());
1095 properties[
"storageClassName"] =
1096 storageClassName(varDecl->getStorageClass());
1097 properties[
"isThreadLocal"] =
1098 varDecl->getTLSKind() != clang::VarDecl::TLS_None;
1100 if (
auto *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(decl)) {
1101 properties[
"isMutable"] = fieldDecl->isMutable();
1102 properties[
"isBitField"] = fieldDecl->isBitField();
1104 if (
auto *parmDecl = llvm::dyn_cast<clang::ParmVarDecl>(decl)) {
1105 properties[
"isUsed"] = parmDecl->isUsed();
1106 properties[
"hasDefaultArg"] = parmDecl->hasDefaultArg();
1108 if (
auto *recordDecl = llvm::dyn_cast<clang::CXXRecordDecl>(decl)) {
1109 properties[
"isReferenced"] = recordDecl->isReferenced();
1110 properties[
"hasDefinition"] = recordDecl->hasDefinition();
1111 if (recordDecl->hasDefinition() && recordDecl->isCompleteDefinition()) {
1112 properties[
"isAbstract"] = recordDecl->isAbstract();
1113 properties[
"isPolymorphic"] = recordDecl->isPolymorphic();
1114 properties[
"isEmpty"] = recordDecl->isEmpty();
1115 properties[
"isAggregate"] = recordDecl->isAggregate();
1116 properties[
"isPOD"] = recordDecl->isPOD();
1117 properties[
"isTrivial"] = recordDecl->isTrivial();
1118 if (recordDecl->getNumBases() > 0) {
1119 AcavJson bases = AcavJson::array();
1120 for (
const auto &base : recordDecl->bases()) {
1121 clang::QualType baseType = base.getType();
1122 if (baseType.isNull()) {
1126 baseInfo[
"type"] = getCachedTypeString(baseType);
1127 baseInfo[
"isVirtual"] = base.isVirtual();
1128 baseInfo[
"accessSpecifier"] =
1129 static_cast<int64_t
>(base.getAccessSpecifier());
1130 bases.push_back(baseInfo);
1132 properties[
"bases"] = bases;
1133 properties[
"numBases"] =
1134 static_cast<int64_t
>(recordDecl->getNumBases());
1137 if (
auto *tagDecl = llvm::dyn_cast<clang::TagDecl>(recordDecl)) {
1138 properties[
"tagKind"] =
static_cast<int64_t
>(tagDecl->getTagKind());
1139 properties[
"isCompleteDefinition"] = tagDecl->isCompleteDefinition();
1142 if (
auto *enumDecl = llvm::dyn_cast<clang::EnumDecl>(decl)) {
1143 properties[
"isScoped"] = enumDecl->isScoped();
1144 properties[
"isFixed"] = enumDecl->isFixed();
1145 if (enumDecl->isFixed()) {
1146 clang::QualType intType = enumDecl->getIntegerType();
1147 if (!intType.isNull()) {
1148 properties[
"underlyingType"] = getCachedTypeString(intType);
1152 if (
auto *enumConstDecl = llvm::dyn_cast<clang::EnumConstantDecl>(decl)) {
1153 properties[
"initVal"] = enumConstDecl->getInitVal().getSExtValue();
1155 if (
auto *tempTypeParm = llvm::dyn_cast<clang::TemplateTypeParmDecl>(decl)) {
1156 properties[
"depth"] =
static_cast<int64_t
>(tempTypeParm->getDepth());
1157 properties[
"index"] =
static_cast<int64_t
>(tempTypeParm->getIndex());
1158 properties[
"hasDefaultArgument"] = tempTypeParm->hasDefaultArgument();
1160 if (
auto *classTemplateSpec =
1161 llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
1162 const clang::TemplateArgumentList &args =
1163 classTemplateSpec->getTemplateArgs();
1164 typeExtractor_.extractTemplateArgs(&args, properties);
1165 properties[
"specializationKind"] =
1166 static_cast<int64_t
>(classTemplateSpec->getSpecializationKind());
1168 if (
auto *typedefDecl = llvm::dyn_cast<clang::TypedefNameDecl>(decl)) {
1169 clang::QualType underlying = typedefDecl->getUnderlyingType();
1170 if (!underlying.isNull()) {
1171 properties[
"underlyingType"] = getCachedTypeString(underlying);
1176 AstViewNode *currentNode =
1177 parentStack_.empty() ? nullptr : parentStack_.back();
1178 properties[
"semanticDeclContext"] = buildDeclContextChain(
1179 decl->getDeclContext(), decl, declContextToNode_, currentNode);
1180 properties[
"lexicalDeclContext"] = buildDeclContextChain(
1181 decl->getLexicalDeclContext(), decl, declContextToNode_, currentNode);
1185bool AcavAstVisitor::VisitStmt(clang::Stmt *stmt) {
1186 if (!stmt || parentStack_.empty()) {
1189 AcavJson &properties = currentProperties();
1190 if (
auto *expr = llvm::dyn_cast<clang::Expr>(stmt)) {
1191 clang::QualType exprType = expr->getType();
1192 if (!exprType.isNull()) {
1193 properties[
"type"] = getCachedTypeString(exprType);
1195 properties[
"valueKind"] =
static_cast<int64_t
>(expr->getValueKind());
1196 properties[
"valueKindName"] = exprValueKindName(expr->getValueKind());
1197 properties[
"objectKind"] =
static_cast<int64_t
>(expr->getObjectKind());
1198 properties[
"objectKindName"] = exprObjectKindName(expr->getObjectKind());
1199 properties[
"isTypeDependent"] = expr->isTypeDependent();
1200 properties[
"isValueDependent"] = expr->isValueDependent();
1201 properties[
"isLValue"] = expr->isLValue();
1202 properties[
"isPRValue"] = expr->isPRValue();
1203 properties[
"isXValue"] = expr->isXValue();
1204 properties[
"isGLValue"] = expr->isGLValue();
1206 if (
auto *ifStmt = llvm::dyn_cast<clang::IfStmt>(stmt)) {
1207 properties[
"hasElse"] = (ifStmt->getElse() !=
nullptr);
1208 properties[
"hasInit"] = (ifStmt->getInit() !=
nullptr);
1209 properties[
"hasVar"] = (ifStmt->getConditionVariable() !=
nullptr);
1210 properties[
"isConstexpr"] = ifStmt->isConstexpr();
1212 if (
auto *binOp = llvm::dyn_cast<clang::BinaryOperator>(stmt)) {
1213 properties[
"opcode"] = InternedString(toStringView(binOp->getOpcodeStr()));
1214 properties[
"opcodeValue"] =
static_cast<int64_t
>(binOp->getOpcode());
1215 properties[
"isAssignment"] = binOp->isAssignmentOp();
1216 properties[
"isCompound"] = binOp->isCompoundAssignmentOp();
1217 properties[
"isComparison"] = binOp->isComparisonOp();
1218 properties[
"isLogical"] = binOp->isLogicalOp();
1220 if (
auto *unaryOp = llvm::dyn_cast<clang::UnaryOperator>(stmt)) {
1221 properties[
"opcode"] = InternedString(
1222 toStringView(clang::UnaryOperator::getOpcodeStr(unaryOp->getOpcode())));
1223 properties[
"opcodeValue"] =
static_cast<int64_t
>(unaryOp->getOpcode());
1224 properties[
"isPrefix"] = unaryOp->isPrefix();
1225 properties[
"isPostfix"] = unaryOp->isPostfix();
1226 properties[
"isIncrementOp"] = unaryOp->isIncrementOp();
1227 properties[
"isDecrementOp"] = unaryOp->isDecrementOp();
1229 if (
auto *intLit = llvm::dyn_cast<clang::IntegerLiteral>(stmt)) {
1230 properties[
"value"] = intLit->getValue().getSExtValue();
1232 if (
auto *floatLit = llvm::dyn_cast<clang::FloatingLiteral>(stmt)) {
1233 properties[
"value"] = floatLit->getValueAsApproximateDouble();
1234 properties[
"isExact"] = floatLit->isExact();
1236 if (
auto *strLit = llvm::dyn_cast<clang::StringLiteral>(stmt)) {
1237 properties[
"byteLength"] =
static_cast<int64_t
>(strLit->getByteLength());
1238 properties[
"length"] =
static_cast<int64_t
>(strLit->getLength());
1239 properties[
"charWidth"] =
static_cast<int64_t
>(strLit->getCharByteWidth());
1241 const bool isSingleByte = strLit->getCharByteWidth() == 1;
1244 properties[
"value"] = InternedString(toStringView(strLit->getString()));
1245 properties[
"encoding"] = InternedString(
"char");
1248 llvm::raw_string_ostream os(buffer);
1249 strLit->outputString(os);
1251 properties[
"value"] = InternedString(buffer);
1252 properties[
"encoding"] = InternedString(
"wide");
1255 if (
auto *charLit = llvm::dyn_cast<clang::CharacterLiteral>(stmt)) {
1256 properties[
"value"] =
static_cast<int64_t
>(charLit->getValue());
1258 if (
auto *boolLit = llvm::dyn_cast<clang::CXXBoolLiteralExpr>(stmt)) {
1259 properties[
"value"] = boolLit->getValue();
1261 if (
auto *declRef = llvm::dyn_cast<clang::DeclRefExpr>(stmt)) {
1262 if (
auto *decl = declRef->getDecl()) {
1263 if (
auto *namedDecl = llvm::dyn_cast<clang::NamedDecl>(decl)) {
1264 maybeSetNamedDeclProperty(properties,
"declName", namedDecl);
1268 if (
auto *memberExpr = llvm::dyn_cast<clang::MemberExpr>(stmt)) {
1269 if (
auto *member = memberExpr->getMemberDecl()) {
1270 maybeSetNamedDeclProperty(properties,
"memberName", member);
1272 properties[
"isArrow"] = memberExpr->isArrow();
1274 if (
auto *callExpr = llvm::dyn_cast<clang::CallExpr>(stmt)) {
1275 properties[
"numArgs"] =
static_cast<int64_t
>(callExpr->getNumArgs());
1276 if (
auto *callee = callExpr->getCallee()) {
1277 if (
auto *declRef = llvm::dyn_cast<clang::DeclRefExpr>(callee)) {
1278 if (
auto *funcDecl =
1279 llvm::dyn_cast<clang::FunctionDecl>(declRef->getDecl())) {
1280 maybeSetNamedDeclProperty(properties,
"calleeName", funcDecl);
1285 if (
auto *castExpr = llvm::dyn_cast<clang::CastExpr>(stmt)) {
1286 properties[
"castKind"] = InternedString(castExpr->getCastKindName());
1287 properties[
"castKindValue"] =
static_cast<int64_t
>(castExpr->getCastKind());
1288 if (
auto *explicitCast =
1289 llvm::dyn_cast<clang::ExplicitCastExpr>(castExpr)) {
1290 clang::QualType targetType = explicitCast->getTypeAsWritten();
1291 properties[
"targetType"] = getCachedTypeString(targetType);
1294 if (
auto *ctorExpr = llvm::dyn_cast<clang::CXXConstructExpr>(stmt)) {
1295 if (
auto *ctorDecl = ctorExpr->getConstructor()) {
1296 maybeSetNamedDeclProperty(properties,
"constructorName", ctorDecl);
1298 properties[
"numArgs"] =
static_cast<int64_t
>(ctorExpr->getNumArgs());
1299 properties[
"isElidable"] = ctorExpr->isElidable();
1300 properties[
"requiresZeroInit"] = ctorExpr->requiresZeroInitialization();
1302 if (
auto *newExpr = llvm::dyn_cast<clang::CXXNewExpr>(stmt)) {
1303 clang::QualType allocatedType = newExpr->getAllocatedType();
1304 properties[
"allocatedType"] = getCachedTypeString(allocatedType);
1305 properties[
"isArray"] = newExpr->isArray();
1306 properties[
"isGlobalNew"] = newExpr->isGlobalNew();
1308 if (
auto *deleteExpr = llvm::dyn_cast<clang::CXXDeleteExpr>(stmt)) {
1309 properties[
"isArray"] = deleteExpr->isArrayForm();
1310 properties[
"isGlobalDelete"] = deleteExpr->isGlobalDelete();
1312 if (
auto *lambdaExpr = llvm::dyn_cast<clang::LambdaExpr>(stmt)) {
1313 properties[
"isMutable"] = lambdaExpr->isMutable();
1314 properties[
"hasExplicitParams"] = lambdaExpr->hasExplicitParameters();
1315 properties[
"hasExplicitResultType"] = lambdaExpr->hasExplicitResultType();
1316 properties[
"numCaptures"] =
1317 static_cast<int64_t
>(lambdaExpr->capture_size());
1322bool AcavAstVisitor::VisitType(clang::Type *type) {
1323 if (!type || parentStack_.empty()) {
1326 const clang::Type *canonicalType =
1327 type->getCanonicalTypeInternal().getTypePtr();
1328 AcavJson &properties = currentProperties();
1329 if (properties.contains(
"canonicalType")) {
1332 clang::QualType qt(canonicalType, 0);
1333 properties[
"canonicalType"] = getCachedTypeString(qt);
1334 if (
auto *builtinType = llvm::dyn_cast<clang::BuiltinType>(canonicalType)) {
1335 clang::PrintingPolicy policy(astContext_.getLangOpts());
1336 properties[
"typeName"] =
1337 InternedString(toStringView(builtinType->getName(policy)));
1339 if (
auto *arrayType =
1340 llvm::dyn_cast<clang::ConstantArrayType>(canonicalType)) {
1341 properties[
"size"] =
1342 static_cast<int64_t
>(arrayType->getSize().getZExtValue());
1347bool AcavAstVisitor::VisitTypeLoc(clang::TypeLoc typeLoc) {
1348 if (typeLoc.isNull() || parentStack_.empty()) {
1351 const clang::Type *type = typeLoc.getType().getTypePtr();
1352 AcavJson &properties = currentProperties();
1354 clang::SourceRange localRange = typeLoc.getLocalSourceRange();
1355 if (localRange.isValid()) {
1356 properties[
"hasLocalRange"] =
true;
1361bool AcavAstVisitor::VisitAttr(clang::Attr *attr) {
1362 if (!attr || parentStack_.empty()) {
1365 AcavJson &properties = currentProperties();
1366 properties[
"spelling"] = InternedString(attr->getSpelling());
1370bool AcavAstVisitor::VisitConceptReference(clang::ConceptReference *cr) {
1371 if (!cr || parentStack_.empty()) {
1374 AcavJson &properties = currentProperties();
1375 if (
auto *namedConcept = cr->getNamedConcept()) {
1376 maybeSetNamedDeclProperty(properties,
"name", namedConcept);
1381bool AcavAstVisitor::VisitCXXBaseSpecifier(
1382 const clang::CXXBaseSpecifier &spec) {
1383 if (parentStack_.empty()) {
1386 AcavJson &properties = currentProperties();
1387 clang::QualType baseType = spec.getType();
1388 if (!baseType.isNull()) {
1389 properties[
"baseType"] = getCachedTypeString(baseType);
1394bool AcavAstVisitor::VisitCXXCtorInitializer(
1395 clang::CXXCtorInitializer *init) {
1396 if (!init || parentStack_.empty()) {
1399 AcavJson &properties = currentProperties();
1400 if (init->isMemberInitializer() && init->getMember()) {
1401 maybeSetNamedDeclProperty(properties,
"member", init->getMember());
1406bool AcavAstVisitor::VisitLambdaCapture(
const clang::LambdaCapture *capture) {
1407 if (!capture || parentStack_.empty()) {
1410 AcavJson &properties = currentProperties();
1411 properties[
"captureKind"] =
static_cast<int64_t
>(capture->getCaptureKind());
1415bool AcavAstVisitor::VisitNestedNameSpecifier(
1416 clang::NestedNameSpecifier *nns) {
1417 if (!nns || parentStack_.empty()) {
1420 AcavJson &properties = currentProperties();
1421 std::string qualifierStr;
1422 llvm::raw_string_ostream os(qualifierStr);
1423 nns->print(os, astContext_.getPrintingPolicy());
1425 properties[
"qualifier"] = InternedString(qualifierStr);
1429bool AcavAstVisitor::VisitNestedNameSpecifierLoc(
1430 clang::NestedNameSpecifierLoc loc) {
1431 if (!loc || parentStack_.empty()) {
1434 AcavJson &properties = currentProperties();
1438bool AcavAstVisitor::VisitTemplateArgument(clang::TemplateArgument arg) {
1439 if (parentStack_.empty()) {
1442 AcavJson &properties = currentProperties();
1443 properties[
"argKind"] =
static_cast<int64_t
>(arg.getKind());
1444 switch (arg.getKind()) {
1445 case clang::TemplateArgument::Type:
1446 if (!arg.getAsType().isNull()) {
1447 properties[
"value"] = getCachedTypeString(arg.getAsType());
1450 case clang::TemplateArgument::Integral:
1451 properties[
"value"] = arg.getAsIntegral().getSExtValue();
1459bool AcavAstVisitor::VisitTemplateArgumentLoc(
1460 clang::TemplateArgumentLoc loc) {
1461 if (parentStack_.empty()) {
1464 AcavJson &properties = currentProperties();
1465 const clang::TemplateArgument &arg = loc.getArgument();
1466 properties[
"argKind"] =
static_cast<int64_t
>(arg.getKind());
1467 switch (arg.getKind()) {
1468 case clang::TemplateArgument::Type:
1469 if (!arg.getAsType().isNull()) {
1470 properties[
"value"] = getCachedTypeString(arg.getAsType());
1473 case clang::TemplateArgument::Integral:
1474 properties[
"value"] = arg.getAsIntegral().getSExtValue();
1482bool AcavAstVisitor::VisitTemplateName(clang::TemplateName name) {
1483 if (parentStack_.empty()) {
1486 AcavJson &properties = currentProperties();
1487 if (
auto *tempDecl = name.getAsTemplateDecl()) {
1488 if (
auto *namedDecl = llvm::dyn_cast<clang::NamedDecl>(tempDecl)) {
1489 maybeSetNamedDeclProperty(properties,
"name", namedDecl);
1498AstViewNode *AcavAstVisitor::createNodeFromDecl(clang::Decl *decl) {
1503 properties[
"kind"] = InternedString(getFullDeclClassName(decl));
1504 properties[
"isDecl"] =
true;
1505 clang::SourceRange clangRange = decl->getSourceRange();
1506 maybeAddMacroSpellingRange(properties, clangRange,
1507 astContext_.getSourceManager(), fileManager_);
1508 SourceRange auroraRange = SourceRange::fromClang(
1509 clangRange, astContext_.getSourceManager(), fileManager_);
1510 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1511 ++stats_.totalCount;
1513 return context_->createAstViewNode(astNode);
1516AstViewNode *AcavAstVisitor::createNodeFromStmt(clang::Stmt *stmt) {
1521 properties[
"kind"] = InternedString(stmt->getStmtClassName());
1522 clang::SourceRange clangRange = stmt->getSourceRange();
1523 maybeAddMacroSpellingRange(properties, clangRange,
1524 astContext_.getSourceManager(), fileManager_);
1525 SourceRange auroraRange = SourceRange::fromClang(
1526 clangRange, astContext_.getSourceManager(), fileManager_);
1527 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1528 ++stats_.totalCount;
1530 return context_->createAstViewNode(astNode);
1533AstViewNode *AcavAstVisitor::createNodeFromType(
const clang::Type *type) {
1537 const clang::Type *canonicalType =
1538 type->getCanonicalTypeInternal().getTypePtr();
1539 if (AstNode *existing = context_->findTypeNode(canonicalType)) {
1540 ++stats_.totalCount;
1542 return context_->createAstViewNode(existing);
1545 properties[
"kind"] = InternedString(getFullTypeClassName(type));
1546 SourceRange auroraRange = SourceRange::fromClang(
1547 clang::SourceRange(), astContext_.getSourceManager(), fileManager_);
1549 context_->getOrCreateTypeNode(canonicalType, properties, auroraRange);
1550 ++stats_.totalCount;
1552 return context_->createAstViewNode(astNode);
1555AstViewNode *AcavAstVisitor::createNodeFromTypeLoc(clang::TypeLoc typeLoc) {
1556 if (typeLoc.isNull()) {
1559 const clang::Type *type = typeLoc.getType().getTypePtr();
1561 properties[
"kind"] = InternedString(getFullTypeClassName(type));
1562 maybeAddMacroSpellingRange(properties, typeLoc.getSourceRange(),
1563 astContext_.getSourceManager(), fileManager_);
1564 SourceRange auroraRange = SourceRange::fromClang(
1565 typeLoc.getSourceRange(), astContext_.getSourceManager(), fileManager_);
1566 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1567 ++stats_.totalCount;
1568 ++stats_.typeLocCount;
1569 return context_->createAstViewNode(astNode);
1572AstViewNode *AcavAstVisitor::createNodeFromAttr(clang::Attr *attr) {
1577 properties[
"kind"] = InternedString(
"Attr");
1578 maybeAddMacroSpellingRange(properties, attr->getRange(),
1579 astContext_.getSourceManager(), fileManager_);
1580 SourceRange auroraRange = SourceRange::fromClang(
1581 attr->getRange(), astContext_.getSourceManager(), fileManager_);
1582 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1583 ++stats_.totalCount;
1585 return context_->createAstViewNode(astNode);
1589AcavAstVisitor::createNodeFromConceptRef(clang::ConceptReference *cr) {
1594 properties[
"kind"] = InternedString(
"ConceptReference");
1595 maybeAddMacroSpellingRange(properties, cr->getSourceRange(),
1596 astContext_.getSourceManager(), fileManager_);
1597 SourceRange auroraRange = SourceRange::fromClang(
1598 cr->getSourceRange(), astContext_.getSourceManager(), fileManager_);
1599 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1600 ++stats_.totalCount;
1601 ++stats_.conceptRefCount;
1602 return context_->createAstViewNode(astNode);
1605AstViewNode *AcavAstVisitor::createNodeFromCXXBaseSpec(
1606 const clang::CXXBaseSpecifier &spec) {
1608 properties[
"kind"] = InternedString(
"CXXBaseSpecifier");
1609 maybeAddMacroSpellingRange(properties, spec.getSourceRange(),
1610 astContext_.getSourceManager(), fileManager_);
1611 SourceRange auroraRange = SourceRange::fromClang(
1612 spec.getSourceRange(), astContext_.getSourceManager(), fileManager_);
1613 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1614 ++stats_.totalCount;
1615 ++stats_.cxxBaseSpecCount;
1616 return context_->createAstViewNode(astNode);
1620AcavAstVisitor::createNodeFromCtorInit(clang::CXXCtorInitializer *init) {
1625 properties[
"kind"] = InternedString(
"CXXCtorInitializer");
1626 maybeAddMacroSpellingRange(properties, init->getSourceRange(),
1627 astContext_.getSourceManager(), fileManager_);
1628 SourceRange auroraRange = SourceRange::fromClang(
1629 init->getSourceRange(), astContext_.getSourceManager(), fileManager_);
1630 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1631 ++stats_.totalCount;
1632 ++stats_.ctorInitCount;
1633 return context_->createAstViewNode(astNode);
1636AstViewNode *AcavAstVisitor::createNodeFromLambdaCapture(
1637 const clang::LambdaCapture *capture) {
1642 properties[
"kind"] = InternedString(
"LambdaCapture");
1643 SourceRange auroraRange = SourceRange::fromClang(
1644 clang::SourceRange(), astContext_.getSourceManager(), fileManager_);
1645 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1646 ++stats_.totalCount;
1647 ++stats_.lambdaCaptureCount;
1648 return context_->createAstViewNode(astNode);
1651#if LLVM_VERSION_MAJOR >= 22
1652AstViewNode *AcavAstVisitor::createNodeFromNestedNameSpec(
1653 clang::NestedNameSpecifier nns) {
1658AstViewNode *AcavAstVisitor::createNodeFromNestedNameSpec(
1659 clang::NestedNameSpecifier *nns) {
1665 properties[
"kind"] = InternedString(
"NestedNameSpecifier");
1666 SourceRange auroraRange = SourceRange::fromClang(
1667 clang::SourceRange(), astContext_.getSourceManager(), fileManager_);
1668 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1669 ++stats_.totalCount;
1670 ++stats_.nestedNameSpecCount;
1671 return context_->createAstViewNode(astNode);
1674AstViewNode *AcavAstVisitor::createNodeFromNestedNameSpecLoc(
1675 clang::NestedNameSpecifierLoc loc) {
1680 properties[
"kind"] = InternedString(
"NestedNameSpecifierLoc");
1681 maybeAddMacroSpellingRange(properties, loc.getSourceRange(),
1682 astContext_.getSourceManager(), fileManager_);
1683 SourceRange auroraRange = SourceRange::fromClang(
1684 loc.getSourceRange(), astContext_.getSourceManager(), fileManager_);
1685 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1686 ++stats_.totalCount;
1687 ++stats_.nestedNameSpecLocCount;
1688 return context_->createAstViewNode(astNode);
1692AcavAstVisitor::createNodeFromTemplateArg(clang::TemplateArgument arg) {
1694 properties[
"kind"] = InternedString(
"TemplateArgument");
1695 SourceRange auroraRange = SourceRange::fromClang(
1696 clang::SourceRange(), astContext_.getSourceManager(), fileManager_);
1697 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1698 ++stats_.totalCount;
1699 ++stats_.tempArgCount;
1700 return context_->createAstViewNode(astNode);
1704AcavAstVisitor::createNodeFromTemplateArgLoc(clang::TemplateArgumentLoc loc) {
1706 properties[
"kind"] = InternedString(
"TemplateArgumentLoc");
1707 maybeAddMacroSpellingRange(properties, loc.getSourceRange(),
1708 astContext_.getSourceManager(), fileManager_);
1709 SourceRange auroraRange = SourceRange::fromClang(
1710 loc.getSourceRange(), astContext_.getSourceManager(), fileManager_);
1711 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1712 ++stats_.totalCount;
1713 ++stats_.tempArgLocCount;
1714 return context_->createAstViewNode(astNode);
1718AcavAstVisitor::createNodeFromTemplateName(clang::TemplateName name) {
1720 properties[
"kind"] = InternedString(
"TemplateName");
1721 SourceRange auroraRange = SourceRange::fromClang(
1722 clang::SourceRange(), astContext_.getSourceManager(), fileManager_);
1723 AstNode *astNode = context_->createAstNode(properties, auroraRange);
1724 ++stats_.totalCount;
1725 ++stats_.tempNameCount;
1726 return context_->createAstViewNode(astNode);
1735 bool extractComments) {
1739 clang::ASTContext &ctx = astUnit.getASTContext();
1740 clang::TranslationUnitDecl *tuDecl = ctx.getTranslationUnitDecl();
1744 AcavAstVisitor visitor(context, fileManager, ctx,
1745 astUnit.getPreprocessorPtr().get(), extractComments);
1746 visitor.TraverseDecl(tuDecl);
1747 stats = visitor.getStats();
1748 return visitor.getRootNode();
Clang AST to ACAV AST transformation.
nlohmann::basic_json< std::map, std::vector, InternedString, bool, int64_t, uint64_t, double, std::allocator, nlohmann::adl_serializer, std::vector< uint8_t > > AcavJson
Custom JSON type using InternedString for automatic string deduplication.
static AstViewNode * buildFromASTUnit(clang::ASTUnit &astUnit, AstContext *context, FileManager &fileManager, AstExtractionStats &stats, bool extractComments=false)
Build ACAV AST from Clang ASTUnit.
Memory manager for AST nodes in a translation unit.
Represents node in AST tree hierarchy.
Centralized file registry providing path-to-FileID mapping.
Immutable string with automatic deduplication via global pool.
Represents a specific position in source code.
Represents a span of source code (begin to end).
static SourceRange fromClang(const clang::SourceRange &range, const clang::SourceManager &sm, FileManager &fileMgr)
Create SourceRange from Clang's SourceRange.