diff --git a/src/lib/data/StorageProvider.cpp b/src/lib/data/StorageProvider.cpp index 5a9fca0c..70160f50 100644 --- a/src/lib/data/StorageProvider.cpp +++ b/src/lib/data/StorageProvider.cpp @@ -1,5 +1,7 @@ #include "data/StorageProvider.h" +#include "utility/logging/logging.h" + int StorageProvider::getStorageCount() const { std::lock_guard lock(m_storagesMutex); @@ -57,5 +59,18 @@ std::shared_ptr StorageProvider::popInjectionSource() return ret; } +void StorageProvider::logCurrentState() const +{ + std::string logString = "Storages waiting for injection:"; + { + std::lock_guard lock(m_storagesMutex); + for (std::shared_ptr storage: m_storages) + { + logString += " " + std::to_string(storage->getSourceLocationCount()) + ";"; + } + } + LOG_INFO(logString); +} + diff --git a/src/lib/data/StorageProvider.h b/src/lib/data/StorageProvider.h index 4fe329b8..3d19e6db 100644 --- a/src/lib/data/StorageProvider.h +++ b/src/lib/data/StorageProvider.h @@ -18,6 +18,8 @@ public: // returns empty shared_ptr if no storages available std::shared_ptr popInjectionSource(); + void logCurrentState() const; + private: std::list> m_storages; // larger storages are in front mutable std::mutex m_storagesMutex; diff --git a/src/lib/utility/file/FileManager.cpp b/src/lib/utility/file/FileManager.cpp index 58b75a63..c9d17759 100644 --- a/src/lib/utility/file/FileManager.cpp +++ b/src/lib/utility/file/FileManager.cpp @@ -27,8 +27,8 @@ void FileManager::setPaths( std::vector 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 FileManager::makeCanonical(const std::vector& filePaths) +{ + std::vector 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) diff --git a/src/lib/utility/file/FileManager.h b/src/lib/utility/file/FileManager.h index 6247f872..143d24f3 100644 --- a/src/lib/utility/file/FileManager.h +++ b/src/lib/utility/file/FileManager.h @@ -34,6 +34,7 @@ public: virtual const FileInfo getFileInfo(const FilePath& filePath) const; private: + std::vector makeCanonical(const std::vector& filePaths); bool isExcluded(const FilePath& filePath) const; std::map m_files; diff --git a/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp b/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp index a2f1f36b..be29d1b6 100644 --- a/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp +++ b/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp @@ -1215,6 +1215,7 @@ bool CxxAstVisitor::checkIgnoresTypeLoc(const clang::TypeLoc& tl) (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || + (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || (!tl.getAs().isNull()) || diff --git a/src/lib_cxx/data/parser/cxx/name/CxxFunctionDeclName.cpp b/src/lib_cxx/data/parser/cxx/name/CxxFunctionDeclName.cpp index 83fadbfc..e3c7c66a 100644 --- a/src/lib_cxx/data/parser/cxx/name/CxxFunctionDeclName.cpp +++ b/src/lib_cxx/data/parser/cxx/name/CxxFunctionDeclName.cpp @@ -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) diff --git a/src/lib_cxx/data/parser/cxx/name/CxxTypeName.cpp b/src/lib_cxx/data/parser/cxx/name/CxxTypeName.cpp index a71d9e02..b54a0eeb 100644 --- a/src/lib_cxx/data/parser/cxx/name/CxxTypeName.cpp +++ b/src/lib_cxx/data/parser/cxx/name/CxxTypeName.cpp @@ -1,5 +1,16 @@ #include "data/parser/cxx/name/CxxTypeName.h" +std::shared_ptr CxxTypeName::makeUnsolvedIfNull(std::shared_ptr name) +{ + if (name) + { + return name; + } + return std::make_shared( + "unsolved-type", std::vector() + ); +} + CxxTypeName::Modifier::Modifier(std::string symbol) : symbol(symbol) { diff --git a/src/lib_cxx/data/parser/cxx/name/CxxTypeName.h b/src/lib_cxx/data/parser/cxx/name/CxxTypeName.h index 130a09b4..00d4abaa 100644 --- a/src/lib_cxx/data/parser/cxx/name/CxxTypeName.h +++ b/src/lib_cxx/data/parser/cxx/name/CxxTypeName.h @@ -13,6 +13,8 @@ class CxxTypeName: public CxxName { public: + static std::shared_ptr makeUnsolvedIfNull(std::shared_ptr name); + struct Modifier { Modifier(std::string symbol); diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp index ca015ccd..623e76b9 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp @@ -38,13 +38,15 @@ std::shared_ptr CxxDeclNameResolver::getName(const clang::NamedDecl } } - if ((clang::isa(declaration)) && + std::shared_ptr declName; + + if ((declaration) && + (clang::isa(declaration)) && (clang::dyn_cast(declaration)->isLambda())) { declaration = clang::dyn_cast(declaration)->getLambdaCallOperator(); } - std::shared_ptr declName; if (declaration) { declName = getDeclName(clang::dyn_cast(declaration)); @@ -89,195 +91,198 @@ std::shared_ptr CxxDeclNameResolver::getContextName(const clang::DeclCo std::shared_ptr CxxDeclNameResolver::getDeclName(const clang::NamedDecl* declaration) { - ScopedSwitcher switcher(m_currentDecl, declaration); + if (declaration) + { + ScopedSwitcher switcher(m_currentDecl, declaration); - std::string declNameString = declaration->getNameAsString(); - if (const clang::TypeAliasDecl* typeAliasDecl = clang::dyn_cast_or_null(declaration)) - { - clang::TypeAliasTemplateDecl* templatedDeclaration = typeAliasDecl->getDescribedAliasTemplate(); - if (templatedDeclaration) + std::string declNameString = declaration->getNameAsString(); + if (const clang::TypeAliasDecl* typeAliasDecl = clang::dyn_cast_or_null(declaration)) { - return getDeclName(templatedDeclaration); - } - } - if (const clang::RecordDecl* recordDecl = clang::dyn_cast_or_null(declaration)) - { - if (recordDecl->isLambda()) - { - // we skip this node because its child (the lambda call operator) has already been recorded. - return std::shared_ptr(); - } - 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(getNameForAnonymousSymbol(symbolKindName, presumedBegin), std::vector()); - } - else if (const clang::CXXRecordDecl* cxxRecordDecl = clang::dyn_cast_or_null(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(declaration)) + } + if (const clang::RecordDecl* recordDecl = clang::dyn_cast_or_null(declaration)) + { + if (recordDecl->isLambda()) { - const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl = - clang::dyn_cast(declaration); - - clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters(); - unsigned int currentParameterIndex = 0; - - std::vector 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(); + } + 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(getNameForAnonymousSymbol(symbolKindName, presumedBegin), std::vector()); + } + else if (const clang::CXXRecordDecl* cxxRecordDecl = clang::dyn_cast_or_null(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(declaration)) + { + const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl = + clang::dyn_cast(declaration); + + clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters(); + unsigned int currentParameterIndex = 0; + + std::vector 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(declNameString, templateParameters); - } - else if (clang::isa(declaration)) - { - std::vector templateArguments; - const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast(declaration)->getTemplateArgs(); - for (size_t i = 0; i < templateArgumentList.size(); i++) + return std::make_shared(declNameString, templateParameters); + } + else if (clang::isa(declaration)) { - templateArguments.push_back(getTemplateArgumentName(templateArgumentList.get(i))); + std::vector templateArguments; + const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast(declaration)->getTemplateArgs(); + for (size_t i = 0; i < templateArgumentList.size(); i++) + { + templateArguments.push_back(getTemplateArgumentName(templateArgumentList.get(i))); + } + return std::make_shared(declNameString, templateArguments); } - return std::make_shared(declNameString, templateArguments); } } - } - else if (clang::isa(declaration)) - { - const clang::FunctionDecl* functionDecl = clang::dyn_cast(declaration); + else if (clang::isa(declaration)) + { + const clang::FunctionDecl* functionDecl = clang::dyn_cast(declaration); - std::string functionName = declNameString; - std::vector templateArguments; + std::string functionName = declNameString; + std::vector templateArguments; - if ((clang::dyn_cast_or_null(functionDecl)) && - (clang::dyn_cast_or_null(functionDecl)->getParent()->isLambda())) + if ((clang::dyn_cast_or_null(functionDecl)) && + (clang::dyn_cast_or_null(functionDecl)->getParent()->isLambda())) + { + const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager(); + const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(clang::dyn_cast_or_null(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 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(declaration)) + { + const clang::CXXMethodDecl* methodDecl = clang::dyn_cast(declaration); + isStatic = methodDecl->isStatic(); + isConst = methodDecl->isConst(); + } + else + { + isStatic = functionDecl->getStorageClass() == clang::SC_Static; + } + + CxxTypeNameResolver typenNameResolver(getIgnoredContextDecls()); + typenNameResolver.ignoreContextDecl(functionDecl); + std::shared_ptr returnTypeName = CxxTypeName::makeUnsolvedIfNull(typenNameResolver.getName(functionDecl->getReturnType())); + + std::vector> 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( + functionName, + templateArguments, + returnTypeName, + parameterTypeNames, + isConst, + isStatic + ); + } + else if (clang::isa(declaration)) // also triggers on TemplateTemplateParmDecl + { + std::vector templateParameters; + clang::TemplateParameterList* parameterList = clang::dyn_cast(declaration)->getTemplateParameters(); + for (size_t i = 0; i < parameterList->size(); i++) + { + templateParameters.push_back(getTemplateParameterString(parameterList->getParam(i))); + } + return std::make_shared(declNameString, templateParameters); + } + else if (clang::isa(declaration) && clang::dyn_cast(declaration)->isAnonymousNamespace()) { const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager(); - const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(clang::dyn_cast_or_null(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(getNameForAnonymousSymbol("namespace", presumedBegin), std::vector()); } - else if (clang::FunctionTemplateDecl* templateFunctionDeclaration = functionDecl->getDescribedFunctionTemplate()) + else if (clang::isa(declaration) && declNameString.size() == 0) { - std::shared_ptr 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(getNameForAnonymousSymbol("enum", presumedBegin), std::vector()); } - else + else if ( + ( + clang::isa(declaration) || + clang::isa(declaration) || + clang::isa(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(getNameForAnonymousSymbol("template parameter", presumedBegin), std::vector()); + } + else if (clang::isa(declaration) && declNameString.size() == 0) + { + const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager(); + const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart()); + return std::make_shared(getNameForAnonymousSymbol("parameter", presumedBegin), std::vector()); } - bool isStatic = false; - bool isConst = false; - - if (clang::isa(declaration)) + if (declNameString.size() > 0) { - const clang::CXXMethodDecl* methodDecl = clang::dyn_cast(declaration); - isStatic = methodDecl->isStatic(); - isConst = methodDecl->isConst(); + return std::make_shared(declNameString, std::vector(), std::shared_ptr()); } - else - { - isStatic = functionDecl->getStorageClass() == clang::SC_Static; - } - - CxxTypeNameResolver typenNameResolver(getIgnoredContextDecls()); - typenNameResolver.ignoreContextDecl(functionDecl); - std::shared_ptr returnTypeName = typenNameResolver.getName(functionDecl->getReturnType()); - - std::vector> parameterTypeNames; - for (unsigned int i = 0; i < functionDecl->param_size(); i++) - { - parameterTypeNames.push_back(typenNameResolver.getName(functionDecl->parameters()[i]->getType())); - } - - return std::make_shared( - functionName, - templateArguments, - returnTypeName, - parameterTypeNames, - isConst, - isStatic - ); - } - else if (clang::isa(declaration)) // also triggers on TemplateTemplateParmDecl - { - std::vector templateParameters; - clang::TemplateParameterList* parameterList = clang::dyn_cast(declaration)->getTemplateParameters(); - for (size_t i = 0; i < parameterList->size(); i++) - { - templateParameters.push_back(getTemplateParameterString(parameterList->getParam(i))); - } - return std::make_shared(declNameString, templateParameters); - } - else if (clang::isa(declaration) && clang::dyn_cast(declaration)->isAnonymousNamespace()) - { - const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager(); - const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart()); - return std::make_shared(getNameForAnonymousSymbol("namespace", presumedBegin), std::vector()); - } - else if (clang::isa(declaration) && declNameString.size() == 0) - { - const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager(); - const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart()); - return std::make_shared(getNameForAnonymousSymbol("enum", presumedBegin), std::vector()); - } - else if ( - ( - clang::isa(declaration) || - clang::isa(declaration) || - clang::isa(declaration) - ) && declNameString.size() == 0) - { - const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager(); - const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart()); - return std::make_shared(getNameForAnonymousSymbol("template parameter", presumedBegin), std::vector()); - } - else if (clang::isa(declaration) && declNameString.size() == 0) - { - const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager(); - const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(declaration->getLocStart()); - return std::make_shared(getNameForAnonymousSymbol("parameter", presumedBegin), std::vector()); - } - - if (declNameString.size() > 0) - { - return std::make_shared(declNameString, std::vector(), std::shared_ptr()); } 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(parameter)); - break; - case clang::Decl::TemplateTypeParm: - templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast(parameter)); - break; - case clang::Decl::TemplateTemplateParm: - templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast(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(parameter)); + break; + case clang::Decl::TemplateTypeParm: + templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast(parameter)); + break; + case clang::Decl::TemplateTemplateParm: + templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast(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 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 typeName = CxxTypeName::makeUnsolvedIfNull(typeNameResolver.getName(parameter->getType())); + typeString = typeName->toString(); if (parameter->isTemplateParameterPack()) { diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxSpecifierNameResolver.cpp b/src/lib_cxx/data/parser/cxx/name_resolver/CxxSpecifierNameResolver.cpp index e13932eb..19d0abf0 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxSpecifierNameResolver.cpp +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxSpecifierNameResolver.cpp @@ -24,58 +24,58 @@ CxxSpecifierNameResolver::~CxxSpecifierNameResolver() std::shared_ptr CxxSpecifierNameResolver::getName(const clang::NestedNameSpecifier* nestedNameSpecifier) { std::shared_ptr 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( - nestedNameSpecifier->getAsIdentifier()->getName(), std::vector() - ); - - if (const clang::NestedNameSpecifier* prefix = nestedNameSpecifier->getPrefix()) + case clang::NestedNameSpecifier::Identifier: { - std::shared_ptr parentName = getName(prefix); - if (parentName) + name = std::make_shared( + nestedNameSpecifier->getAsIdentifier()->getName(), std::vector() + ); + + if (const clang::NestedNameSpecifier* prefix = nestedNameSpecifier->getPrefix()) { - name->setParent(parentName); + std::shared_ptr 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; } diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp b/src/lib_cxx/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp index f43c8b7a..5e7b37a0 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp @@ -30,16 +30,8 @@ std::string CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang case clang::TemplateArgument::Type: { CxxTypeNameResolver typeNameResolver(getIgnoredContextDecls()); - std::shared_ptr 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 typeName = CxxTypeName::makeUnsolvedIfNull(typeNameResolver.getName(argument.getAsType())); + return typeName->toString(); } case clang::TemplateArgument::Integral: case clang::TemplateArgument::Null: diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp b/src/lib_cxx/data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp index f5822dad..d865897b 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp @@ -37,244 +37,266 @@ std::shared_ptr CxxTypeNameResolver::getName(const clang::Type* typ { std::shared_ptr typeName; - switch (type->getTypeClass()) + if (type) { - case clang::Type::Paren: - { - typeName = getName(type->getAs()->getInnerType()); - break; - } - case clang::Type::Typedef: - { - CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); - std::shared_ptr declName = declNameResolver.getName(type->getAs()->getDecl()); - if (declName) + switch (type->getTypeClass()) { - typeName = std::make_shared( - declName->getName(), - std::vector(), - 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(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(type)->getNamedType()); - break; - } - case clang::Type::Enum: - case clang::Type::Record: - { - CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); - std::shared_ptr declName = declNameResolver.getName(type->getAs()->getDecl()); - if (declName) - { - typeName = std::make_shared( - declName->getName(), - std::vector(), - 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( - type->getAs()->getName(pp), std::vector() - ); - break; - } - case clang::Type::TemplateSpecialization: - { - const clang::TagType* tagType = type->getAs(); // remove this case when NameHierarchy is split into namepart and parameter part - if (tagType) - { - CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); - std::shared_ptr declName = declNameResolver.getName(tagType->getDecl()); - if (declName) + case clang::Type::Paren: { - typeName = std::make_shared( - declName->getName(), - declName->getTemplateParameterNames(), - declName->getParent() - ); + typeName = getName(type->getAs()->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(); - CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); - const std::shared_ptr declName = declNameResolver.getName(templateSpecializationType->getTemplateName().getAsTemplateDecl()); - - if (declName) + case clang::Type::Attributed: { + typeName = getName(type->getAs()->getModifiedType()); + break; + } + case clang::Type::InjectedClassName: + { + typeName = getName(type->getAs()->getInjectedSpecializationType()); + break; + } + case clang::Type::Typedef: + { + CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); + std::shared_ptr declName = declNameResolver.getName(type->getAs()->getDecl()); + if (declName) + { + typeName = std::make_shared( + declName->getName(), + std::vector(), + 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(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(type)->getNamedType()); + break; + } + case clang::Type::Enum: + case clang::Type::Record: + { + CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); + std::shared_ptr declName = declNameResolver.getName(type->getAs()->getDecl()); + if (declName) + { + typeName = std::make_shared( + 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( + type->getAs()->getName(pp), std::vector() + ); + break; + } + case clang::Type::TemplateSpecialization: + { + const clang::TagType* tagType = type->getAs(); // remove this case when NameHierarchy is split into namepart and parameter part + if (tagType) + { + CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); + std::shared_ptr declName = declNameResolver.getName(tagType->getDecl()); + if (declName) + { + typeName = std::make_shared( + 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(); + CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); + const std::shared_ptr declName = declNameResolver.getName(templateSpecializationType->getTemplateName().getAsTemplateDecl()); + + if (declName) + { + std::vector 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( + declName->getName(), + templateArguments, + declName->getParent() + ); + } + else + { + LOG_WARNING("no decl found"); + } + } + break; + } + case clang::Type::TemplateTypeParm: + { + CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); + std::shared_ptr declName = declNameResolver.getName(clang::dyn_cast(type)->getDecl()); + if (declName) + { + typeName = std::make_shared( + declName->getName(), + declName->getTemplateParameterNames(), + declName->getParent() + ); + } + break; + } + case clang::Type::SubstTemplateTypeParm: + { + typeName = getName(type->getAs()->getReplacementType()); + break; + } + case clang::Type::DependentName: + { + const clang::DependentNameType* dependentType = clang::dyn_cast(type); + + CxxSpecifierNameResolver specifierNameResolver(getIgnoredContextDecls()); + std::shared_ptr specifierName = specifierNameResolver.getName(dependentType->getQualifier()); + + typeName = std::make_shared( + dependentType->getIdentifier()->getName().str(), std::vector(), specifierName + ); + break; + } + case clang::Type::DependentTemplateSpecialization: + { + const clang::DependentTemplateSpecializationType* dependentType = clang::dyn_cast(type); + + CxxSpecifierNameResolver specifierNameResolver(getIgnoredContextDecls()); + std::shared_ptr specifierName = specifierNameResolver.getName(dependentType->getQualifier()); + std::vector 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( - 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(type)->getPattern()); + break; } - } - break; - } - case clang::Type::TemplateTypeParm: - { - CxxDeclNameResolver declNameResolver(getIgnoredContextDecls()); - std::shared_ptr declName = declNameResolver.getName(clang::dyn_cast(type)->getDecl()); - if (declName) - { - typeName = std::make_shared( - declName->getName(), - declName->getTemplateParameterNames(), - declName->getParent() - ); - } - break; - } - case clang::Type::SubstTemplateTypeParm: - { - typeName = getName(type->getAs()->getReplacementType()); - break; - } - case clang::Type::DependentName: - { - const clang::DependentNameType* dependentType = clang::dyn_cast(type); - - CxxSpecifierNameResolver specifierNameResolver(getIgnoredContextDecls()); - std::shared_ptr specifierName = specifierNameResolver.getName(dependentType->getQualifier()); - - typeName = std::make_shared( - dependentType->getIdentifier()->getName().str(), std::vector(), specifierName - ); - break; - } - case clang::Type::DependentTemplateSpecialization: - { - const clang::DependentTemplateSpecializationType* dependentType = clang::dyn_cast(type); - - CxxSpecifierNameResolver specifierNameResolver(getIgnoredContextDecls()); - std::shared_ptr specifierName = specifierNameResolver.getName(dependentType->getQualifier()); - - std::vector 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( - dependentType->getIdentifier()->getName().str(), templateArguments, specifierName - ); - break; - } - case clang::Type::PackExpansion: - { - typeName = getName(clang::dyn_cast(type)->getPattern()); - break; - } - case clang::Type::Auto: - { - clang::QualType deducedType = clang::dyn_cast(type)->getDeducedType(); - if (!deducedType.isNull()) - { - typeName = getName(deducedType); - } - else - { - typeName = std::make_shared( - "auto", std::vector() - ); - } - break; - } - case clang::Type::Decltype: - { - typeName = getName(clang::dyn_cast(type)->getUnderlyingType()); - break; - } - case clang::Type::FunctionProto: - { - const clang::FunctionProtoType* protoType = clang::dyn_cast(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(type)->getDeducedType(); + if (!deducedType.isNull()) + { + typeName = getName(deducedType); + } + else + { + typeName = std::make_shared( + "auto", std::vector() + ); + } + break; + } + case clang::Type::Decltype: + { + typeName = getName(clang::dyn_cast(type)->getUnderlyingType()); + break; + } + case clang::Type::FunctionProto: + { + const clang::FunctionProtoType* protoType = clang::dyn_cast(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( + nameString, std::vector() + ); + break; + } + case clang::Type::Adjusted: + case clang::Type::Decayed: + { + typeName = getName(type->getAs()->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( + nameString, std::vector() + ); + break; } - nameString += getName(protoType->getParamType(i))->toString(); } - nameString += ")"; - - typeName = std::make_shared( - nameString, std::vector() - ); - break; - } - case clang::Type::Adjusted: - case clang::Type::Decayed: - { - typeName = getName(type->getAs()->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( - nameString, std::vector() - ); - break; - } } return typeName; } diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index e78fb198..7469630d 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -1296,11 +1296,6 @@ public: )); } - - - - - void test_cxx_parser_finds_type_usage_of_global_variable() { std::shared_ptr client = parseCode( @@ -2030,6 +2025,24 @@ public: )); } + void test_cxx_parser_usage_of_injected_type_in_method_declaration() + { + std::shared_ptr client = parseCode( + "template \n" + "class Foo\n" + "{\n" + " Foo& operator=(const Foo&) = delete;\n" + "};\n" + ); + + TS_ASSERT(utility::containsElement( + client->typeUses, "Foo::T> & Foo::operator=(const Foo::T> &) -> Foo::T> <4:2 4:4>" + )); + TS_ASSERT(utility::containsElement( + client->typeUses, "Foo::T> & Foo::operator=(const Foo::T> &) -> Foo::T> <4:23 4:25>" + )); + } + void test_cxx_parser_finds_use_of_qualified_type_in_function() { std::shared_ptr client = parseCode(