logic: indexer and name resolving fixes

* made header and excluded filepaths of filemanager canonical
* implemented solving Attributed- and InjectedClassNameType
* handled clang returning null objects in NameResolvers
This commit is contained in:
malte_langkabel
2016-11-29 17:26:57 +01:00
parent b2358f581c
commit 328cf7e8cc
13 changed files with 542 additions and 472 deletions
+15
View File
@@ -1,5 +1,7 @@
#include "data/StorageProvider.h"
#include "utility/logging/logging.h"
int StorageProvider::getStorageCount() const
{
std::lock_guard<std::mutex> lock(m_storagesMutex);
@@ -57,5 +59,18 @@ std::shared_ptr<IntermediateStorage> StorageProvider::popInjectionSource()
return ret;
}
void StorageProvider::logCurrentState() const
{
std::string logString = "Storages waiting for injection:";
{
std::lock_guard<std::mutex> lock(m_storagesMutex);
for (std::shared_ptr<IntermediateStorage> storage: m_storages)
{
logString += " " + std::to_string(storage->getSourceLocationCount()) + ";";
}
}
LOG_INFO(logString);
}
+2
View File
@@ -18,6 +18,8 @@ public:
// returns empty shared_ptr if no storages available
std::shared_ptr<IntermediateStorage> popInjectionSource();
void logCurrentState() const;
private:
std::list<std::shared_ptr<IntermediateStorage>> m_storages; // larger storages are in front
mutable std::mutex m_storagesMutex;
+12 -2
View File
@@ -27,8 +27,8 @@ void FileManager::setPaths(
std::vector<std::string> sourceExtensions
){
m_sourcePaths = sourcePaths;
m_headerPaths = headerPaths;
m_excludePaths = excludePaths;
m_headerPaths = makeCanonical(headerPaths);
m_excludePaths = makeCanonical(excludePaths);
m_sourceExtensions = sourceExtensions;
}
@@ -159,6 +159,16 @@ const FileInfo FileManager::getFileInfo(const FilePath& filePath) const
return it->second;
}
std::vector<FilePath> FileManager::makeCanonical(const std::vector<FilePath>& filePaths)
{
std::vector<FilePath> ret;
for (const FilePath filePath: filePaths)
{
ret.push_back(filePath.canonical());
}
return ret;
}
bool FileManager::isExcluded(const FilePath& filePath) const
{
for (FilePath path : m_excludePaths)
+1
View File
@@ -34,6 +34,7 @@ public:
virtual const FileInfo getFileInfo(const FilePath& filePath) const;
private:
std::vector<FilePath> makeCanonical(const std::vector<FilePath>& filePaths);
bool isExcluded(const FilePath& filePath) const;
std::map<FilePath, FileInfo> m_files;
@@ -1215,6 +1215,7 @@ bool CxxAstVisitor::checkIgnoresTypeLoc(const clang::TypeLoc& tl)
(!tl.getAs<clang::TypedefTypeLoc>().isNull()) ||
(!tl.getAs<clang::TemplateTypeParmTypeLoc>().isNull()) ||
(!tl.getAs<clang::TemplateSpecializationTypeLoc>().isNull()) ||
(!tl.getAs<clang::InjectedClassNameTypeLoc>().isNull()) ||
(!tl.getAs<clang::DependentNameTypeLoc>().isNull()) ||
(!tl.getAs<clang::DependentTemplateSpecializationTypeLoc>().isNull()) ||
(!tl.getAs<clang::BuiltinTypeLoc>().isNull()) ||
@@ -44,7 +44,7 @@ NameHierarchy CxxFunctionDeclName::toNameHierarchy() const
{
signaturePrefix += "static ";
}
signaturePrefix += m_returnTypeName->toString();
signaturePrefix += CxxTypeName::makeUnsolvedIfNull(m_returnTypeName)->toString();
std::string signaturePostfix = "(";
for (size_t i = 0; i < m_parameterTypeNames.size(); i++)
@@ -53,7 +53,7 @@ NameHierarchy CxxFunctionDeclName::toNameHierarchy() const
{
signaturePostfix += ", ";
}
signaturePostfix += m_parameterTypeNames[i]->toString();
signaturePostfix += CxxTypeName::makeUnsolvedIfNull(m_parameterTypeNames[i])->toString();
}
signaturePostfix += ")";
if (m_isConst)
@@ -1,5 +1,16 @@
#include "data/parser/cxx/name/CxxTypeName.h"
std::shared_ptr<CxxTypeName> CxxTypeName::makeUnsolvedIfNull(std::shared_ptr<CxxTypeName> name)
{
if (name)
{
return name;
}
return std::make_shared<CxxTypeName>(
"unsolved-type", std::vector<std::string>()
);
}
CxxTypeName::Modifier::Modifier(std::string symbol)
: symbol(symbol)
{
@@ -13,6 +13,8 @@
class CxxTypeName: public CxxName
{
public:
static std::shared_ptr<CxxTypeName> makeUnsolvedIfNull(std::shared_ptr<CxxTypeName> name);
struct Modifier
{
Modifier(std::string symbol);
@@ -38,13 +38,15 @@ std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getName(const clang::NamedDecl
}
}
if ((clang::isa<clang::CXXRecordDecl>(declaration)) &&
std::shared_ptr<CxxDeclName> declName;
if ((declaration) &&
(clang::isa<clang::CXXRecordDecl>(declaration)) &&
(clang::dyn_cast<clang::CXXRecordDecl>(declaration)->isLambda()))
{
declaration = clang::dyn_cast<clang::CXXRecordDecl>(declaration)->getLambdaCallOperator();
}
std::shared_ptr<CxxDeclName> declName;
if (declaration)
{
declName = getDeclName(clang::dyn_cast<const clang::NamedDecl>(declaration));
@@ -89,195 +91,198 @@ std::shared_ptr<CxxName> CxxDeclNameResolver::getContextName(const clang::DeclCo
std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::NamedDecl* declaration)
{
ScopedSwitcher<const clang::NamedDecl*> switcher(m_currentDecl, declaration);
if (declaration)
{
ScopedSwitcher<const clang::NamedDecl*> switcher(m_currentDecl, declaration);
std::string declNameString = declaration->getNameAsString();
if (const clang::TypeAliasDecl* typeAliasDecl = clang::dyn_cast_or_null<clang::TypeAliasDecl>(declaration))
{
clang::TypeAliasTemplateDecl* templatedDeclaration = typeAliasDecl->getDescribedAliasTemplate();
if (templatedDeclaration)
std::string declNameString = declaration->getNameAsString();
if (const clang::TypeAliasDecl* typeAliasDecl = clang::dyn_cast_or_null<clang::TypeAliasDecl>(declaration))
{
return getDeclName(templatedDeclaration);
}
}
if (const clang::RecordDecl* recordDecl = clang::dyn_cast_or_null<clang::RecordDecl>(declaration))
{
if (recordDecl->isLambda())
{
// we skip this node because its child (the lambda call operator) has already been recorded.
return std::shared_ptr<CxxDeclName>();
}
else if (declNameString.size() == 0)
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
const std::string symbolKindName = (recordDecl->isStruct() ? "struct" : "class");
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol(symbolKindName, presumedBegin), std::vector<std::string>());
}
else if (const clang::CXXRecordDecl* cxxRecordDecl = clang::dyn_cast_or_null<clang::CXXRecordDecl>(declaration))
{
clang::ClassTemplateDecl* templateClassDeclaration = cxxRecordDecl->getDescribedClassTemplate();
if (templateClassDeclaration)
clang::TypeAliasTemplateDecl* templatedDeclaration = typeAliasDecl->getDescribedAliasTemplate();
if (templatedDeclaration)
{
return getDeclName(templateClassDeclaration);
return getDeclName(templatedDeclaration);
}
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(declaration))
}
if (const clang::RecordDecl* recordDecl = clang::dyn_cast_or_null<clang::RecordDecl>(declaration))
{
if (recordDecl->isLambda())
{
const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl =
clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration);
clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters();
unsigned int currentParameterIndex = 0;
std::vector<std::string> templateParameters;
const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs();
const int templateArgumentCount = templateArgumentList.size();
for (int i = 0; i < templateArgumentCount; i++)
// we skip this node because its child (the lambda call operator) has already been recorded.
return std::shared_ptr<CxxDeclName>();
}
else if (declNameString.size() == 0)
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
const std::string symbolKindName = (recordDecl->isStruct() ? "struct" : "class");
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol(symbolKindName, presumedBegin), std::vector<std::string>());
}
else if (const clang::CXXRecordDecl* cxxRecordDecl = clang::dyn_cast_or_null<clang::CXXRecordDecl>(declaration))
{
clang::ClassTemplateDecl* templateClassDeclaration = cxxRecordDecl->getDescribedClassTemplate();
if (templateClassDeclaration)
{
const clang::TemplateArgument& templateArgument = templateArgumentList.get(i);
if (templateArgument.isDependent()) // IMPORTANT_TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter.
return getDeclName(templateClassDeclaration);
}
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(declaration))
{
const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl =
clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration);
clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters();
unsigned int currentParameterIndex = 0;
std::vector<std::string> templateParameters;
const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs();
const int templateArgumentCount = templateArgumentList.size();
for (int i = 0; i < templateArgumentCount; i++)
{
if(currentParameterIndex < parameterList->size())
const clang::TemplateArgument& templateArgument = templateArgumentList.get(i);
if (templateArgument.isDependent()) // IMPORTANT_TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter.
{
templateParameters.push_back(getTemplateParameterString(parameterList->getParam(currentParameterIndex)));
if(currentParameterIndex < parameterList->size())
{
templateParameters.push_back(getTemplateParameterString(parameterList->getParam(currentParameterIndex)));
}
else
{
//this if fixes the crash, but not the problem TODO
// const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
// LOG_ERROR("Template getParam out of Range " + declaration->getLocation().printToString(sourceManager));
}
currentParameterIndex++;
}
else
{
//this if fixes the crash, but not the problem TODO
// const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
// LOG_ERROR("Template getParam out of Range " + declaration->getLocation().printToString(sourceManager));
templateParameters.push_back(getTemplateArgumentName(templateArgument));
}
currentParameterIndex++;
}
else
{
templateParameters.push_back(getTemplateArgumentName(templateArgument));
}
}
return std::make_shared<CxxDeclName>(declNameString, templateParameters);
}
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
{
std::vector<std::string> templateArguments;
const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(declaration)->getTemplateArgs();
for (size_t i = 0; i < templateArgumentList.size(); i++)
return std::make_shared<CxxDeclName>(declNameString, templateParameters);
}
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
{
templateArguments.push_back(getTemplateArgumentName(templateArgumentList.get(i)));
std::vector<std::string> templateArguments;
const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(declaration)->getTemplateArgs();
for (size_t i = 0; i < templateArgumentList.size(); i++)
{
templateArguments.push_back(getTemplateArgumentName(templateArgumentList.get(i)));
}
return std::make_shared<CxxDeclName>(declNameString, templateArguments);
}
return std::make_shared<CxxDeclName>(declNameString, templateArguments);
}
}
}
else if (clang::isa<clang::FunctionDecl>(declaration))
{
const clang::FunctionDecl* functionDecl = clang::dyn_cast<clang::FunctionDecl>(declaration);
else if (clang::isa<clang::FunctionDecl>(declaration))
{
const clang::FunctionDecl* functionDecl = clang::dyn_cast<clang::FunctionDecl>(declaration);
std::string functionName = declNameString;
std::vector<std::string> templateArguments;
std::string functionName = declNameString;
std::vector<std::string> templateArguments;
if ((clang::dyn_cast_or_null<clang::CXXMethodDecl>(functionDecl)) &&
(clang::dyn_cast_or_null<clang::CXXMethodDecl>(functionDecl)->getParent()->isLambda()))
if ((clang::dyn_cast_or_null<clang::CXXMethodDecl>(functionDecl)) &&
(clang::dyn_cast_or_null<clang::CXXMethodDecl>(functionDecl)->getParent()->isLambda()))
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(clang::dyn_cast_or_null<clang::CXXMethodDecl>(functionDecl)->getParent()->getLocStart());
functionName = "lambda at " + std::to_string(presumedBegin.getLine()) + ":" + std::to_string(presumedBegin.getColumn());
}
else if (clang::FunctionTemplateDecl* templateFunctionDeclaration = functionDecl->getDescribedFunctionTemplate())
{
std::shared_ptr<CxxDeclName> templateDeclName = getDeclName(templateFunctionDeclaration);
functionName = templateDeclName->getName();
templateArguments = templateDeclName->getTemplateParameterNames();
}
else
{
if (functionDecl->isFunctionTemplateSpecialization())
{
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));
}
}
}
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::shared_ptr<CxxTypeName> returnTypeName = CxxTypeName::makeUnsolvedIfNull(typenNameResolver.getName(functionDecl->getReturnType()));
std::vector<std::shared_ptr<CxxTypeName>> parameterTypeNames;
for (unsigned int i = 0; i < functionDecl->param_size(); i++)
{
parameterTypeNames.push_back(CxxTypeName::makeUnsolvedIfNull(typenNameResolver.getName(functionDecl->parameters()[i]->getType())));
}
return std::make_shared<CxxFunctionDeclName>(
functionName,
templateArguments,
returnTypeName,
parameterTypeNames,
isConst,
isStatic
);
}
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);
}
else if (clang::isa<clang::NamespaceDecl>(declaration) && clang::dyn_cast<clang::NamespaceDecl>(declaration)->isAnonymousNamespace())
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(clang::dyn_cast_or_null<clang::CXXMethodDecl>(functionDecl)->getParent()->getLocStart());
functionName = "lambda at " + std::to_string(presumedBegin.getLine()) + ":" + std::to_string(presumedBegin.getColumn());
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol("namespace", presumedBegin), std::vector<std::string>());
}
else if (clang::FunctionTemplateDecl* templateFunctionDeclaration = functionDecl->getDescribedFunctionTemplate())
else if (clang::isa<clang::EnumDecl>(declaration) && declNameString.size() == 0)
{
std::shared_ptr<CxxDeclName> templateDeclName = getDeclName(templateFunctionDeclaration);
functionName = templateDeclName->getName();
templateArguments = templateDeclName->getTemplateParameterNames();
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol("enum", presumedBegin), std::vector<std::string>());
}
else
else if (
(
clang::isa<clang::TemplateTypeParmDecl>(declaration) ||
clang::isa<clang::NonTypeTemplateParmDecl>(declaration) ||
clang::isa<clang::TemplateTemplateParmDecl>(declaration)
) && declNameString.size() == 0)
{
if (functionDecl->isFunctionTemplateSpecialization())
{
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::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol("template parameter", presumedBegin), std::vector<std::string>());
}
else if (clang::isa<clang::ParmVarDecl>(declaration) && declNameString.size() == 0)
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol("parameter", presumedBegin), std::vector<std::string>());
}
bool isStatic = false;
bool isConst = false;
if (clang::isa<clang::CXXMethodDecl>(declaration))
if (declNameString.size() > 0)
{
const clang::CXXMethodDecl* methodDecl = clang::dyn_cast<const clang::CXXMethodDecl>(declaration);
isStatic = methodDecl->isStatic();
isConst = methodDecl->isConst();
return std::make_shared<CxxDeclName>(declNameString, std::vector<std::string>(), std::shared_ptr<CxxName>());
}
else
{
isStatic = functionDecl->getStorageClass() == clang::SC_Static;
}
CxxTypeNameResolver typenNameResolver(getIgnoredContextDecls());
typenNameResolver.ignoreContextDecl(functionDecl);
std::shared_ptr<CxxTypeName> returnTypeName = typenNameResolver.getName(functionDecl->getReturnType());
std::vector<std::shared_ptr<CxxTypeName>> parameterTypeNames;
for (unsigned int i = 0; i < functionDecl->param_size(); i++)
{
parameterTypeNames.push_back(typenNameResolver.getName(functionDecl->parameters()[i]->getType()));
}
return std::make_shared<CxxFunctionDeclName>(
functionName,
templateArguments,
returnTypeName,
parameterTypeNames,
isConst,
isStatic
);
}
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);
}
else if (clang::isa<clang::NamespaceDecl>(declaration) && clang::dyn_cast<clang::NamespaceDecl>(declaration)->isAnonymousNamespace())
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol("namespace", presumedBegin), std::vector<std::string>());
}
else if (clang::isa<clang::EnumDecl>(declaration) && declNameString.size() == 0)
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol("enum", presumedBegin), std::vector<std::string>());
}
else if (
(
clang::isa<clang::TemplateTypeParmDecl>(declaration) ||
clang::isa<clang::NonTypeTemplateParmDecl>(declaration) ||
clang::isa<clang::TemplateTemplateParmDecl>(declaration)
) && declNameString.size() == 0)
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol("template parameter", presumedBegin), std::vector<std::string>());
}
else if (clang::isa<clang::ParmVarDecl>(declaration) && declNameString.size() == 0)
{
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart());
return std::make_shared<CxxDeclName>(getNameForAnonymousSymbol("parameter", presumedBegin), std::vector<std::string>());
}
if (declNameString.size() > 0)
{
return std::make_shared<CxxDeclName>(declNameString, std::vector<std::string>(), std::shared_ptr<CxxName>());
}
const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
@@ -300,27 +305,30 @@ std::string CxxDeclNameResolver::getTemplateParameterString(const clang::NamedDe
{
std::string templateParameterTypeString = "";
clang::Decl::Kind templateParameterKind = parameter->getKind();
switch (templateParameterKind)
if (parameter)
{
case clang::Decl::NonTypeTemplateParm:
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::NonTypeTemplateParmDecl>(parameter));
break;
case clang::Decl::TemplateTypeParm:
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTypeParmDecl>(parameter));
break;
case clang::Decl::TemplateTemplateParm:
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTemplateParmDecl>(parameter));
break;
default:
// LOG_ERROR("Unhandled kind of template parameter.");
break;
}
clang::Decl::Kind templateParameterKind = parameter->getKind();
switch (templateParameterKind)
{
case clang::Decl::NonTypeTemplateParm:
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::NonTypeTemplateParmDecl>(parameter));
break;
case clang::Decl::TemplateTypeParm:
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTypeParmDecl>(parameter));
break;
case clang::Decl::TemplateTemplateParm:
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTemplateParmDecl>(parameter));
break;
default:
// LOG_ERROR("Unhandled kind of template parameter.");
break;
}
std::string parameterName = parameter->getName();
if (!parameterName.empty())
{
templateParameterTypeString += " " + parameterName;
std::string parameterName = parameter->getName();
if (!parameterName.empty())
{
templateParameterTypeString += " " + parameterName;
}
}
return templateParameterTypeString;
}
@@ -340,15 +348,8 @@ std::string CxxDeclNameResolver::getTemplateParameterTypeString(const clang::Non
std::string typeString = "";
std::shared_ptr<CxxTypeName> typeName = typeNameResolver.getName(parameter->getType());
if (typeName)
{
typeString = typeName->toString();
}
else
{
LOG_WARNING("unable to solve type of non-type template parameter declaration");
}
std::shared_ptr<CxxTypeName> typeName = CxxTypeName::makeUnsolvedIfNull(typeNameResolver.getName(parameter->getType()));
typeString = typeName->toString();
if (parameter->isTemplateParameterPack())
{
@@ -24,58 +24,58 @@ CxxSpecifierNameResolver::~CxxSpecifierNameResolver()
std::shared_ptr<CxxName> CxxSpecifierNameResolver::getName(const clang::NestedNameSpecifier* nestedNameSpecifier)
{
std::shared_ptr<CxxName> name;
if (!nestedNameSpecifier)
{
return name;
}
clang::NestedNameSpecifier::SpecifierKind nnsKind = nestedNameSpecifier->getKind();
switch (nnsKind)
if (nestedNameSpecifier)
{
case clang::NestedNameSpecifier::Identifier:
clang::NestedNameSpecifier::SpecifierKind nnsKind = nestedNameSpecifier->getKind();
switch (nnsKind)
{
name = std::make_shared<CxxDeclName>(
nestedNameSpecifier->getAsIdentifier()->getName(), std::vector<std::string>()
);
if (const clang::NestedNameSpecifier* prefix = nestedNameSpecifier->getPrefix())
case clang::NestedNameSpecifier::Identifier:
{
std::shared_ptr<CxxName> parentName = getName(prefix);
if (parentName)
name = std::make_shared<CxxDeclName>(
nestedNameSpecifier->getAsIdentifier()->getName(), std::vector<std::string>()
);
if (const clang::NestedNameSpecifier* prefix = nestedNameSpecifier->getPrefix())
{
name->setParent(parentName);
std::shared_ptr<CxxName> parentName = getName(prefix);
if (parentName)
{
name->setParent(parentName);
}
}
}
break;
case clang::NestedNameSpecifier::Namespace:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
name = declNameResolver.getName(nestedNameSpecifier->getAsNamespace());
}
break;
case clang::NestedNameSpecifier::NamespaceAlias:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
name = declNameResolver.getName(nestedNameSpecifier->getAsNamespaceAlias());
}
break;
case clang::NestedNameSpecifier::TypeSpec:
case clang::NestedNameSpecifier::TypeSpecWithTemplate:
{
CxxTypeNameResolver typeNameResolver(getIgnoredContextDecls());
name = CxxTypeName::makeUnsolvedIfNull(typeNameResolver.getName(nestedNameSpecifier->getAsType()));
}
break;
case clang::NestedNameSpecifier::Global:
// no context name hierarchy needed.
break;
case clang::NestedNameSpecifier::Super:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
name = declNameResolver.getName(nestedNameSpecifier->getAsRecordDecl());
}
break;
}
break;
case clang::NestedNameSpecifier::Namespace:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
name = declNameResolver.getName(nestedNameSpecifier->getAsNamespace());
}
break;
case clang::NestedNameSpecifier::NamespaceAlias:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
name = declNameResolver.getName(nestedNameSpecifier->getAsNamespaceAlias());
}
break;
case clang::NestedNameSpecifier::TypeSpec:
case clang::NestedNameSpecifier::TypeSpecWithTemplate:
{
CxxTypeNameResolver typeNameResolver(getIgnoredContextDecls());
name = typeNameResolver.getName(nestedNameSpecifier->getAsType());
}
break;
case clang::NestedNameSpecifier::Global:
// no context name hierarchy needed.
break;
case clang::NestedNameSpecifier::Super:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
name = declNameResolver.getName(nestedNameSpecifier->getAsRecordDecl());
}
break;
}
return name;
}
@@ -30,16 +30,8 @@ std::string CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang
case clang::TemplateArgument::Type:
{
CxxTypeNameResolver typeNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxTypeName> typeName = typeNameResolver.getName(argument.getAsType());
if (typeName)
{
return typeName->toString();
}
else
{
LOG_WARNING("Unable to solve name for template type argument");
}
break;
std::shared_ptr<CxxTypeName> typeName = CxxTypeName::makeUnsolvedIfNull(typeNameResolver.getName(argument.getAsType()));
return typeName->toString();
}
case clang::TemplateArgument::Integral:
case clang::TemplateArgument::Null:
@@ -37,244 +37,266 @@ std::shared_ptr<CxxTypeName> CxxTypeNameResolver::getName(const clang::Type* typ
{
std::shared_ptr<CxxTypeName> typeName;
switch (type->getTypeClass())
if (type)
{
case clang::Type::Paren:
{
typeName = getName(type->getAs<clang::ParenType>()->getInnerType());
break;
}
case clang::Type::Typedef:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(type->getAs<clang::TypedefType>()->getDecl());
if (declName)
switch (type->getTypeClass())
{
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
std::vector<std::string>(),
declName->getParent()
);
}
break;
}
case clang::Type::MemberPointer:
case clang::Type::Pointer:
{
typeName = getName(type->getPointeeType());
typeName->addModifier(CxxTypeName::Modifier("*"));
break;
}
case clang::Type::ConstantArray:
case clang::Type::DependentSizedArray:
case clang::Type::IncompleteArray:
case clang::Type::VariableArray:
{
typeName = getName(clang::dyn_cast<clang::ArrayType>(type)->getElementType());
typeName->addModifier(CxxTypeName::Modifier("[]"));
break;
}
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
typeName = getName(type->getPointeeType());
typeName->addModifier(CxxTypeName::Modifier("&"));
break;
}
case clang::Type::Elaborated:
{
typeName = getName(clang::dyn_cast<clang::ElaboratedType>(type)->getNamedType());
break;
}
case clang::Type::Enum:
case clang::Type::Record:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(type->getAs<clang::TagType>()->getDecl());
if (declName)
{
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
std::vector<std::string>(),
declName->getParent()
);
}
break;
}
case clang::Type::Builtin:
{
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
typeName = std::make_shared<CxxTypeName>(
type->getAs<clang::BuiltinType>()->getName(pp), std::vector<std::string>()
);
break;
}
case clang::Type::TemplateSpecialization:
{
const clang::TagType* tagType = type->getAs<clang::TagType>(); // remove this case when NameHierarchy is split into namepart and parameter part
if (tagType)
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(tagType->getDecl());
if (declName)
case clang::Type::Paren:
{
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
declName->getTemplateParameterNames(),
declName->getParent()
);
typeName = getName(type->getAs<clang::ParenType>()->getInnerType());
break;
}
}
else // specialization of a template template parameter (no concrete class) important, may help: has no underlying decl!
{
const clang::TemplateSpecializationType* templateSpecializationType = type->getAs<clang::TemplateSpecializationType>();
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
const std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(templateSpecializationType->getTemplateName().getAsTemplateDecl());
if (declName)
case clang::Type::Attributed:
{
typeName = getName(type->getAs<clang::AttributedType>()->getModifiedType());
break;
}
case clang::Type::InjectedClassName:
{
typeName = getName(type->getAs<clang::InjectedClassNameType>()->getInjectedSpecializationType());
break;
}
case clang::Type::Typedef:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(type->getAs<clang::TypedefType>()->getDecl());
if (declName)
{
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
std::vector<std::string>(),
declName->getParent()
);
}
break;
}
case clang::Type::MemberPointer:
case clang::Type::Pointer:
{
typeName = getName(type->getPointeeType());
if (typeName)
{
typeName->addModifier(CxxTypeName::Modifier("*"));
}
break;
}
case clang::Type::ConstantArray:
case clang::Type::DependentSizedArray:
case clang::Type::IncompleteArray:
case clang::Type::VariableArray:
{
typeName = getName(clang::dyn_cast<clang::ArrayType>(type)->getElementType());
if (typeName)
{
typeName->addModifier(CxxTypeName::Modifier("[]"));
}
break;
}
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
typeName = getName(type->getPointeeType());
if (typeName)
{
typeName->addModifier(CxxTypeName::Modifier("&"));
}
break;
}
case clang::Type::Elaborated:
{
typeName = getName(clang::dyn_cast<clang::ElaboratedType>(type)->getNamedType());
break;
}
case clang::Type::Enum:
case clang::Type::Record:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(type->getAs<clang::TagType>()->getDecl());
if (declName)
{
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
declName->getTemplateParameterNames(), // contains template arguments if decl is a template specialization
declName->getParent()
);
}
break;
}
case clang::Type::Builtin:
{
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
typeName = std::make_shared<CxxTypeName>(
type->getAs<clang::BuiltinType>()->getName(pp), std::vector<std::string>()
);
break;
}
case clang::Type::TemplateSpecialization:
{
const clang::TagType* tagType = type->getAs<clang::TagType>(); // remove this case when NameHierarchy is split into namepart and parameter part
if (tagType)
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(tagType->getDecl());
if (declName)
{
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
declName->getTemplateParameterNames(),
declName->getParent()
);
}
}
else // specialization of a template template parameter (no concrete class) important, may help: has no underlying decl!
{
const clang::TemplateSpecializationType* templateSpecializationType = type->getAs<clang::TemplateSpecializationType>();
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
const std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(templateSpecializationType->getTemplateName().getAsTemplateDecl());
if (declName)
{
std::vector<std::string> templateArguments;
CxxTemplateArgumentNameResolver resolver(getIgnoredContextDecls());
for (size_t i = 0; i < templateSpecializationType->getNumArgs(); i++)
{
templateArguments.push_back(resolver.getTemplateArgumentName(templateSpecializationType->getArg(i)));
}
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
templateArguments,
declName->getParent()
);
}
else
{
LOG_WARNING("no decl found");
}
}
break;
}
case clang::Type::TemplateTypeParm:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(clang::dyn_cast<clang::TemplateTypeParmType>(type)->getDecl());
if (declName)
{
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
declName->getTemplateParameterNames(),
declName->getParent()
);
}
break;
}
case clang::Type::SubstTemplateTypeParm:
{
typeName = getName(type->getAs<clang::SubstTemplateTypeParmType>()->getReplacementType());
break;
}
case clang::Type::DependentName:
{
const clang::DependentNameType* dependentType = clang::dyn_cast<clang::DependentNameType>(type);
CxxSpecifierNameResolver specifierNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxName> specifierName = specifierNameResolver.getName(dependentType->getQualifier());
typeName = std::make_shared<CxxTypeName>(
dependentType->getIdentifier()->getName().str(), std::vector<std::string>(), specifierName
);
break;
}
case clang::Type::DependentTemplateSpecialization:
{
const clang::DependentTemplateSpecializationType* dependentType = clang::dyn_cast<clang::DependentTemplateSpecializationType>(type);
CxxSpecifierNameResolver specifierNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxName> specifierName = specifierNameResolver.getName(dependentType->getQualifier());
std::vector<std::string> templateArguments;
CxxTemplateArgumentNameResolver resolver(getIgnoredContextDecls());
for (size_t i = 0; i < templateSpecializationType->getNumArgs(); i++)
for (size_t i = 0; i < dependentType->getNumArgs(); i++)
{
templateArguments.push_back(resolver.getTemplateArgumentName(templateSpecializationType->getArg(i)));
templateArguments.push_back(resolver.getTemplateArgumentName(dependentType->getArg(i)));
}
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
templateArguments,
declName->getParent()
dependentType->getIdentifier()->getName().str(), templateArguments, specifierName
);
break;
}
else
case clang::Type::PackExpansion:
{
LOG_WARNING("no decl found");
typeName = getName(clang::dyn_cast<clang::PackExpansionType>(type)->getPattern());
break;
}
}
break;
}
case clang::Type::TemplateTypeParm:
{
CxxDeclNameResolver declNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxDeclName> declName = declNameResolver.getName(clang::dyn_cast<clang::TemplateTypeParmType>(type)->getDecl());
if (declName)
{
typeName = std::make_shared<CxxTypeName>(
declName->getName(),
declName->getTemplateParameterNames(),
declName->getParent()
);
}
break;
}
case clang::Type::SubstTemplateTypeParm:
{
typeName = getName(type->getAs<clang::SubstTemplateTypeParmType>()->getReplacementType());
break;
}
case clang::Type::DependentName:
{
const clang::DependentNameType* dependentType = clang::dyn_cast<clang::DependentNameType>(type);
CxxSpecifierNameResolver specifierNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxName> specifierName = specifierNameResolver.getName(dependentType->getQualifier());
typeName = std::make_shared<CxxTypeName>(
dependentType->getIdentifier()->getName().str(), std::vector<std::string>(), specifierName
);
break;
}
case clang::Type::DependentTemplateSpecialization:
{
const clang::DependentTemplateSpecializationType* dependentType = clang::dyn_cast<clang::DependentTemplateSpecializationType>(type);
CxxSpecifierNameResolver specifierNameResolver(getIgnoredContextDecls());
std::shared_ptr<CxxName> specifierName = specifierNameResolver.getName(dependentType->getQualifier());
std::vector<std::string> templateArguments;
CxxTemplateArgumentNameResolver resolver(getIgnoredContextDecls());
for (size_t i = 0; i < dependentType->getNumArgs(); i++)
{
templateArguments.push_back(resolver.getTemplateArgumentName(dependentType->getArg(i)));
}
typeName = std::make_shared<CxxTypeName>(
dependentType->getIdentifier()->getName().str(), templateArguments, specifierName
);
break;
}
case clang::Type::PackExpansion:
{
typeName = getName(clang::dyn_cast<clang::PackExpansionType>(type)->getPattern());
break;
}
case clang::Type::Auto:
{
clang::QualType deducedType = clang::dyn_cast<clang::AutoType>(type)->getDeducedType();
if (!deducedType.isNull())
{
typeName = getName(deducedType);
}
else
{
typeName = std::make_shared<CxxTypeName>(
"auto", std::vector<std::string>()
);
}
break;
}
case clang::Type::Decltype:
{
typeName = getName(clang::dyn_cast<clang::DecltypeType>(type)->getUnderlyingType());
break;
}
case clang::Type::FunctionProto:
{
const clang::FunctionProtoType* protoType = clang::dyn_cast<clang::FunctionProtoType>(type);
std::string nameString = getName(protoType->getReturnType())->toString();
nameString += "(";
for (size_t i = 0; i < protoType->getNumParams(); i++)
{
if (i != 0)
case clang::Type::Auto:
{
nameString += ", ";
clang::QualType deducedType = clang::dyn_cast<clang::AutoType>(type)->getDeducedType();
if (!deducedType.isNull())
{
typeName = getName(deducedType);
}
else
{
typeName = std::make_shared<CxxTypeName>(
"auto", std::vector<std::string>()
);
}
break;
}
case clang::Type::Decltype:
{
typeName = getName(clang::dyn_cast<clang::DecltypeType>(type)->getUnderlyingType());
break;
}
case clang::Type::FunctionProto:
{
const clang::FunctionProtoType* protoType = clang::dyn_cast<clang::FunctionProtoType>(type);
std::string nameString = CxxTypeName::makeUnsolvedIfNull(getName(protoType->getReturnType()))->toString();
nameString += "(";
for (size_t i = 0; i < protoType->getNumParams(); i++)
{
if (i != 0)
{
nameString += ", ";
}
nameString += CxxTypeName::makeUnsolvedIfNull(getName(protoType->getParamType(i)))->toString();
}
nameString += ")";
typeName = std::make_shared<CxxTypeName>(
nameString, std::vector<std::string>()
);
break;
}
case clang::Type::Adjusted:
case clang::Type::Decayed:
{
typeName = getName(type->getAs<clang::AdjustedType>()->getOriginalType());
break;
}
default:
{
std::string typeClassName = type->getTypeClassName();
LOG_INFO(std::string("Unhandled kind of type encountered: ") + typeClassName);
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
clang::SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
clang::QualType::print(type, clang::Qualifiers(), StrOS, pp, clang::Twine());
std::string nameString = StrOS.str();
typeName = std::make_shared<CxxTypeName>(
nameString, std::vector<std::string>()
);
break;
}
nameString += getName(protoType->getParamType(i))->toString();
}
nameString += ")";
typeName = std::make_shared<CxxTypeName>(
nameString, std::vector<std::string>()
);
break;
}
case clang::Type::Adjusted:
case clang::Type::Decayed:
{
typeName = getName(type->getAs<clang::AdjustedType>()->getOriginalType());
break;
}
default:
{
std::string typeClassName = type->getTypeClassName();
LOG_INFO(std::string("Unhandled kind of type encountered: ") + typeClassName);
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
clang::SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
clang::QualType::print(type, clang::Qualifiers(), StrOS, pp, clang::Twine());
std::string nameString = StrOS.str();
typeName = std::make_shared<CxxTypeName>(
nameString, std::vector<std::string>()
);
break;
}
}
return typeName;
}
+18 -5
View File
@@ -1296,11 +1296,6 @@ public:
));
}
void test_cxx_parser_finds_type_usage_of_global_variable()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -2030,6 +2025,24 @@ public:
));
}
void test_cxx_parser_usage_of_injected_type_in_method_declaration()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
"class Foo\n"
"{\n"
" Foo& operator=(const Foo&) = delete;\n"
"};\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->typeUses, "Foo<Foo<typename T>::T> & Foo<typename T>::operator=(const Foo<Foo<typename T>::T> &) -> Foo<Foo<typename T>::T> <4:2 4:4>"
));
TS_ASSERT(utility::containsElement<std::string>(
client->typeUses, "Foo<Foo<typename T>::T> & Foo<typename T>::operator=(const Foo<Foo<typename T>::T> &) -> Foo<Foo<typename T>::T> <4:23 4:25>"
));
}
void test_cxx_parser_finds_use_of_qualified_type_in_function()
{
std::shared_ptr<TestParserClient> client = parseCode(