data: template argument fix
* improved context detection of template parameters. * fixed case where declaration and definition of template function has 2 nodes in graph. * removed code duplications: replaced individual cache classes in ASTVisitor with template based
This commit is contained in:
@@ -38,10 +38,23 @@ ASTVisitor::ASTVisitor(clang::ASTContext* context, clang::Preprocessor* preproce
|
||||
, m_typeContext(RT_Reference)
|
||||
, m_contextAccess(ParserClient::ACCESS_NONE)
|
||||
{
|
||||
m_declNameCache = std::make_shared<DeclNameCache>();
|
||||
m_typeNameCache = std::make_shared<TypeNameCache>();
|
||||
m_contextNameGenerator = std::make_shared<ContextDeclNameGenerator>(nullptr, m_declNameCache);
|
||||
m_childContextNameGenerator = std::make_shared<ContextDeclNameGenerator>(nullptr, m_declNameCache);
|
||||
m_declNameCache = std::make_shared<DeclNameCache>([](const clang::NamedDecl* decl) -> NameHierarchy
|
||||
{
|
||||
if (decl)
|
||||
{
|
||||
return utility::getDeclNameHierarchy(decl);
|
||||
}
|
||||
return NameHierarchy("global");
|
||||
});
|
||||
m_typeNameCache = std::make_shared<TypeNameCache>([](const clang::Type* type) -> NameHierarchy
|
||||
{
|
||||
if (type)
|
||||
{
|
||||
CxxTypeNameResolver resolver;
|
||||
return resolver.getTypeNameHierarchy(type);
|
||||
}
|
||||
return NameHierarchy("global");
|
||||
});
|
||||
}
|
||||
|
||||
ASTVisitor::~ASTVisitor()
|
||||
@@ -50,7 +63,7 @@ ASTVisitor::~ASTVisitor()
|
||||
|
||||
bool ASTVisitor::VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl)
|
||||
{
|
||||
//decl->dump();
|
||||
decl->dump();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -152,8 +165,8 @@ bool ASTVisitor::TraverseVarDecl(clang::VarDecl *d)
|
||||
{
|
||||
std::shared_ptr<ScopedSwitcher<std::shared_ptr<ContextNameGenerator>>> switcher;
|
||||
|
||||
NameHierarchy contextNameHierarchy = m_contextNameGenerator->getName();
|
||||
if (!(contextNameHierarchy.size() > 0 && contextNameHierarchy.back()->hasSignature())) // TODO: optimize this: remove requirement to get the name here!
|
||||
NameHierarchy contextNameHierarchy = getContextName();
|
||||
if (!(contextNameHierarchy.size() > 0 && contextNameHierarchy.back()->hasSignature())) // TODO: whle test if its a function. optimize this: remove requirement to get the name here!
|
||||
{
|
||||
switcher = std::make_shared<ScopedSwitcher<std::shared_ptr<ContextNameGenerator>>>(m_contextNameGenerator, std::make_shared<ContextDeclNameGenerator>(d, m_declNameCache));
|
||||
}
|
||||
@@ -166,6 +179,13 @@ bool ASTVisitor::TraverseClassTemplateDecl(clang::ClassTemplateDecl* d)
|
||||
return base::TraverseClassTemplateDecl(d);
|
||||
}
|
||||
|
||||
bool ASTVisitor::TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* d)
|
||||
{
|
||||
// we need to use the templated decl here because name resolving for FunctionTemplateDecl is not returning a correct signature yet.
|
||||
ScopedSwitcher<std::shared_ptr<ContextNameGenerator>> switcher(m_contextNameGenerator, std::make_shared<ContextDeclNameGenerator>(d->getTemplatedDecl(), m_declNameCache));
|
||||
return base::TraverseFunctionTemplateDecl(d);
|
||||
}
|
||||
|
||||
bool ASTVisitor::TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d)
|
||||
{
|
||||
// same as base::TraverseTemplateTypeParmDecl(..) but we need to integrate the setter for the context info.
|
||||
@@ -194,7 +214,6 @@ bool ASTVisitor::TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDec
|
||||
ScopedSwitcher<RefType> sw1(m_typeContext, RT_TemplateDefaultArgument);
|
||||
ScopedSwitcher<std::shared_ptr<ContextNameGenerator>> sw2(m_contextNameGenerator, std::make_shared<ContextDeclNameGenerator>(d, m_declNameCache));
|
||||
|
||||
//d->getDefaultArgument
|
||||
TraverseTemplateArgumentLoc(d->getDefaultArgument());
|
||||
}
|
||||
|
||||
@@ -230,12 +249,22 @@ bool ASTVisitor::TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializa
|
||||
return base::TraverseTemplateSpecializationTypeLoc(loc);
|
||||
}
|
||||
|
||||
bool ASTVisitor::TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e) // TODO: do this for unresolved and dependent stuff
|
||||
{
|
||||
std::shared_ptr<ContextNameGenerator> n;
|
||||
ScopedSwitcher<std::shared_ptr<ContextNameGenerator>> sw(m_childContextNameGenerator, n);
|
||||
return base::TraverseUnresolvedLookupExpr(e);
|
||||
}
|
||||
|
||||
bool ASTVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc)
|
||||
{
|
||||
std::shared_ptr<ScopedSwitcher<RefType>> sw1;
|
||||
std::shared_ptr<ScopedSwitcher<std::shared_ptr<ContextNameGenerator>>> sw2;
|
||||
|
||||
if (m_typeContext != RT_TemplateDefaultArgument)
|
||||
if (m_typeContext != RT_TemplateDefaultArgument
|
||||
&&
|
||||
m_childContextNameGenerator
|
||||
)
|
||||
{
|
||||
sw1 = std::make_shared<ScopedSwitcher<RefType>>(m_typeContext, RT_TemplateArgument);
|
||||
sw2 = std::make_shared<ScopedSwitcher<std::shared_ptr<ContextNameGenerator>>>(m_contextNameGenerator, m_childContextNameGenerator);
|
||||
@@ -250,12 +279,6 @@ bool ASTVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& l
|
||||
return base::TraverseTemplateArgumentLoc(loc);
|
||||
}
|
||||
|
||||
//bool ASTVisitor::TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* d)
|
||||
//{
|
||||
// ScopedSwitcher<clang::Decl*> switcher(m_contextDecl, d);
|
||||
// return base::TraverseFunctionTemplateDecl(d);
|
||||
//}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Expression context propagation
|
||||
|
||||
@@ -1052,8 +1075,8 @@ void ASTVisitor::RecordTypeRef(
|
||||
if (isLocatedInProjectFile(beginLoc))
|
||||
{
|
||||
ParseLocation parseLocation = getDeclRefRange(0, beginLoc);
|
||||
NameHierarchy typeNameHierarchy = m_typeNameCache->getName(type);
|
||||
NameHierarchy contextNameHierarchy = m_contextNameGenerator->getName();
|
||||
NameHierarchy typeNameHierarchy = m_typeNameCache->getValue(type);
|
||||
NameHierarchy contextNameHierarchy = getContextName();
|
||||
|
||||
if (refType == RT_TemplateArgument)
|
||||
{
|
||||
@@ -1112,7 +1135,8 @@ void ASTVisitor::RecordDeclRef(
|
||||
}
|
||||
|
||||
ParseLocation parseLocation = getDeclRefRange(d, beginLoc);
|
||||
NameHierarchy declNameHierarchy = m_declNameCache->getName(d);
|
||||
//NameHierarchy declNameHierarchy = m_declNameCache->getValue(d);
|
||||
NameHierarchy declNameHierarchy = utility::getDeclNameHierarchy(d);
|
||||
|
||||
bool fallback = false;
|
||||
|
||||
@@ -1192,7 +1216,7 @@ void ASTVisitor::RecordDeclRef(
|
||||
{
|
||||
m_client->onMethodOverrideParsed(
|
||||
parseLocation,
|
||||
m_declNameCache->getName(*it),
|
||||
m_declNameCache->getValue(*it),
|
||||
declNameHierarchy);
|
||||
}
|
||||
|
||||
@@ -1205,7 +1229,7 @@ void ASTVisitor::RecordDeclRef(
|
||||
m_client->onTemplateMemberFunctionSpecializationParsed(
|
||||
parseLocation,
|
||||
declNameHierarchy,
|
||||
m_declNameCache->getName(specializedNamedDecl));
|
||||
m_declNameCache->getValue(specializedNamedDecl));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1266,7 +1290,7 @@ void ASTVisitor::RecordDeclRef(
|
||||
m_client->onTemplateSpecializationParsed(
|
||||
parseLocation,
|
||||
declNameHierarchy,
|
||||
m_declNameCache->getName(specializedFromDecl)); // use context and childcontext!!
|
||||
m_declNameCache->getValue(specializedFromDecl)); // use context and childcontext!!
|
||||
}
|
||||
break;
|
||||
case ST_FunctionTemplateSpecialization:
|
||||
@@ -1275,7 +1299,7 @@ void ASTVisitor::RecordDeclRef(
|
||||
m_client->onTemplateSpecializationParsed(
|
||||
parseLocation,
|
||||
declNameHierarchy,
|
||||
m_declNameCache->getName(functionDecl->getPrimaryTemplate()->getTemplatedDecl())); // TODO: use contect and childcontext!!
|
||||
m_declNameCache->getValue(functionDecl->getPrimaryTemplate()->getTemplatedDecl())); // TODO: use contect and childcontext!!
|
||||
}
|
||||
break;
|
||||
case ST_LocalVariable:
|
||||
@@ -1289,7 +1313,7 @@ void ASTVisitor::RecordDeclRef(
|
||||
}
|
||||
else
|
||||
{
|
||||
const NameHierarchy contextNameHierarchy = m_contextNameGenerator->getName();
|
||||
const NameHierarchy contextNameHierarchy = getContextName();
|
||||
switch (symbolType)
|
||||
{
|
||||
case ST_Field:
|
||||
@@ -1570,3 +1594,12 @@ ParseLocation ASTVisitor::getParseLocation(const clang::SourceRange& sourceRange
|
||||
presumedEnd.getColumn()
|
||||
);
|
||||
}
|
||||
|
||||
NameHierarchy ASTVisitor::getContextName()
|
||||
{
|
||||
if (m_contextNameGenerator)
|
||||
{
|
||||
return m_contextNameGenerator->getName();
|
||||
}
|
||||
return NameHierarchy("global");
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "data/parser/ParserClient.h"
|
||||
#include "utility/file/FileRegister.h"
|
||||
#include "utility/Cache.h"
|
||||
|
||||
|
||||
|
||||
@@ -19,61 +20,8 @@
|
||||
class ASTVisitor: clang::RecursiveASTVisitor<ASTVisitor>
|
||||
{
|
||||
public:
|
||||
|
||||
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;
|
||||
};
|
||||
typedef Cache<const clang::NamedDecl*, NameHierarchy> DeclNameCache;
|
||||
typedef Cache<const clang::Type*, NameHierarchy> TypeNameCache;
|
||||
|
||||
class ContextNameGenerator
|
||||
{
|
||||
@@ -94,8 +42,9 @@ public:
|
||||
|
||||
virtual NameHierarchy getName() const
|
||||
{
|
||||
return m_nameCache->getName(m_decl);
|
||||
return m_nameCache->getValue(m_decl);
|
||||
}
|
||||
|
||||
private:
|
||||
const clang::NamedDecl* m_decl;
|
||||
std::shared_ptr<DeclNameCache> m_nameCache;
|
||||
@@ -113,8 +62,9 @@ public:
|
||||
|
||||
virtual NameHierarchy getName() const
|
||||
{
|
||||
return m_nameCache->getName(m_type);
|
||||
return m_nameCache->getValue(m_type);
|
||||
}
|
||||
|
||||
private:
|
||||
const clang::Type* m_type;
|
||||
std::shared_ptr<TypeNameCache> m_nameCache;
|
||||
@@ -225,11 +175,13 @@ private:
|
||||
bool TraverseFieldDecl(clang::FieldDecl *d);
|
||||
bool TraverseVarDecl(clang::VarDecl *d);
|
||||
bool TraverseClassTemplateDecl(clang::ClassTemplateDecl* d);
|
||||
bool TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* d);
|
||||
bool TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d);
|
||||
bool TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d);
|
||||
bool TraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d);
|
||||
bool TraverseDeclRefExpr(clang::DeclRefExpr* expr);
|
||||
bool TraverseDeclRefExpr(clang::DeclRefExpr* e);
|
||||
bool TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc);
|
||||
bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e);
|
||||
bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
|
||||
|
||||
// Expression context propagation
|
||||
@@ -302,6 +254,8 @@ private:
|
||||
ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const;
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
|
||||
NameHierarchy getContextName();
|
||||
|
||||
struct FileIdHash {
|
||||
size_t operator()(clang::FileID fileID) const {
|
||||
return fileID.getHashValue();
|
||||
@@ -312,7 +266,7 @@ private:
|
||||
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<ContextNameGenerator> m_childContextNameGenerator; // TODO: rename templateArgumentContextNameGenerator
|
||||
|
||||
std::shared_ptr<DeclNameCache> m_declNameCache;
|
||||
std::shared_ptr<TypeNameCache> m_typeNameCache;
|
||||
|
||||
@@ -10,14 +10,24 @@
|
||||
|
||||
CxxDeclNameResolver::CxxDeclNameResolver(const clang::Decl* declaration)
|
||||
: CxxNameResolver(std::vector<const clang::Decl*>())
|
||||
, m_declaration(declaration)
|
||||
{
|
||||
const clang::Decl* prev = declaration;
|
||||
while (prev)
|
||||
{
|
||||
m_declaration = prev;
|
||||
prev = prev->getPreviousDecl();
|
||||
}
|
||||
}
|
||||
|
||||
CxxDeclNameResolver::CxxDeclNameResolver(const clang::Decl* declaration, std::vector<const clang::Decl*> ignoredContextDecls)
|
||||
: CxxNameResolver(ignoredContextDecls)
|
||||
, m_declaration(declaration)
|
||||
{
|
||||
const clang::Decl* prev = declaration;
|
||||
while (prev)
|
||||
{
|
||||
m_declaration = prev;
|
||||
prev = prev->getPreviousDecl();
|
||||
}
|
||||
}
|
||||
|
||||
CxxDeclNameResolver::~CxxDeclNameResolver()
|
||||
|
||||
@@ -23,6 +23,8 @@ CxxTemplateArgumentNameResolver::~CxxTemplateArgumentNameResolver()
|
||||
|
||||
std::string CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument)
|
||||
{
|
||||
// This doesn't work correctly if the template argument is dependent.
|
||||
// If that's required: build name from depth and index of template arg.
|
||||
const clang::TemplateArgument::ArgKind kind = argument.getKind();
|
||||
switch (kind)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user