logic: fixed getting the parent of a Cxx template parameter's declaration

* switched to getting the template parameter's parent from the ASTContext instead of using the DeclContext
This commit is contained in:
mlangkabel
2017-11-14 12:09:32 +01:00
parent 6488c6538e
commit 9d17e2e7e6
7 changed files with 203 additions and 50 deletions
@@ -475,14 +475,12 @@ void CxxAstVisitor::traverseDeclContextHelper(clang::DeclContext* d)
return;
}
// Traverse children.
for (clang::DeclContext::decl_iterator it = d->decls_begin(),
itEnd = d->decls_end(); it != itEnd; ++it)
{
// BlockDecls are traversed through BlockExprs.
if (!llvm::isa<clang::BlockDecl>(*it))
for (auto* child : d->decls()) {
// BlockDecls and CapturedDecls are traversed through BlockExprs and
// CapturedStmts respectively.
if (!llvm::isa<clang::BlockDecl>(child) && !llvm::isa<clang::CapturedDecl>(child))
{
TraverseDecl(*it);
TraverseDecl(child);
}
}
}
@@ -36,17 +36,9 @@ CxxDeclNameResolver::~CxxDeclNameResolver()
std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getName(const clang::NamedDecl* declaration)
{
{
const clang::Decl* prev = declaration;
while (prev)
{
declaration = clang::dyn_cast_or_null<clang::NamedDecl>(prev);
prev = prev->getPreviousDecl();
}
}
declaration = utility::getFirstDecl(declaration);
std::shared_ptr<CxxDeclName> declName;
if ((declaration) &&
(clang::isa<clang::CXXRecordDecl>(declaration)) &&
(clang::dyn_cast<clang::CXXRecordDecl>(declaration)->isLambda()))
@@ -77,6 +69,60 @@ std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getName(const clang::NamedDecl
CxxSpecifierNameResolver specifierNameResolver(getCanonicalFilePathCache(), getIgnoredContextDecls());
declName->setParent(specifierNameResolver.getName(usingDecl->getQualifier()));
}
else if (
clang::isa<clang::TemplateTypeParmDecl>(declaration) ||
clang::isa<clang::NonTypeTemplateParmDecl>(declaration) ||
clang::isa<clang::TemplateTemplateParmDecl>(declaration)
) {
clang::ASTContext& context = declaration->getASTContext();
clang::ASTContext::DynTypedNodeList parents = context.getParents(*declaration);
for (const clang::ast_type_traits::DynTypedNode* parent = parents.begin(); parent != parents.end(); parent++)
{
const clang::Decl* parentDecl = parent->get<clang::Decl>();
while (parentDecl != nullptr)
{
parentDecl = utility::getFirstDecl(parentDecl);
if (const clang::TemplateDecl* parentTemplateDecl = clang::dyn_cast_or_null<clang::TemplateDecl>(parentDecl))
{
if (!ignoresContext(parentTemplateDecl) && !ignoresContext(parentTemplateDecl->getTemplatedDecl()))
{
declName->setParent(getName(parentTemplateDecl));
}
break;
}
else if (const clang::ClassTemplatePartialSpecializationDecl* parentTemplateDecl = clang::dyn_cast_or_null<clang::ClassTemplatePartialSpecializationDecl>(parentDecl))
{
if (!ignoresContext(parentDecl))
{
declName->setParent(getName(parentTemplateDecl));
}
break;
}
if (const clang::DeclContext* parentDeclContext = parentDecl->getDeclContext())
{
if (ignoresContext(parentDeclContext))
{
break;
}
parentDecl = clang::dyn_cast_or_null<clang::Decl>(parentDeclContext);
if (parentDecl)
{
if (clang::TemplateDecl* describedTemplate = parentDecl->getDescribedTemplate())
{
parentDecl = describedTemplate;
}
}
}
else
{
break;
}
}
}
}
else
{
declName->setParent(getContextName(declaration->getDeclContext()));
@@ -215,20 +261,15 @@ std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
}
else if (clang::FunctionTemplateDecl* templateFunctionDeclaration = functionDecl->getDescribedFunctionTemplate())
{
std::shared_ptr<CxxDeclName> templateDeclName = getDeclName(templateFunctionDeclaration);
functionName = templateDeclName->getName();
templateArguments = templateDeclName->getTemplateParameterNames();
templateArguments = getTemplateParameterStrings(templateFunctionDeclaration);
}
else
else if (functionDecl->isFunctionTemplateSpecialization())
{
if (functionDecl->isFunctionTemplateSpecialization())
const clang::TemplateArgumentList* templateArgumentList = functionDecl->getTemplateSpecializationArgs();
for (size_t i = 0; i < templateArgumentList->size(); i++)
{
const clang::TemplateArgumentList* templateArgumentList = functionDecl->getTemplateSpecializationArgs();
for (size_t i = 0; i < templateArgumentList->size(); i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentList->get(i);
templateArguments.push_back(getTemplateArgumentName(templateArgument));
}
const clang::TemplateArgument& templateArgument = templateArgumentList->get(i);
templateArguments.push_back(getTemplateArgumentName(templateArgument));
}
}
@@ -276,15 +317,14 @@ std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
isStatic
);
}
else if (clang::isa<clang::FunctionTemplateDecl>(declaration))
{
const clang::FunctionTemplateDecl* functionTemplateDecl = clang::dyn_cast<clang::FunctionTemplateDecl>(declaration);
return getDeclName(functionTemplateDecl->getTemplatedDecl());
}
else if (clang::isa<clang::TemplateDecl>(declaration)) // also triggers on TemplateTemplateParmDecl
{
std::vector<std::string> templateParameters;
clang::TemplateParameterList* parameterList = clang::dyn_cast<clang::TemplateDecl>(declaration)->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameters.push_back(getTemplateParameterString(parameterList->getParam(i)));
}
return std::make_shared<CxxDeclName>(declNameString, templateParameters);
return std::make_shared<CxxDeclName>(declNameString, getTemplateParameterStrings(clang::dyn_cast<clang::TemplateDecl>(declaration)));
}
else if (clang::isa<clang::FieldDecl>(declaration))
{
@@ -410,6 +450,17 @@ std::string CxxDeclNameResolver::getNameForAnonymousSymbol(const std::string& sy
return "anonymous " + symbolKindName;
}
std::vector<std::string> CxxDeclNameResolver::getTemplateParameterStrings(const clang::TemplateDecl* templateDecl)
{
std::vector<std::string> templateParameterStrings;
clang::TemplateParameterList* parameterList = templateDecl->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameterStrings.push_back(getTemplateParameterString(parameterList->getParam(i)));
}
return templateParameterStrings;
}
std::string CxxDeclNameResolver::getTemplateParameterString(const clang::NamedDecl* parameter)
{
std::string templateParameterTypeString;
@@ -25,6 +25,7 @@ private:
std::string getTranslationUnitMainFileName(const clang::Decl* declaration);
std::string getDeclarationFileName(const clang::Decl* declaration);
std::string getNameForAnonymousSymbol(const std::string& symbolKindName, const clang::Decl* declaration);
std::vector<std::string> getTemplateParameterStrings(const clang::TemplateDecl* templateDecl);
std::string getTemplateParameterString(const clang::NamedDecl* parameter);
std::string getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter);
@@ -21,15 +21,26 @@ void CxxNameResolver::ignoreContextDecl(const clang::Decl* decl)
}
}
bool CxxNameResolver::ignoresContext(const clang::Decl* decl)
{
if (decl)
{
for (size_t i = 0; i < m_ignoredContextDecls.size(); i++)
{
if (decl == m_ignoredContextDecls[i])
{
return true;
}
}
}
return false;
}
bool CxxNameResolver::ignoresContext(const clang::DeclContext* declContext)
{
const clang::Decl* decl = clang::dyn_cast<clang::Decl>(declContext);
for (size_t i = 0; i < m_ignoredContextDecls.size(); i++)
if (const clang::Decl* decl = clang::dyn_cast_or_null<clang::Decl>(declContext))
{
if (decl == m_ignoredContextDecls[i])
{
return true;
}
return ignoresContext(decl);
}
return false;
}
@@ -17,6 +17,7 @@ public:
virtual ~CxxNameResolver();
void ignoreContextDecl(const clang::Decl* decl);
bool ignoresContext(const clang::Decl* decl);
bool ignoresContext(const clang::DeclContext* declContext);
protected:
@@ -8,6 +8,8 @@
namespace utility
{
template <typename T>
const T* getFirstDecl(const T* decl);
bool isImplicit(const clang::Decl* d);
AccessKind convertAccessSpecifier(clang::AccessSpecifier access);
SymbolKind convertTagKind(const clang::TagTypeKind tagKind);
@@ -15,4 +17,19 @@ namespace utility
std::string getFileNameOfFileEntry(const clang::FileEntry* entry);
}
template <typename T>
const T* utility::getFirstDecl(const T* decl)
{
const clang::Decl* ret = decl;
{
const clang::Decl* prev = ret;
while (prev)
{
ret = prev;
prev = prev->getPreviousDecl();
}
}
return clang::dyn_cast_or_null<T>(ret);
}
#endif // UTILITY_CLANG_H