data: revised indexing
* increased performance. coati is now 1.55 times as fast as at version 0.4 * integrated sourceweb parsing code * removed astbodyvisitor * NameHierarchy now store signatures in a new format * storage does not allow to re-set the type of a node, once it is marked as "defined". * made onTemplateRecordSpecParsed just create the edge, not the node. * removed distinction between template specialitzations for functions and classes
This commit is contained in:
@@ -18,7 +18,7 @@ ASTAction::~ASTAction()
|
||||
|
||||
std::unique_ptr<clang::ASTConsumer> ASTAction::CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile)
|
||||
{
|
||||
return std::unique_ptr<clang::ASTConsumer>(new ASTConsumer(&compiler.getASTContext(), m_client, m_fileRegister));
|
||||
return std::unique_ptr<clang::ASTConsumer>(new ASTConsumer(&compiler.getASTContext(), &compiler.getPreprocessor(), m_client, m_fileRegister));
|
||||
}
|
||||
|
||||
bool ASTAction::BeginSourceFileAction(clang::CompilerInstance& compiler, llvm::StringRef filePath)
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
#include "data/parser/cxx/ASTBodyVisitor.h"
|
||||
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
|
||||
ASTBodyVisitor::ASTBodyVisitor(ASTBodyVisitorClient* client, clang::FunctionDecl* functionDecl)
|
||||
: m_client(client)
|
||||
, m_functionDecl(functionDecl)
|
||||
, m_varDecl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ASTBodyVisitor::ASTBodyVisitor(ASTBodyVisitorClient* client, clang::DeclaratorDecl* varDecl)
|
||||
: m_client(client)
|
||||
, m_functionDecl(nullptr)
|
||||
, m_varDecl(varDecl)
|
||||
{
|
||||
}
|
||||
|
||||
ASTBodyVisitor::~ASTBodyVisitor()
|
||||
{
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitStmt(clang::Stmt* stmt)
|
||||
{
|
||||
VisitChildren(stmt);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitChildren(clang::Stmt* stmt)
|
||||
{
|
||||
for (clang::Stmt::child_iterator it = stmt->child_begin(); it != stmt->child_end(); it++)
|
||||
{
|
||||
if (*it)
|
||||
{
|
||||
static_cast<ASTBodyVisitor*>(this)->Visit(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitCallExpr(clang::CallExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitCallExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitCallExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitCXXConstructExpr(clang::CXXConstructExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitCXXConstructExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitCXXConstructExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitExplicitCastExpr(clang::ExplicitCastExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitExplicitCastExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitExplicitCastExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitCXXTemporaryObjectExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitCXXTemporaryObjectExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitCXXNewExpr(clang::CXXNewExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitCXXNewExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitCXXNewExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitMemberExpr(clang::make_ptr<clang::MemberExpr>::type expr)
|
||||
{
|
||||
if (expr->getMemberDecl()->getKind() == clang::Decl::Kind::Field)
|
||||
{
|
||||
if(m_functionDecl)
|
||||
{
|
||||
m_client->VisitMemberExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitMemberExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
}
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitDeclRefExpr(clang::DeclRefExpr* expr)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitDeclRefExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitDeclRefExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
|
||||
if (expr->getDecl()->getKind() == clang::Decl::Var && expr->getDecl()->isDefinedOutsideFunctionOrMethod())
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitGlobalVariableExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitGlobalVariableExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
}
|
||||
else if (expr->getDecl()->getKind() == clang::Decl::EnumConstant)
|
||||
{
|
||||
if (m_functionDecl)
|
||||
{
|
||||
m_client->VisitEnumExprInDeclBody(m_functionDecl, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->VisitEnumExprInDeclBody(m_varDecl, expr);
|
||||
}
|
||||
}
|
||||
|
||||
VisitStmt(expr);
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitLambdaExpr(clang::LambdaExpr* expr)
|
||||
{
|
||||
// Don't visit the lambda's children. The ASTVisitor creates a new ASTBodyVisitor for these.
|
||||
}
|
||||
|
||||
void ASTBodyVisitor::VisitDeclStmt(clang::DeclStmt* stmt)
|
||||
{
|
||||
for (clang::Decl* decl : stmt->decls())
|
||||
{
|
||||
if (clang::isa<clang::VarDecl>(decl))
|
||||
{
|
||||
m_client->VisitVarDeclInDeclBody(m_functionDecl, clang::dyn_cast<clang::VarDecl>(decl));
|
||||
}
|
||||
}
|
||||
VisitStmt(stmt);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#ifndef AST_BODY_VISITOR
|
||||
#define AST_BODY_VISITOR
|
||||
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "data/parser/cxx/ASTBodyVisitorClient.h"
|
||||
|
||||
class ASTBodyVisitor: public clang::StmtVisitor<ASTBodyVisitor>
|
||||
{
|
||||
public:
|
||||
ASTBodyVisitor(ASTBodyVisitorClient* client, clang::FunctionDecl* functionDecl);
|
||||
ASTBodyVisitor(ASTBodyVisitorClient* client, clang::DeclaratorDecl* varDecl);
|
||||
virtual ~ASTBodyVisitor();
|
||||
|
||||
void VisitStmt(clang::Stmt* stmt);
|
||||
void VisitChildren(clang::Stmt* stmt);
|
||||
void VisitCallExpr(clang::CallExpr* expr);
|
||||
void VisitCXXConstructExpr(clang::CXXConstructExpr* expr);
|
||||
void VisitExplicitCastExpr(clang::ExplicitCastExpr* expr);
|
||||
void VisitCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* expr);
|
||||
void VisitCXXNewExpr(clang::CXXNewExpr* expr);
|
||||
void VisitMemberExpr(clang::make_ptr<clang::MemberExpr>::type expr);
|
||||
void VisitDeclRefExpr(clang::make_ptr<clang::DeclRefExpr>::type expr);
|
||||
void VisitLambdaExpr(clang::LambdaExpr* expr);
|
||||
void VisitDeclStmt(clang::DeclStmt* stmt);
|
||||
|
||||
private:
|
||||
ASTBodyVisitorClient* m_client;
|
||||
clang::FunctionDecl* m_functionDecl;
|
||||
clang::DeclaratorDecl* m_varDecl;
|
||||
};
|
||||
|
||||
#endif // AST_BODY_VISITOR
|
||||
@@ -1,9 +0,0 @@
|
||||
#include "data/parser/cxx/ASTBodyVisitorClient.h"
|
||||
|
||||
ASTBodyVisitorClient::ASTBodyVisitorClient()
|
||||
{
|
||||
}
|
||||
|
||||
ASTBodyVisitorClient::~ASTBodyVisitorClient()
|
||||
{
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#ifndef AST_BODY_VISITOR_CLIENT_H
|
||||
#define AST_BODY_VISITOR_CLIENT_H
|
||||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
|
||||
class ASTBodyVisitorClient
|
||||
{
|
||||
public:
|
||||
ASTBodyVisitorClient();
|
||||
virtual ~ASTBodyVisitorClient();
|
||||
|
||||
virtual void VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallExpr* expr) = 0;
|
||||
virtual void VisitCallExprInDeclBody(clang::DeclaratorDecl* decl, clang::CallExpr* expr) = 0;
|
||||
virtual void VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0;
|
||||
virtual void VisitDeclRefExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr) = 0;
|
||||
virtual void VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr) = 0;
|
||||
virtual void VisitCXXConstructExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXConstructExpr* expr) = 0;
|
||||
virtual void VisitExplicitCastExprInDeclBody(clang::FunctionDecl* decl, clang::ExplicitCastExpr* expr) = 0;
|
||||
virtual void VisitExplicitCastExprInDeclBody(clang::DeclaratorDecl* decl, clang::ExplicitCastExpr* expr) = 0;
|
||||
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::FunctionDecl* decl, clang::CXXTemporaryObjectExpr* expr) = 0;
|
||||
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXTemporaryObjectExpr* expr) = 0;
|
||||
virtual void VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr) = 0;
|
||||
virtual void VisitCXXNewExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXNewExpr* expr) = 0;
|
||||
virtual void VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr) = 0;
|
||||
virtual void VisitMemberExprInDeclBody(clang::DeclaratorDecl* decl, clang::MemberExpr* expr) = 0;
|
||||
virtual void VisitGlobalVariableExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0;
|
||||
virtual void VisitGlobalVariableExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr) = 0;
|
||||
virtual void VisitEnumExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr) = 0;
|
||||
virtual void VisitEnumExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr) = 0;
|
||||
virtual void VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl) = 0;
|
||||
};
|
||||
|
||||
#endif // AST_BODY_VISITOR_CLIENT_H
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#include "data/parser/ParserClient.h"
|
||||
|
||||
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister)
|
||||
: m_visitor(context, client, fileRegister)
|
||||
ASTConsumer::ASTConsumer(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister)
|
||||
: m_visitor(context, preprocessor, client, fileRegister)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ ASTConsumer::~ASTConsumer()
|
||||
|
||||
void ASTConsumer::HandleTranslationUnit(clang::ASTContext& context)
|
||||
{
|
||||
m_visitor.TraverseDecl(context.getTranslationUnitDecl());
|
||||
m_visitor.indexDecl(context.getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class ASTConsumer
|
||||
: public clang::ASTConsumer
|
||||
{
|
||||
public:
|
||||
explicit ASTConsumer(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister);
|
||||
explicit ASTConsumer(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister);
|
||||
virtual ~ASTConsumer();
|
||||
|
||||
virtual void HandleTranslationUnit(clang::ASTContext& context);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,108 +4,320 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include <clang/AST/RecursiveASTVisitor.h>
|
||||
#include <clang/Basic/SourceLocation.h>
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
|
||||
#include "data/parser/ParserClient.h"
|
||||
#include "utility/file/FileRegister.h"
|
||||
|
||||
#include "data/parser/cxx/ASTBodyVisitorClient.h"
|
||||
#include "data/parser/ParserClient.h"
|
||||
|
||||
class ASTVisitor
|
||||
: public clang::RecursiveASTVisitor<ASTVisitor>
|
||||
, public ASTBodyVisitorClient
|
||||
|
||||
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
|
||||
#include "data/parser/cxx/utilityCxx.h"
|
||||
|
||||
class ASTVisitor: clang::RecursiveASTVisitor<ASTVisitor>
|
||||
{
|
||||
public:
|
||||
ASTVisitor(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister);
|
||||
virtual ~ASTVisitor();
|
||||
|
||||
class TypeNameCache
|
||||
{
|
||||
public:
|
||||
NameHierarchy getName(const clang::Type* type)
|
||||
{
|
||||
if (type)
|
||||
{
|
||||
NameHierarchy nameHierarchy;
|
||||
std::unordered_map<const clang::Type*, NameHierarchy>::const_iterator it = m_typeNameMap.find(type);
|
||||
if (it != m_typeNameMap.end())
|
||||
{
|
||||
nameHierarchy = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
CxxTypeNameResolver resolver;
|
||||
nameHierarchy = resolver.getTypeNameHierarchy(type);
|
||||
m_typeNameMap[type] = nameHierarchy;
|
||||
}
|
||||
return nameHierarchy;
|
||||
}
|
||||
return NameHierarchy("global");
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<const clang::Type*, NameHierarchy> m_typeNameMap;
|
||||
};
|
||||
|
||||
class DeclNameCache
|
||||
{
|
||||
public:
|
||||
NameHierarchy getName(const clang::NamedDecl* decl)
|
||||
{
|
||||
if (decl)
|
||||
{
|
||||
NameHierarchy nameHierarchy;
|
||||
std::unordered_map<const clang::Decl*, NameHierarchy>::const_iterator it = m_declNameCache.find(decl);
|
||||
if (it != m_declNameCache.end())
|
||||
{
|
||||
nameHierarchy = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
nameHierarchy = utility::getDeclNameHierarchy(decl);
|
||||
m_declNameCache[decl] = nameHierarchy;
|
||||
}
|
||||
return nameHierarchy;
|
||||
}
|
||||
return NameHierarchy("global");
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<const clang::Decl*, NameHierarchy> m_declNameCache;
|
||||
};
|
||||
|
||||
class ContextNameGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~ContextNameGenerator() {}
|
||||
virtual NameHierarchy getName() const = 0;
|
||||
};
|
||||
|
||||
class ContextDeclNameGenerator: public ContextNameGenerator
|
||||
{
|
||||
public:
|
||||
ContextDeclNameGenerator(const clang::NamedDecl* decl, std::shared_ptr<DeclNameCache> nameCache)
|
||||
: m_decl(decl)
|
||||
, m_nameCache(nameCache)
|
||||
{}
|
||||
|
||||
virtual ~ContextDeclNameGenerator() {}
|
||||
|
||||
virtual NameHierarchy getName() const
|
||||
{
|
||||
return m_nameCache->getName(m_decl);
|
||||
}
|
||||
private:
|
||||
const clang::NamedDecl* m_decl;
|
||||
std::shared_ptr<DeclNameCache> m_nameCache;
|
||||
};
|
||||
|
||||
class ContextTypeNameGenerator: public ContextNameGenerator
|
||||
{
|
||||
public:
|
||||
ContextTypeNameGenerator(const clang::Type* type, std::shared_ptr<TypeNameCache> nameCache)
|
||||
: m_type(type)
|
||||
, m_nameCache(nameCache)
|
||||
{}
|
||||
|
||||
virtual ~ContextTypeNameGenerator() {}
|
||||
|
||||
virtual NameHierarchy getName() const
|
||||
{
|
||||
return m_nameCache->getName(m_type);
|
||||
}
|
||||
private:
|
||||
const clang::Type* m_type;
|
||||
std::shared_ptr<TypeNameCache> m_nameCache;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
ASTVisitor(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister);
|
||||
|
||||
// Left for debugging purposes. Uncomment to see a colored ast-dump of the parsed file.
|
||||
// virtual bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl)
|
||||
// {
|
||||
// decl->dump();
|
||||
// return true;
|
||||
// }
|
||||
virtual bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl);
|
||||
|
||||
// RecursiveASTVisitor implementation
|
||||
virtual bool VisitStmt(const clang::Stmt* statement); // avoid visiting
|
||||
|
||||
virtual bool VisitTypedefDecl(clang::TypedefDecl* declaration); // typedefs
|
||||
virtual bool VisitRecordDecl(clang::RecordDecl* declaration);
|
||||
virtual bool VisitVarDecl(clang::VarDecl* declaration); // global variables and static fields
|
||||
virtual bool VisitFieldDecl(clang::FieldDecl* declaration); // fields
|
||||
virtual bool VisitFunctionDecl(clang::FunctionDecl* declaration); // functions
|
||||
virtual bool VisitLambdaExpr(clang::LambdaExpr* expr); // lambdas
|
||||
virtual bool VisitParmVarDecl(clang::ParmVarDecl* declaration);
|
||||
virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl* declaration); // methods
|
||||
virtual bool VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration); // initialization list
|
||||
virtual bool VisitNamespaceDecl(clang::NamespaceDecl* declaration); // namespaces
|
||||
virtual bool VisitEnumDecl(clang::EnumDecl* declaration); // enums
|
||||
virtual bool VisitEnumConstantDecl(clang::EnumConstantDecl* declaration); // enum fields
|
||||
|
||||
virtual bool VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl *declaration);
|
||||
virtual bool VisitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl *declaration);
|
||||
virtual bool VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration);
|
||||
virtual bool VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* declaration);
|
||||
virtual bool VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declaration);
|
||||
|
||||
// ASTBodyVisitorClient implementation
|
||||
virtual void VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallExpr* expr); // calls
|
||||
virtual void VisitCallExprInDeclBody(clang::DeclaratorDecl* decl, clang::CallExpr* expr); // calls in initialization of global variables
|
||||
virtual void VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr);
|
||||
virtual void VisitDeclRefExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr);
|
||||
virtual void VisitCXXConstructExprInDeclBody(clang::FunctionDecl* decl, clang::CXXConstructExpr* expr); // constructor calls
|
||||
virtual void VisitCXXConstructExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXConstructExpr* expr); // constructor calls of global variables
|
||||
virtual void VisitExplicitCastExprInDeclBody(clang::FunctionDecl* decl, clang::ExplicitCastExpr* expr);
|
||||
virtual void VisitExplicitCastExprInDeclBody(clang::DeclaratorDecl* decl, clang::ExplicitCastExpr* expr);
|
||||
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::FunctionDecl* decl, clang::CXXTemporaryObjectExpr* expr);
|
||||
virtual void VisitCXXTemporaryObjectExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXTemporaryObjectExpr* expr);
|
||||
virtual void VisitCXXNewExprInDeclBody(clang::FunctionDecl* decl, clang::CXXNewExpr* expr); // type use of new operator
|
||||
virtual void VisitCXXNewExprInDeclBody(clang::DeclaratorDecl* decl, clang::CXXNewExpr* expr); // type use of new operator in global space
|
||||
virtual void VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::MemberExpr* expr); // field usages
|
||||
virtual void VisitMemberExprInDeclBody(clang::DeclaratorDecl* decl, clang::MemberExpr* expr); // field usages
|
||||
virtual void VisitGlobalVariableExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr); // global variable usage
|
||||
virtual void VisitGlobalVariableExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr); // global variable usage
|
||||
virtual void VisitEnumExprInDeclBody(clang::FunctionDecl* decl, clang::DeclRefExpr* expr); // enum field usage
|
||||
virtual void VisitEnumExprInDeclBody(clang::DeclaratorDecl* decl, clang::DeclRefExpr* expr); // enum field usage in global variable
|
||||
virtual void VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl); // type usages
|
||||
void indexDecl(clang::Decl *d) { TraverseDecl(d); }
|
||||
|
||||
private:
|
||||
void processFunctionDecl(clang::FunctionDecl* declaration);
|
||||
void processTemplateArgumentsOfExplicitSpecialization(clang::FunctionDecl* declaration);
|
||||
void processTemplateArgumentsOfExplicitSpecialization(clang::ClassTemplateSpecializationDecl* specializationDecl);
|
||||
void processTemplateArguments(clang::DeclRefExpr* expr);
|
||||
void processTemplateArguments(clang::TypeLoc loc);
|
||||
typedef clang::RecursiveASTVisitor<ASTVisitor> base;
|
||||
friend class clang::RecursiveASTVisitor<ASTVisitor>;
|
||||
|
||||
bool isLocatedInUnparsedProjectFile(const clang::Decl* declaration) const;
|
||||
bool isLocatedInProjectFile(const ParseLocation& location) const;
|
||||
bool isLocatedInProjectFile(const clang::Decl* declaration) const;
|
||||
// XXX: The CF_Read flag is useful mostly for lvalues -- for rvalues, we
|
||||
// don't set the CF_Read flag, but the rvalue is assumed to be read anyway.
|
||||
|
||||
ParserClient::AccessType convertAccessType(clang::AccessSpecifier) const;
|
||||
ParserClient::AbstractionType getAbstractionType(const clang::CXXMethodDecl* methodDecl) const;
|
||||
enum ContextFlags {
|
||||
CF_Called = 0x1, // the value is read only to be called
|
||||
CF_Read = 0x2, // the value is read for any other use
|
||||
CF_AddressTaken = 0x4, // the gl-value's address escapes
|
||||
CF_Assigned = 0x8, // the gl-value is assigned to
|
||||
CF_Modified = 0x10 // the gl-value is updated (i.e. compound assignment)
|
||||
};
|
||||
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
ParseLocation getParseLocationForTokenAtLocation(const clang::SourceLocation& loc) const;
|
||||
ParseLocation getParseLocationForTokensInRange(const clang::SourceRange& range) const;
|
||||
ParseLocation getParseLocationForNamedDecl(const clang::NamedDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocationOfRecordBody(clang::RecordDecl* decl) const;
|
||||
enum RefType : int {
|
||||
RT_AddressTaken,
|
||||
RT_Assigned,
|
||||
RT_BaseClass,
|
||||
RT_Called,
|
||||
RT_Declaration,
|
||||
RT_DefinedTest,
|
||||
RT_Definition,
|
||||
RT_Expansion,
|
||||
RT_Included,
|
||||
RT_Initialized,
|
||||
RT_Modified,
|
||||
RT_NamespaceAlias,
|
||||
RT_Other,
|
||||
RT_Qualifier,
|
||||
RT_Read,
|
||||
RT_Reference,
|
||||
RT_TemplateArgument,
|
||||
RT_TemplateDefaultArgument,
|
||||
RT_Undefinition,
|
||||
RT_Using,
|
||||
RT_UsingDirective,
|
||||
RT_Max
|
||||
};
|
||||
|
||||
ParseTypeUsage getParseTypeUsage(const clang::TypeLoc& typeLoc, const clang::QualType& type) const;
|
||||
ParseTypeUsage getParseTypeUsage(const clang::TypeLoc& typeLoc, const std::shared_ptr<DataType> type) const;
|
||||
ParseTypeUsage getParseTypeUsage(const clang::SourceRange& sourceRange, const std::shared_ptr<DataType> type) const;
|
||||
ParseTypeUsage getParseTypeUsageOfReturnType(const clang::FunctionDecl* declaration) const;
|
||||
std::vector<ParseTypeUsage> getParameters(const clang::FunctionDecl* declaration) const;
|
||||
enum SymbolType : int { // we dont need this. decl already knows it!
|
||||
ST_Class,
|
||||
ST_ClassTemplateSpecialization,
|
||||
ST_Constructor,
|
||||
ST_Destructor,
|
||||
ST_Enum,
|
||||
ST_Enumerator,
|
||||
ST_Field,
|
||||
ST_Function,
|
||||
ST_FunctionTemplateSpecialization,
|
||||
ST_GlobalVariable,
|
||||
ST_LocalVariable,
|
||||
ST_Macro,
|
||||
ST_Method,
|
||||
ST_Namespace,
|
||||
ST_Parameter,
|
||||
ST_Path,
|
||||
ST_Struct,
|
||||
ST_Typedef,
|
||||
ST_TemplateParameter,
|
||||
ST_Union,
|
||||
ST_Max
|
||||
};
|
||||
|
||||
ParseVariable getParseVariable(const clang::DeclaratorDecl* declaration);
|
||||
ParseFunction getParseFunction(const clang::FunctionDecl* declaration);
|
||||
ParseFunction getParseFunction(const clang::FunctionTemplateDecl* declaration);
|
||||
struct Location {
|
||||
unsigned int fileID;
|
||||
unsigned int line; // 1-based
|
||||
int column; // 1-based
|
||||
};
|
||||
|
||||
NameHierarchy getDeclNameHierarchy(const clang::Decl* decl);
|
||||
typedef unsigned int Context;
|
||||
|
||||
clang::ASTContext* m_context;
|
||||
clang::Preprocessor* m_preprocessor;
|
||||
ParserClient* m_client;
|
||||
FileRegister* m_fileRegister;
|
||||
std::unordered_map<const clang::Decl*, NameHierarchy> m_nameCache;
|
||||
|
||||
Context m_thisContext;
|
||||
Context m_childContext;
|
||||
RefType m_typeContext;
|
||||
|
||||
// Misc routines
|
||||
bool shouldVisitTemplateInstantiations() const { return true; }
|
||||
bool shouldUseDataRecursionFor(clang::Stmt *s) const;
|
||||
|
||||
// Dispatcher routines
|
||||
bool TraverseStmt(clang::Stmt *stmt);
|
||||
bool TraverseType(clang::QualType t);
|
||||
bool TraverseTypeLoc(clang::TypeLoc tl);
|
||||
bool TraverseDecl(clang::Decl *d);
|
||||
bool TraverseLambdaExpr(clang::LambdaExpr* e);
|
||||
bool TraverseFunctionDecl(clang::FunctionDecl* d);
|
||||
bool TraverseTypedefDecl(clang::TypedefDecl *d);
|
||||
bool TraverseFieldDecl(clang::FieldDecl *d);
|
||||
bool TraverseVarDecl(clang::VarDecl *d);
|
||||
bool TraverseClassTemplateDecl(clang::ClassTemplateDecl* d);
|
||||
bool TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d);
|
||||
bool TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d);
|
||||
bool TraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d);
|
||||
bool TraverseDeclRefExpr(clang::DeclRefExpr* expr);
|
||||
bool TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc);
|
||||
bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
|
||||
// Expression context propagation
|
||||
bool TraverseCallExpr(clang::CallExpr *e) { return TraverseCallCommon(e); }
|
||||
bool TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr *e) { return TraverseCallCommon(e); }
|
||||
bool TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr *e) { return TraverseCallCommon(e); }
|
||||
bool TraverseBinComma(clang::BinaryOperator *s);
|
||||
bool TraverseBinAssign(clang::BinaryOperator *e) { return TraverseAssignCommon(e, CF_Assigned); }
|
||||
#define OPERATOR(NAME) bool TraverseBin##NAME##Assign(clang::CompoundAssignOperator *e) { return TraverseAssignCommon(e, CF_Modified); }
|
||||
OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub)
|
||||
OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor)
|
||||
#undef OPERATOR
|
||||
bool VisitParenExpr(clang::ParenExpr *e) { m_childContext = m_thisContext; return true; }
|
||||
bool VisitCastExpr(clang::CastExpr *e);
|
||||
bool VisitUnaryAddrOf(clang::UnaryOperator *e);
|
||||
bool VisitUnaryDeref(clang::UnaryOperator *e);
|
||||
bool VisitDeclStmt(clang::DeclStmt *s);
|
||||
bool VisitReturnStmt(clang::ReturnStmt *s);
|
||||
bool VisitVarDecl(clang::VarDecl *d);
|
||||
bool VisitInitListExpr(clang::InitListExpr *e);
|
||||
bool TraverseConstructorInitializer(clang::CXXCtorInitializer *init);
|
||||
bool TraverseCallCommon(clang::CallExpr *call);
|
||||
bool TraverseAssignCommon(clang::BinaryOperator *e, ContextFlags lhsFlag);
|
||||
|
||||
// Expression reference recording
|
||||
bool VisitLambdaExpr(clang::LambdaExpr* e);
|
||||
bool VisitMemberExpr(clang::MemberExpr *e);
|
||||
bool VisitDeclRefExpr(clang::DeclRefExpr *e);
|
||||
bool VisitCXXConstructExpr(clang::CXXConstructExpr *e);
|
||||
void RecordDeclRefExpr(clang::NamedDecl *d, clang::SourceLocation loc, clang::Expr *e, Context context);
|
||||
|
||||
// NestedNameSpecifier handling
|
||||
bool TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc qualifier);
|
||||
|
||||
// Declaration and TypeLoc handling
|
||||
void traverseDeclContextHelper(clang::DeclContext *d);
|
||||
bool TraverseCXXRecordDecl(clang::CXXRecordDecl *d);
|
||||
bool TraverseNamespaceAliasDecl(clang::NamespaceAliasDecl *d);
|
||||
bool TraverseClassTemplateSpecializationDecl(
|
||||
clang::ClassTemplateSpecializationDecl *d);
|
||||
void templateParameterListsHelper(clang::DeclaratorDecl *d);
|
||||
bool VisitDecl(clang::Decl *d);
|
||||
bool VisitTypeLoc(clang::TypeLoc tl);
|
||||
|
||||
// Reference recording
|
||||
ParseLocation getDeclRefRange(
|
||||
clang::NamedDecl *decl,
|
||||
clang::SourceLocation loc);
|
||||
|
||||
void RecordTypeRef(
|
||||
const clang::Type* type,
|
||||
clang::SourceLocation beginLoc,
|
||||
RefType refType,
|
||||
SymbolType symbolType = ST_Max);
|
||||
|
||||
void RecordDeclRef(
|
||||
clang::NamedDecl *d,
|
||||
clang::SourceLocation beginLoc,
|
||||
RefType refType,
|
||||
SymbolType symbolType = ST_Max);
|
||||
|
||||
bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc);
|
||||
bool isLocatedInProjectFile(clang::SourceLocation loc);
|
||||
|
||||
ParserClient::AccessType convertAccessType(clang::AccessSpecifier access) const;
|
||||
ParserClient::AbstractionType getAbstractionType(const clang::CXXMethodDecl* methodDecl) const;
|
||||
ParseLocation getParseLocationOfRecordBody(clang::RecordDecl* decl) const;
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
|
||||
struct FileIdHash {
|
||||
size_t operator()(clang::FileID fileID) const {
|
||||
return fileID.getHashValue();
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inUnparsedProjectFileMap;
|
||||
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inProjectFileMap;
|
||||
|
||||
std::shared_ptr<ContextNameGenerator> m_contextNameGenerator;
|
||||
std::shared_ptr<ContextNameGenerator> m_childContextNameGenerator;
|
||||
|
||||
std::shared_ptr<DeclNameCache> m_declNameCache;
|
||||
std::shared_ptr<TypeNameCache> m_typeNameCache;
|
||||
|
||||
ParserClient::AccessType m_contextAccess;
|
||||
};
|
||||
|
||||
#endif // AST_VISITOR_H
|
||||
|
||||
@@ -54,7 +54,7 @@ NameHierarchy CxxDeclNameResolver::getContextNameHierarchy(const clang::DeclCont
|
||||
{
|
||||
NameHierarchy contextNameHierarchy;
|
||||
|
||||
if (!ignoresContext(declContext))
|
||||
if (declContext && !ignoresContext(declContext))
|
||||
{
|
||||
const clang::DeclContext* parentContext = declContext->getParent();
|
||||
if (parentContext)
|
||||
@@ -139,7 +139,7 @@ std::shared_ptr<NameElement> CxxDeclNameResolver::getDeclName()
|
||||
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
|
||||
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(recordDecl->getLocStart());
|
||||
std::string lambdaName = "lambda at " + std::to_string(presumedBegin.getLine()) + ":" + std::to_string(presumedBegin.getColumn());
|
||||
return std::make_shared<NameElement>(lambdaName, lambdaName);
|
||||
return std::make_shared<NameElement>(lambdaName, NameElement::Signature("void", "()"));
|
||||
}
|
||||
else if (declNameString.size() == 0)
|
||||
{
|
||||
@@ -160,15 +160,16 @@ std::shared_ptr<NameElement> CxxDeclNameResolver::getDeclName()
|
||||
}
|
||||
}
|
||||
|
||||
const clang::FunctionDecl* functionDecl = clang::dyn_cast<clang::FunctionDecl>(declaration);
|
||||
std::string functionName;
|
||||
|
||||
const clang::FunctionDecl* functionDecl = clang::dyn_cast<clang::FunctionDecl>(declaration);
|
||||
if (clang::FunctionTemplateDecl* templateFunctionDeclaration = functionDecl->getDescribedFunctionTemplate())
|
||||
{
|
||||
return getDeclName(templateFunctionDeclaration);
|
||||
functionName = getDeclName(templateFunctionDeclaration)->getName();
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
std::string functionName = declNameString;
|
||||
functionName = declNameString;
|
||||
if (functionDecl->isFunctionTemplateSpecialization())
|
||||
{
|
||||
std::string templateArgumentNamePart = "<";
|
||||
@@ -182,40 +183,40 @@ std::shared_ptr<NameElement> CxxDeclNameResolver::getDeclName()
|
||||
templateArgumentNamePart += ">";
|
||||
functionName += templateArgumentNamePart;
|
||||
}
|
||||
|
||||
bool isStatic = false;
|
||||
bool isConst = false;
|
||||
|
||||
if (clang::isa<clang::CXXMethodDecl>(declaration))
|
||||
{
|
||||
const clang::CXXMethodDecl* methodDecl = clang::dyn_cast<const clang::CXXMethodDecl>(declaration);
|
||||
isStatic = methodDecl->isStatic();
|
||||
isConst = methodDecl->isConst();
|
||||
}
|
||||
else
|
||||
{
|
||||
isStatic = functionDecl->getStorageClass() == clang::SC_Static;
|
||||
}
|
||||
|
||||
CxxTypeNameResolver typenNameResolver(getIgnoredContextDecls());
|
||||
typenNameResolver.ignoreContextDecl(functionDecl);
|
||||
std::string returnTypeString = typenNameResolver.qualTypeToDataType(functionDecl->getReturnType())->getFullTypeName();
|
||||
|
||||
std::string parameterString = "(";
|
||||
for (unsigned int i = 0; i < functionDecl->param_size(); i++)
|
||||
{
|
||||
parameterString += typenNameResolver.qualTypeToDataType(functionDecl->parameters()[i]->getType())->getFullTypeName();
|
||||
if (i < functionDecl->param_size() - 1)
|
||||
{
|
||||
parameterString += ", ";
|
||||
}
|
||||
}
|
||||
parameterString += ")";
|
||||
|
||||
return std::make_shared<NameElement>(
|
||||
functionName,
|
||||
(isStatic ? "static " : "") + returnTypeString + " " + functionName + parameterString + (isConst ? " const" : ""));
|
||||
}
|
||||
|
||||
bool isStatic = false;
|
||||
bool isConst = false;
|
||||
|
||||
if (clang::isa<clang::CXXMethodDecl>(declaration))
|
||||
{
|
||||
const clang::CXXMethodDecl* methodDecl = clang::dyn_cast<const clang::CXXMethodDecl>(declaration);
|
||||
isStatic = methodDecl->isStatic();
|
||||
isConst = methodDecl->isConst();
|
||||
}
|
||||
else
|
||||
{
|
||||
isStatic = functionDecl->getStorageClass() == clang::SC_Static;
|
||||
}
|
||||
|
||||
CxxTypeNameResolver typenNameResolver(getIgnoredContextDecls());
|
||||
typenNameResolver.ignoreContextDecl(functionDecl);
|
||||
std::string returnTypeString = typenNameResolver.qualTypeToDataType(functionDecl->getReturnType())->getFullTypeName();
|
||||
|
||||
std::string parameterString = "(";
|
||||
for (unsigned int i = 0; i < functionDecl->param_size(); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
parameterString += ", ";
|
||||
}
|
||||
parameterString += typenNameResolver.qualTypeToDataType(functionDecl->parameters()[i]->getType())->getFullTypeName();
|
||||
}
|
||||
parameterString += ")";
|
||||
|
||||
return std::make_shared<NameElement>(
|
||||
functionName,
|
||||
NameElement::Signature((isStatic ? "static " : "") + returnTypeString, parameterString + (isConst ? " const" : "")));
|
||||
|
||||
}
|
||||
else if (clang::isa<clang::TemplateDecl>(declaration)) // also triggers on TemplateTemplateParmDecl
|
||||
|
||||
@@ -134,11 +134,11 @@ std::shared_ptr<DataType> CxxTypeNameResolver::typeToDataType(const clang::Type*
|
||||
}
|
||||
templateArgumentNamePart += ">";
|
||||
|
||||
std::string declName = typeNameHerarchy.back()->getFullName();
|
||||
std::string declName = typeNameHerarchy.back()->getName();
|
||||
declName = declName.substr(0, declName.rfind("<")); // remove template parameters
|
||||
declName += templateArgumentNamePart; // add template arguments
|
||||
typeNameHerarchy.pop();
|
||||
typeNameHerarchy.push(std::make_shared<NameElement>(declName));
|
||||
typeNameHerarchy.push(std::make_shared<NameElement>(declName)); // templateSpecialization has no signature.
|
||||
}
|
||||
}
|
||||
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
|
||||
@@ -219,6 +219,11 @@ std::shared_ptr<DataType> CxxTypeNameResolver::typeToDataType(const clang::Type*
|
||||
return dataType;
|
||||
}
|
||||
|
||||
NameHierarchy CxxTypeNameResolver::getTypeNameHierarchy(const clang::Type* type)
|
||||
{
|
||||
return typeToDataType(type)->getTypeNameHierarchy();
|
||||
}
|
||||
|
||||
NameHierarchy CxxTypeNameResolver::getNameHierarchy(const clang::NestedNameSpecifier* nestedNameSpecifier)
|
||||
{
|
||||
clang::NestedNameSpecifier::SpecifierKind nnsKind = nestedNameSpecifier->getKind();
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
virtual ~CxxTypeNameResolver();
|
||||
|
||||
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType);
|
||||
NameHierarchy getTypeNameHierarchy(const clang::Type* type);
|
||||
|
||||
private:
|
||||
std::shared_ptr<DataType> typeToDataType(const clang::Type* type);
|
||||
|
||||
Reference in New Issue
Block a user