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:
malte_langkabel
2016-02-17 10:45:35 +01:00
parent 9047d602ff
commit 42513fe102
41 changed files with 5022 additions and 4521 deletions
+292 -80
View File
@@ -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