#include "data/parser/cxx/CxxAstVisitor.h" #include #include #include "data/parser/cxx/name_resolver/CxxDeclNameResolver.h" #include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h" #include "data/parser/cxx/CanonicalFilePathCache.h" #include "data/parser/cxx/CxxAstVisitorComponent.h" #include "data/parser/cxx/CxxAstVisitorComponentContext.h" #include "data/parser/cxx/CxxAstVisitorComponentDeclRefKind.h" #include "data/parser/cxx/CxxAstVisitorComponentTypeRefKind.h" #include "data/parser/cxx/CxxAstVisitorComponentImplicitCode.h" #include "data/parser/cxx/CxxAstVisitorComponentIndexer.h" #include "data/parser/cxx/utilityClang.h" #include "data/parser/ParserClient.h" #include "data/parser/ParseLocation.h" #include "utility/file/FileRegister.h" #include "utility/utilityString.h" CxxAstVisitor::CxxAstVisitor( clang::ASTContext* astContext, clang::Preprocessor* preprocessor, std::shared_ptr client, std::shared_ptr fileRegister, std::shared_ptr canonicalFilePathCache ) : m_astContext(astContext) , m_preprocessor(preprocessor) , m_client(client) , m_fileRegister(fileRegister) , m_canonicalFilePathCache(canonicalFilePathCache) { m_declNameCache = std::make_shared([&](const clang::NamedDecl* decl) -> NameHierarchy { if (decl) { CxxDeclNameResolver resolver(m_canonicalFilePathCache); if (std::shared_ptr declName = resolver.getName(decl)) { return declName->toNameHierarchy(); } } return NameHierarchy(L"global", NAME_DELIMITER_UNKNOWN); } ); m_typeNameCache = std::make_shared([&](const clang::Type* type) -> NameHierarchy { if (type) { CxxTypeNameResolver resolver(m_canonicalFilePathCache); if (std::shared_ptr typeName = resolver.getName(type)) { return typeName->toNameHierarchy(); } } return NameHierarchy(L"global", NAME_DELIMITER_UNKNOWN); } ); m_contextComponent = std::make_shared(this); m_components.push_back(m_contextComponent); m_typeRefKindComponent = std::make_shared(this); m_components.push_back(m_typeRefKindComponent); m_declRefKindComponent = std::make_shared(this); m_components.push_back(m_declRefKindComponent); m_implicitCodeComponent = std::make_shared(this); m_components.push_back(m_implicitCodeComponent); m_indexerComponent = std::make_shared(this, astContext, client, fileRegister); m_components.push_back(m_indexerComponent); } CxxAstVisitor::~CxxAstVisitor() { } template <> std::shared_ptr CxxAstVisitor::getComponent() { return m_contextComponent; } template <> std::shared_ptr CxxAstVisitor::getComponent() { return m_typeRefKindComponent; } template <> std::shared_ptr CxxAstVisitor::getComponent() { return m_declRefKindComponent; } template <> std::shared_ptr CxxAstVisitor::getComponent() { return m_indexerComponent; } std::shared_ptr CxxAstVisitor::getDeclNameCache() { return m_declNameCache; } std::shared_ptr CxxAstVisitor::getTypeNameCache() { return m_typeNameCache; } std::shared_ptr CxxAstVisitor::getCanonicalFilePathCache() { return m_canonicalFilePathCache; } void CxxAstVisitor::indexDecl(clang::Decl* d) { this->TraverseDecl(d); } bool CxxAstVisitor::shouldVisitTemplateInstantiations() const { return true; } bool CxxAstVisitor::shouldVisitImplicitCode() const { return m_implicitCodeComponent->shouldVisitImplicitCode(); } bool CxxAstVisitor::checkIgnoresTypeLoc(const clang::TypeLoc& tl) const { if ((!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull())) { return false; } return true; } #define DEF_TRAVERSE_CUSTOM_TYPE_PTR(__NAME_TYPE__, __PARAM_TYPE__, CODE_BEFORE, CODE_AFTER) \ bool CxxAstVisitor::Traverse##__NAME_TYPE__(clang::__PARAM_TYPE__* v) \ { \ for (auto it = m_components.begin(); it != m_components.end(); it++) \ { \ (*it)->beginTraverse##__NAME_TYPE__(v); \ } \ bool ret = true; \ { CODE_BEFORE; } \ Base::Traverse##__NAME_TYPE__(v); \ { CODE_AFTER; } \ for (auto it = m_components.rbegin(); it != m_components.rend(); it++) \ { \ (*it)->endTraverse##__NAME_TYPE__(v); \ } \ return ret; \ } #define DEF_TRAVERSE_CUSTOM_TYPE(__NAME_TYPE__, __PARAM_TYPE__, CODE_BEFORE, CODE_AFTER) \ bool CxxAstVisitor::Traverse##__NAME_TYPE__(clang::__PARAM_TYPE__ v) \ { \ for (auto it = m_components.begin(); it != m_components.end(); it++) \ { \ (*it)->beginTraverse##__NAME_TYPE__(v); \ } \ bool ret = true; \ { CODE_BEFORE; } \ Base::Traverse##__NAME_TYPE__(v); \ { CODE_AFTER; } \ for (auto it = m_components.rbegin(); it != m_components.rend(); it++) \ { \ (*it)->endTraverse##__NAME_TYPE__(v); \ } \ return ret; \ } #define DEF_TRAVERSE_TYPE_PTR(__TYPE__, CODE_BEFORE, CODE_AFTER) \ DEF_TRAVERSE_CUSTOM_TYPE_PTR(__TYPE__, __TYPE__, CODE_BEFORE, CODE_AFTER) #define DEF_TRAVERSE_TYPE(__TYPE__, CODE_BEFORE, CODE_AFTER) \ DEF_TRAVERSE_CUSTOM_TYPE(__TYPE__, __TYPE__, CODE_BEFORE, CODE_AFTER) bool CxxAstVisitor::TraverseDecl(clang::Decl* decl) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseDecl(decl); } bool ret = m_interruptCounter.getCount() == 0; bool traverse = true; if (decl) { clang::SourceLocation loc = m_astContext->getSourceManager().getExpansionLoc(decl->getLocation()); if (loc.isInvalid()) { loc = decl->getLocation(); } if (loc.isValid()) { traverse = isLocatedInProjectFile(loc); } } if (traverse) { Base::TraverseDecl(decl); } for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseDecl(decl); } return ret; } // same as Base::TraverseQualifiedTypeLoc(..) but we need to make sure to call this.TraverseTypeLoc(..) bool CxxAstVisitor::TraverseQualifiedTypeLoc(clang::QualifiedTypeLoc tl) { return TraverseTypeLoc(tl.getUnqualifiedLoc()); } DEF_TRAVERSE_TYPE(TypeLoc, {}, {}) DEF_TRAVERSE_CUSTOM_TYPE(Type, QualType, {}, {}) DEF_TRAVERSE_TYPE_PTR(Stmt, {}, {}) // same as Base::TraverseCXXRecordDecl(..) but we need to integrate the setter for the context info. // additionally: skip implicit CXXRecordDecls (this does not skip template specializations). bool CxxAstVisitor::TraverseCXXRecordDecl(clang::CXXRecordDecl *d) { if (utility::isImplicit(d) && d->getMemberSpecializationInfo() == nullptr) { return true; } WalkUpFromCXXRecordDecl(d); TraverseNestedNameSpecifierLoc(d->getQualifierLoc()); if (d->isCompleteDefinition()) { for (const auto& base : d->bases()) { if (!traverseCXXBaseSpecifier(base)) { return false; } } } traverseDeclContextHelper(clang::dyn_cast(d)); return true; } bool CxxAstVisitor::traverseCXXBaseSpecifier(const clang::CXXBaseSpecifier& d) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseCXXBaseSpecifier(); } bool ret = TraverseTypeLoc(d.getTypeSourceInfo()->getTypeLoc()); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseCXXBaseSpecifier(); } return ret; } // same as Base::TraverseTemplateTypeParmDecl(..) but we need to integrate the setter for the context info. bool CxxAstVisitor::TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d) { WalkUpFromTemplateTypeParmDecl(d); if (d->hasDefaultArgument() && !d->defaultArgumentWasInherited()) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseTemplateDefaultArgumentLoc(); } TraverseTypeLoc(d->getDefaultArgumentInfo()->getTypeLoc()); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseTemplateDefaultArgumentLoc(); } } traverseDeclContextHelper(clang::dyn_cast(d)); return true; } // same as Base::TraverseTemplateTemplateParmDecl(..) but we need to integrate the setter for the context info. bool CxxAstVisitor::TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d) { WalkUpFromTemplateTemplateParmDecl(d); TraverseDecl(d->getTemplatedDecl()); if (d->hasDefaultArgument() && !d->defaultArgumentWasInherited()) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseTemplateDefaultArgumentLoc(); } TraverseTemplateArgumentLoc(d->getDefaultArgument()); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseTemplateDefaultArgumentLoc(); } } clang::TemplateParameterList* TPL = d->getTemplateParameters(); if (TPL) { for (clang::TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); I != E; ++I) { TraverseDecl(*I); } } traverseDeclContextHelper(clang::dyn_cast(d)); return true; } bool CxxAstVisitor::VisitTranslationUnitDecl(clang::TranslationUnitDecl *d) { return true; } bool CxxAstVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc loc) { bool ret = true; if (loc) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseNestedNameSpecifierLoc(loc); } //todo: call method of base class... if (clang::NestedNameSpecifierLoc prefix = loc.getPrefix()) { ret = TraverseNestedNameSpecifierLoc(prefix); } for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseNestedNameSpecifierLoc(loc); } } return ret; } bool CxxAstVisitor::TraverseConstructorInitializer(clang::CXXCtorInitializer* init) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseConstructorInitializer(init); } if (!VisitConstructorInitializer(init)) { return false; } bool ret = Base::TraverseConstructorInitializer(init); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseConstructorInitializer(init); } return ret; } bool CxxAstVisitor::TraverseCallExpr(clang::CallExpr* s) { return TraverseCallCommon(s); } bool CxxAstVisitor::TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr* s) { return TraverseCallCommon(s); } bool CxxAstVisitor::TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr* s) { return TraverseCallCommon(s); } bool CxxAstVisitor::TraverseCXXConstructExpr(clang::CXXConstructExpr* s) { { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseCallCommonCallee(); } WalkUpFromCXXConstructExpr(s); for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->endTraverseCallCommonCallee(); } } for (unsigned int i = 0; i < s->getNumArgs(); ++i) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseCallCommonArgument(); } TraverseStmt(s->getArg(i)); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseCallCommonArgument(); } } return true; } DEF_TRAVERSE_TYPE_PTR(CXXTemporaryObjectExpr, {}, {}) DEF_TRAVERSE_TYPE_PTR(LambdaExpr, {}, {}) DEF_TRAVERSE_TYPE_PTR(FunctionDecl, {}, {}) DEF_TRAVERSE_TYPE_PTR(ClassTemplateSpecializationDecl, {}, {}) DEF_TRAVERSE_TYPE_PTR(ClassTemplatePartialSpecializationDecl, {}, {}) DEF_TRAVERSE_TYPE_PTR(DeclRefExpr, {}, {}) DEF_TRAVERSE_TYPE_PTR(CXXForRangeStmt, {}, {}) DEF_TRAVERSE_TYPE(TemplateSpecializationTypeLoc, {}, {}) DEF_TRAVERSE_TYPE_PTR(UnresolvedLookupExpr, {}, {}) DEF_TRAVERSE_TYPE_PTR(UnresolvedMemberExpr, {}, {}) bool CxxAstVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseTemplateArgumentLoc(loc); } bool ret = Base::TraverseTemplateArgumentLoc(loc); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseTemplateArgumentLoc(loc); } return ret; } bool CxxAstVisitor::TraverseLambdaCapture(clang::LambdaExpr *lambdaExpr, const clang::LambdaCapture *capture, clang::Expr *Init) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseLambdaCapture(lambdaExpr, capture); } bool ret = true; if (lambdaExpr->isInitCapture(capture)) { ret = TraverseDecl(capture->getCapturedVar()); } for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseLambdaCapture(lambdaExpr, capture); } return ret; } bool CxxAstVisitor::TraverseBinComma(clang::BinaryOperator* s) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseBinCommaLhs(); } TraverseStmt(s->getLHS()); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseBinCommaLhs(); } for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseBinCommaRhs(); } TraverseStmt(s->getRHS()); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseBinCommaRhs(); } return true; } bool CxxAstVisitor::TraverseDeclarationNameInfo(clang::DeclarationNameInfo NameInfo) { // we don't visit any children here return true; } void CxxAstVisitor::traverseDeclContextHelper(clang::DeclContext* d) { if (!d) { return; } for (auto* child : d->decls()) { // BlockDecls and CapturedDecls are traversed through BlockExprs and // CapturedStmts respectively. if (!llvm::isa(child) && !llvm::isa(child)) { TraverseDecl(child); } } } bool CxxAstVisitor::TraverseCallCommon(clang::CallExpr* s) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseCallCommonCallee(); } TraverseStmt(s->getCallee()); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseCallCommonCallee(); } for (unsigned int i = 0; i < s->getNumArgs(); ++i) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseCallCommonArgument(); } TraverseStmt(s->getArg(i)); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseCallCommonArgument(); } } return true; } bool CxxAstVisitor::TraverseAssignCommon(clang::BinaryOperator* s) { for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseAssignCommonLhs(); } TraverseStmt(s->getLHS()); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseAssignCommonLhs(); } for (auto it = m_components.begin(); it != m_components.end(); it++) { (*it)->beginTraverseAssignCommonRhs(); } TraverseStmt(s->getRHS()); for (auto it = m_components.rbegin(); it != m_components.rend(); it++) { (*it)->endTraverseAssignCommonRhs(); } return true; } #undef DEF_TRAVERSE_CUSTOM_TYPE_PTR #undef DEF_TRAVERSE_CUSTOM_TYPE #undef DEF_TRAVERSE_TYPE_PTR #undef DEF_TRAVERSE_TYPE #define DEF_VISIT_CUSTOM_TYPE_PTR(__NAME_TYPE__, __PARAM_TYPE__) \ bool CxxAstVisitor::Visit##__NAME_TYPE__(clang::__PARAM_TYPE__* v) \ { \ for (auto it = m_components.begin(); it != m_components.end(); it++) \ { \ (*it)->visit##__NAME_TYPE__(v); \ } \ return true; \ } #define DEF_VISIT_CUSTOM_TYPE(__NAME_TYPE__, __PARAM_TYPE__) \ bool CxxAstVisitor::Visit##__NAME_TYPE__(clang::__PARAM_TYPE__ v) \ { \ for (auto it = m_components.begin(); it != m_components.end(); it++) \ { \ (*it)->visit##__NAME_TYPE__(v); \ } \ return true; \ } #define DEF_VISIT_TYPE_PTR(__TYPE__) \ DEF_VISIT_CUSTOM_TYPE_PTR(__TYPE__, __TYPE__) #define DEF_VISIT_TYPE(__TYPE__) \ DEF_VISIT_CUSTOM_TYPE(__TYPE__, __TYPE__) DEF_VISIT_TYPE_PTR(CastExpr) DEF_VISIT_CUSTOM_TYPE_PTR(UnaryAddrOf, UnaryOperator) DEF_VISIT_CUSTOM_TYPE_PTR(UnaryDeref, UnaryOperator) DEF_VISIT_TYPE_PTR(DeclStmt) DEF_VISIT_TYPE_PTR(ReturnStmt) DEF_VISIT_TYPE_PTR(InitListExpr) DEF_VISIT_TYPE_PTR(TagDecl) DEF_VISIT_TYPE_PTR(ClassTemplateSpecializationDecl) DEF_VISIT_TYPE_PTR(FunctionDecl) DEF_VISIT_TYPE_PTR(CXXMethodDecl) DEF_VISIT_TYPE_PTR(VarDecl) DEF_VISIT_TYPE_PTR(VarTemplateSpecializationDecl) DEF_VISIT_TYPE_PTR(FieldDecl) DEF_VISIT_TYPE_PTR(TypedefDecl) DEF_VISIT_TYPE_PTR(TypeAliasDecl) DEF_VISIT_TYPE_PTR(NamespaceDecl) DEF_VISIT_TYPE_PTR(NamespaceAliasDecl) DEF_VISIT_TYPE_PTR(EnumConstantDecl) DEF_VISIT_TYPE_PTR(UsingDirectiveDecl) DEF_VISIT_TYPE_PTR(UsingDecl) DEF_VISIT_TYPE_PTR(NonTypeTemplateParmDecl) DEF_VISIT_TYPE_PTR(TemplateTypeParmDecl) DEF_VISIT_TYPE_PTR(TemplateTemplateParmDecl) DEF_VISIT_TYPE(TypeLoc) DEF_VISIT_TYPE_PTR(DeclRefExpr) DEF_VISIT_TYPE_PTR(MemberExpr) DEF_VISIT_TYPE_PTR(CXXDependentScopeMemberExpr) DEF_VISIT_TYPE_PTR(CXXConstructExpr) DEF_VISIT_TYPE_PTR(LambdaExpr) DEF_VISIT_CUSTOM_TYPE_PTR(ConstructorInitializer, CXXCtorInitializer) #undef DEF_VISIT_CUSTOM_TYPE_PTR #undef DEF_VISIT_CUSTOM_TYPE #undef DEF_VISIT_TYPE_PTR #undef DEF_VISIT_TYPE ParseLocation CxxAstVisitor::getParseLocationOfTagDeclBody(clang::TagDecl* decl) const { if (decl->isThisDeclarationADefinition()) { clang::SourceRange range; if (clang::CXXRecordDecl* cxxDecl = clang::dyn_cast_or_null(decl)) { clang::ClassTemplateDecl* templateDecl = cxxDecl->getDescribedClassTemplate(); if (templateDecl) { range = templateDecl->getSourceRange(); } } if (range.isInvalid()) { range = decl->getDefinition()->getSourceRange(); } return getParseLocation(range); } return ParseLocation(); } ParseLocation CxxAstVisitor::getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const { if (decl->hasBody() && decl->isThisDeclarationADefinition()) { clang::SourceRange range; clang::FunctionTemplateDecl* templateDecl = decl->getDescribedFunctionTemplate(); if (templateDecl) { range = templateDecl->getSourceRange(); } else { range = decl->getSourceRange(); } return getParseLocation(range); } return ParseLocation(); } ParseLocation CxxAstVisitor::getParseLocation(const clang::SourceLocation& sourceLocation) const { ParseLocation parseLocation; if (sourceLocation.isValid()) { const clang::SourceManager& sourceManager = m_astContext->getSourceManager(); clang::SourceLocation loc = sourceLocation; if (sourceManager.isMacroBodyExpansion(sourceLocation)) { loc = sourceManager.getExpansionLoc(sourceLocation); if (loc.isInvalid()) { loc = sourceLocation; } } const clang::SourceLocation startLoc = sourceManager.getSpellingLoc(loc); const clang::FileID fileId = sourceManager.getFileID(startLoc); // find the location file if (!fileId.isInvalid()) { const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); if (fileEntry != nullptr && fileEntry->isValid()) { parseLocation.filePath = m_canonicalFilePathCache->getCanonicalFilePath(fileEntry); } } // find the start location { const unsigned int offset = sourceManager.getFileOffset(startLoc); parseLocation.startLineNumber = sourceManager.getLineNumber(fileId, offset); parseLocation.startColumnNumber = sourceManager.getColumnNumber(fileId, offset); } // General case -- find the end of the token starting at loc. { const clang::SourceLocation endSloc = m_preprocessor->getLocForEndOfToken(startLoc); const unsigned int offset = sourceManager.getFileOffset(endSloc); parseLocation.endLineNumber = sourceManager.getLineNumber(fileId, offset); parseLocation.endColumnNumber = sourceManager.getColumnNumber(fileId, offset) - 1; } } return parseLocation; } ParseLocation CxxAstVisitor::getParseLocation(const clang::SourceRange& sourceRange) const { ParseLocation parseLocation; if (sourceRange.isValid()) { const clang::SourceManager& sourceManager = m_astContext->getSourceManager(); clang::SourceRange range = sourceRange; clang::SourceLocation endLoc = m_preprocessor->getLocForEndOfToken(range.getEnd()); if (( sourceManager.isMacroArgExpansion(range.getBegin()) || sourceManager.isMacroBodyExpansion(range.getBegin()) ) && ( sourceManager.isMacroArgExpansion(range.getEnd()) || sourceManager.isMacroBodyExpansion(range.getEnd()) )) { range = sourceManager.getExpansionRange(sourceRange); if (range.isValid()) { endLoc = m_preprocessor->getLocForEndOfToken(range.getBegin()); } else { range = sourceRange; } } const clang::SourceLocation beginLoc = range.getBegin(); const clang::PresumedLoc presumedBegin = sourceManager.getPresumedLoc(beginLoc, false); const clang::PresumedLoc presumedEnd = sourceManager.getPresumedLoc(endLoc.isValid() ? endLoc : range.getEnd(), false); FilePath filePath; { const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(sourceManager.getFileID(beginLoc)); if (fileEntry != nullptr && fileEntry->isValid()) { filePath = m_canonicalFilePathCache->getCanonicalFilePath(fileEntry); } else { filePath = m_canonicalFilePathCache->getCanonicalFilePath(utility::decodeFromUtf8(presumedBegin.getFilename())); } } parseLocation = ParseLocation( filePath, presumedBegin.getLine(), presumedBegin.getColumn(), presumedEnd.getLine(), presumedEnd.getColumn() - (endLoc.isValid() ? 1 : 0) ); } return parseLocation; } bool CxxAstVisitor::isLocatedInProjectFile(clang::SourceLocation loc) { const clang::SourceManager& sourceManager = m_astContext->getSourceManager(); clang::FileID fileId; if (loc.isValid()) { if (sourceManager.isWrittenInMainFile(loc)) { return true; } fileId = sourceManager.getFileID(loc); } if (fileId.isValid()) { auto it = m_inProjectFileMap.find(fileId); if (it != m_inProjectFileMap.end()) { return it->second; } const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); if (fileEntry != nullptr && fileEntry->isValid()) { FilePath filePath = getCanonicalFilePathCache()->getCanonicalFilePath(fileEntry); const bool ret = m_fileRegister->hasFilePath(filePath); m_inProjectFileMap[fileId] = ret; return ret; } } return false; }