data: name resolving refactored

* Created CxxNameResolver classes that take care of resolving the name hierarchies of clang components.
* NameResolvers store clang::Decls they ignore when traversing the hierarchy of DeclContext nodes. This approach is used to avoid infinite loops when parsing template parameters of a template class that depends on it's template parameters that depend on the template class....

<description>
This commit is contained in:
malte_langkabel
2015-04-27 10:33:31 +02:00
parent e0ddc67597
commit a0340d9438
12 changed files with 779 additions and 623 deletions
+9
View File
@@ -1,6 +1,15 @@
add_files(
CLANG_FILES
data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp
data/parser/cxx/name_resolver/CxxDeclNameResolver.h
data/parser/cxx/name_resolver/CxxNameResolver.cpp
data/parser/cxx/name_resolver/CxxNameResolver.h
data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp
data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h
data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp
data/parser/cxx/name_resolver/CxxTypeNameResolver.h
data/parser/cxx/ASTAction.cpp
data/parser/cxx/ASTAction.h
data/parser/cxx/ASTActionFactory.cpp
@@ -0,0 +1,254 @@
#include "data/parser/cxx/name_resolver/CxxDeclNameResolver.h"
#include <clang/AST/DeclTemplate.h>
#include <clang/AST/ASTContext.h>
#include "data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h"
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include "utility/logging/logging.h"
CxxDeclNameResolver::CxxDeclNameResolver(const clang::Decl* declaration)
: CxxNameResolver(std::vector<const clang::Decl*>())
, m_declaration(declaration)
{
}
CxxDeclNameResolver::CxxDeclNameResolver(const clang::Decl* declaration, std::vector<const clang::Decl*> ignoredContextDecls)
: CxxNameResolver(ignoredContextDecls)
, m_declaration(declaration)
{
}
CxxDeclNameResolver::~CxxDeclNameResolver()
{
}
NameHierarchy CxxDeclNameResolver::getDeclNameHierarchy()
{
NameHierarchy contextNameHierarchy;
if (m_declaration)
{
std::string declName = "";
if (clang::isa<clang::NamedDecl>(m_declaration))
{
declName = getDeclName(clang::dyn_cast<const clang::NamedDecl>(m_declaration));
}
else
{
LOG_ERROR("unhandled declaration type: " + std::string(m_declaration->getDeclKindName()));
}
contextNameHierarchy = getContextNameHierarchy(m_declaration->getDeclContext());
if ((clang::isa<clang::NonTypeTemplateParmDecl>(m_declaration) ||
clang::isa<clang::TemplateTypeParmDecl>(m_declaration) ||
clang::isa<clang::TemplateTemplateParmDecl>(m_declaration)) &&
contextNameHierarchy.size() > 0)
{
std::string lastContextElementName = contextNameHierarchy.back()->getFullName();
contextNameHierarchy.pop();
contextNameHierarchy.push(std::make_shared<NameElement>(lastContextElementName + "::" + declName));
}
else
{
contextNameHierarchy.push(std::make_shared<NameElement>(declName));
}
}
return contextNameHierarchy;
}
NameHierarchy CxxDeclNameResolver::getContextNameHierarchy(const clang::DeclContext* declContext)
{
NameHierarchy contextNameHierarchy;
if (!ignoresContext(declContext))
{
const clang::DeclContext* parentContext = declContext->getParent();
if (parentContext)
{
contextNameHierarchy = getContextNameHierarchy(parentContext);
}
if (clang::isa<clang::NamedDecl>(declContext))
{
std::string declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declContext));
if (declName != "")
{
contextNameHierarchy.push(std::make_shared<NameElement>(declName));
}
}
}
return contextNameHierarchy;
}
std::string CxxDeclNameResolver::getDeclName()
{
const clang::NamedDecl* declaration = clang::dyn_cast<clang::NamedDecl>(m_declaration);
std::string declName = declaration->getNameAsString();
clang::Decl::Kind kind = declaration->getKind();
if (clang::isa<clang::CXXRecordDecl>(declaration))
{
clang::ClassTemplateDecl* templateClassDeclaration = clang::dyn_cast<clang::CXXRecordDecl>(declaration)->getDescribedClassTemplate();
if (templateClassDeclaration)
{
declName = getDeclName(templateClassDeclaration);
}
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(declaration))
{
const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl =
clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration);
clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters();
int currentParameterIndex = 0;
std::string specializedParameterNamePart = "<";
int templateArgumentCount = partialSpecializationDecl->getTemplateArgs().size();
const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs();
for (int i = 0; i < templateArgumentCount; i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentList.get(i);
if (templateArgument.isDependent()) // TODO: fix case when arg depends on template parameter of outer template class.
{
specializedParameterNamePart += getTemplateParameterString(parameterList->getParam(currentParameterIndex));
currentParameterIndex++;
}
else
{
specializedParameterNamePart += getTemplateArgumentName(templateArgument);
}
specializedParameterNamePart += (i < templateArgumentCount - 1) ? ", " : "";
}
specializedParameterNamePart += ">";
declName += specializedParameterNamePart;
}
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
{
std::string templateArgumentNamePart = "<";
const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(declaration)->getTemplateArgs();
for (size_t i = 0; i < templateArgumentList.size(); i++)
{
templateArgumentNamePart += getTemplateArgumentName(templateArgumentList.get(i));
templateArgumentNamePart += (i < templateArgumentList.size() - 1) ? ", " : "";
}
templateArgumentNamePart += ">";
declName += templateArgumentNamePart;
}
}
else if (clang::isa<clang::FunctionDecl>(declaration))
{
clang::FunctionTemplateDecl* templateFunctionDeclaration = clang::dyn_cast<clang::FunctionDecl>(declaration)->getDescribedFunctionTemplate();
if (templateFunctionDeclaration)
{
declName = getDeclName(templateFunctionDeclaration);
}
else if (clang::dyn_cast<clang::FunctionDecl>(declaration)->isFunctionTemplateSpecialization())
{
std::string templateArgumentNamePart = "<";
const clang::TemplateArgumentList* templateArgumentList = clang::dyn_cast<clang::FunctionDecl>(declaration)->getTemplateSpecializationArgs();
for (size_t i = 0; i < templateArgumentList->size(); i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentList->get(i);
templateArgumentNamePart += getTemplateArgumentName(templateArgument);
templateArgumentNamePart += (i < templateArgumentList->size() - 1) ? ", " : "";
}
templateArgumentNamePart += ">";
declName += templateArgumentNamePart;
}
}
else if (clang::isa<clang::TemplateDecl>(declaration)) // also triggers on TemplateTemplateParmDecl
{
std::string templateParameterNamePart = "<";
clang::TemplateParameterList* parameterList = clang::dyn_cast<clang::TemplateDecl>(declaration)->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameterNamePart += getTemplateParameterString(parameterList->getParam(i));
templateParameterNamePart += (i < parameterList->size() - 1) ? ", " : "";
}
templateParameterNamePart += ">";
declName += templateParameterNamePart;
}
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());
declName = "anonymous namespace (" + std::string(presumedBegin.getFilename()) + ")";
}
return declName;
}
std::string CxxDeclNameResolver::getDeclName(const clang::NamedDecl* declaration)
{
CxxDeclNameResolver resolver(declaration);
return resolver.getDeclName();
}
std::string CxxDeclNameResolver::getTemplateParameterString(const clang::NamedDecl* parameter)
{
std::string templateParameterTypeString = "";
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.");
}
std::string parameterName = parameter->getName();
if (!parameterName.empty())
{
templateParameterTypeString += " " + parameterName;
}
return templateParameterTypeString;
}
std::string CxxDeclNameResolver::getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter)
{
CxxTypeNameResolver typeNameResolver(getIgnoredContextDecls());
if (clang::isa<clang::TemplateDecl>(m_declaration))
{
typeNameResolver.ignoreContextDecl(clang::dyn_cast<clang::TemplateDecl>(m_declaration)->getTemplatedDecl());
}
else // works for partial template specializations
{
typeNameResolver.ignoreContextDecl(m_declaration);
}
return typeNameResolver.qualTypeToDataType(parameter->getType())->getFullTypeName();
}
std::string CxxDeclNameResolver::getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter)
{
return (parameter->wasDeclaredWithTypename() ? "typename" : "class");
}
std::string CxxDeclNameResolver::getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter)
{
std::string templateParameterTypeString = "template<";
clang::TemplateParameterList* parameterList = parameter->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameterTypeString += getTemplateParameterString(parameterList->getParam(i));
templateParameterTypeString += (i < parameterList->size() - 1) ? ", " : "";
}
templateParameterTypeString += ">";
templateParameterTypeString += " typename"; // TODO: what if template template parameter is defined with class keyword?
return templateParameterTypeString;
}
std::string CxxDeclNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument)
{
CxxTemplateArgumentNameResolver resolver(getIgnoredContextDecls());
return resolver.getTemplateArgumentName(argument);
}
@@ -0,0 +1,29 @@
#ifndef CXX_DECL_NAME_RESOLVER_H
#define CXX_DECL_NAME_RESOLVER_H
#include "data/name/NameHierarchy.h"
#include "data/parser/cxx/name_resolver/CxxNameResolver.h"
class CxxDeclNameResolver: public CxxNameResolver
{
public:
CxxDeclNameResolver(const clang::Decl* declaration);
CxxDeclNameResolver(const clang::Decl* declaration, std::vector<const clang::Decl*> ignoredContextDecls);
~CxxDeclNameResolver();
NameHierarchy getDeclNameHierarchy();
std::string getDeclName();
private:
NameHierarchy getContextNameHierarchy(const clang::DeclContext* declaration);
std::string getDeclName(const clang::NamedDecl* declaration);
std::string getTemplateParameterString(const clang::NamedDecl* parameter);
std::string getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter);
std::string getTemplateArgumentName(const clang::TemplateArgument& argument);
const clang::Decl* m_declaration;
};
#endif // CXX_DECL_NAME_RESOLVER_H
@@ -0,0 +1,33 @@
#include "data/parser/cxx/name_resolver/CxxNameResolver.h"
CxxNameResolver::CxxNameResolver(std::vector<const clang::Decl*> ignoredContextDecls)
: m_ignoredContextDecls(ignoredContextDecls)
{
}
CxxNameResolver::~CxxNameResolver()
{
}
void CxxNameResolver::ignoreContextDecl(const clang::Decl* decl)
{
m_ignoredContextDecls.push_back(decl);
}
bool CxxNameResolver::ignoresContext(const clang::DeclContext* declContext)
{
const clang::Decl* decl = clang::dyn_cast<clang::Decl>(declContext);
for (int i = 0; i < m_ignoredContextDecls.size(); i++)
{
if (decl == m_ignoredContextDecls[i])
{
return true;
}
}
return false;
}
std::vector<const clang::Decl*> CxxNameResolver::getIgnoredContextDecls() const
{
return m_ignoredContextDecls;
}
@@ -0,0 +1,24 @@
#ifndef CXX_NAME_RESOLVER_H
#define CXX_NAME_RESOLVER_H
#include <vector>
#include "clang/AST/Decl.h"
class CxxNameResolver
{
public:
CxxNameResolver(std::vector<const clang::Decl*> ignoredContextDecls);
~CxxNameResolver();
void ignoreContextDecl(const clang::Decl* decl);
bool ignoresContext(const clang::DeclContext* declContext);
protected:
std::vector<const clang::Decl*> getIgnoredContextDecls() const;
private:
std::vector<const clang::Decl*> m_ignoredContextDecls;
};
#endif // CXX_NAME_RESOLVER_H
@@ -0,0 +1,58 @@
#include "data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h"
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/DeclTemplate.h>
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include "utility/logging/logging.h"
CxxTemplateArgumentNameResolver::CxxTemplateArgumentNameResolver()
: CxxNameResolver(std::vector<const clang::Decl*>())
{
}
CxxTemplateArgumentNameResolver::CxxTemplateArgumentNameResolver(std::vector<const clang::Decl*> ignoredContextDecls)
: CxxNameResolver(ignoredContextDecls)
{
}
CxxTemplateArgumentNameResolver::~CxxTemplateArgumentNameResolver()
{
}
std::string CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument)
{
const clang::TemplateArgument::ArgKind kind = argument.getKind();
switch (kind)
{
case clang::TemplateArgument::Type:
{
CxxTypeNameResolver typeNameResolver(getIgnoredContextDecls());
return typeNameResolver.qualTypeToDataType(argument.getAsType())->getFullTypeName();
}
case clang::TemplateArgument::Integral:
case clang::TemplateArgument::Null:
case clang::TemplateArgument::Declaration:
case clang::TemplateArgument::NullPtr:
case clang::TemplateArgument::Template:
case clang::TemplateArgument::TemplateExpansion:
case clang::TemplateArgument::Expression:
{
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"
std::string buf;
llvm::raw_string_ostream os(buf);
argument.print(pp, os);
return os.str();
}
case clang::TemplateArgument::Pack:
LOG_ERROR("Type of template argument not handled: Pack");
break;
default:
LOG_ERROR("Type of template argument not handled." + argument.getKind());
break;
}
return std::string();
}
@@ -0,0 +1,16 @@
#ifndef CXX_TEMPLATE_ARGUMENT_NAME_RESOLVER_H
#define CXX_TEMPLATE_ARGUMENT_NAME_RESOLVER_H
#include "data/parser/cxx/name_resolver/CxxNameResolver.h"
class CxxTemplateArgumentNameResolver: public CxxNameResolver
{
public:
CxxTemplateArgumentNameResolver();
CxxTemplateArgumentNameResolver(std::vector<const clang::Decl*> ignoredContextDecls);
~CxxTemplateArgumentNameResolver();
std::string getTemplateArgumentName(const clang::TemplateArgument& argument);
};
#endif // CXX_TEMPLATE_ARGUMENT_NAME_RESOLVER_H
@@ -0,0 +1,228 @@
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/DeclTemplate.h>
#include <clang/AST/ASTContext.h>
#include "data/parser/cxx/name_resolver/CxxDeclNameResolver.h"
#include "data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h"
#include "data/type/DataType.h"
#include "data/type/NamedDataType.h"
#include "data/type/ArrayModifiedDataType.h"
#include "data/type/PointerModifiedDataType.h"
#include "data/type/ReferenceModifiedDataType.h"
#include "utility/logging/logging.h"
CxxTypeNameResolver::CxxTypeNameResolver()
: CxxNameResolver(std::vector<const clang::Decl*>())
{
}
CxxTypeNameResolver::CxxTypeNameResolver(std::vector<const clang::Decl*> ignoredContextDecls)
: CxxNameResolver(ignoredContextDecls)
{
}
CxxTypeNameResolver::~CxxTypeNameResolver()
{
}
std::shared_ptr<DataType> CxxTypeNameResolver::qualTypeToDataType(clang::QualType qualType)
{
std::shared_ptr<DataType> dataType = typeToDataType(qualType.getTypePtr());
if (qualType.isConstQualified())
{
dataType->addQualifier(DataType::QUALIFIER_CONST);
}
return dataType;
}
std::shared_ptr<DataType> CxxTypeNameResolver::typeToDataType(const clang::Type* type)
{
std::shared_ptr<DataType> dataType;
switch (type->getTypeClass())
{
case clang::Type::Paren:
{
dataType = qualTypeToDataType(type->getAs<clang::ParenType>()->getInnerType());
break;
}
case clang::Type::Typedef:
{
CxxDeclNameResolver declNameResolver(type->getAs<clang::TypedefType>()->getDecl(), getIgnoredContextDecls());
dataType = std::make_shared<NamedDataType>(declNameResolver.getDeclNameHierarchy());
break;
}
case clang::Type::MemberPointer:
{
int ogogo = 0; // test this case!
}
case clang::Type::Pointer:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(type->getPointeeType());
dataType = std::make_shared<PointerModifiedDataType>(innerType);
break;
}
case clang::Type::ConstantArray:
case clang::Type::VariableArray:
case clang::Type::DependentSizedArray:
case clang::Type::IncompleteArray:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(clang::dyn_cast<clang::ArrayType>(type)->getElementType());
dataType = std::make_shared<ArrayModifiedDataType>(innerType);
break;
}
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(type->getPointeeType());
dataType = std::make_shared<ReferenceModifiedDataType>(innerType);
break;
}
case clang::Type::Elaborated:
{
dataType = qualTypeToDataType(clang::dyn_cast<clang::ElaboratedType>(type)->getNamedType());
break;
}
case clang::Type::Enum:
case clang::Type::Record:
{
CxxDeclNameResolver declNameResolver(type->getAs<clang::TagType>()->getDecl(), getIgnoredContextDecls());
dataType = std::make_shared<NamedDataType>(declNameResolver.getDeclNameHierarchy());
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"
clang::SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
clang::QualType::print(type, clang::Qualifiers(), StrOS, pp, clang::Twine());
std::string typeName = StrOS.str();
NameHierarchy typeNameHerarchy;
typeNameHerarchy.push(std::make_shared<NameElement>(typeName));
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::TemplateSpecialization:
{
NameHierarchy typeNameHerarchy;
const clang::TagType* tagType = type->getAs<clang::TagType>(); // remove this case when NameHierarchy is split into namepart and parameter part
if (tagType)
{
CxxDeclNameResolver declNameResolver(tagType->getDecl(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
}
else // specialization of a template template parameter (no concrete class)
{
const clang::TemplateSpecializationType* templateSpecializationType = type->getAs<clang::TemplateSpecializationType>();
CxxDeclNameResolver declNameResolver(templateSpecializationType->getTemplateName().getAsTemplateDecl(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
if (typeNameHerarchy.size() > 0)
{
std::string templateArgumentNamePart = "<";
CxxTemplateArgumentNameResolver resolver(getIgnoredContextDecls());
for (int i = 0; i < templateSpecializationType->getNumArgs(); i++)
{
templateArgumentNamePart += resolver.getTemplateArgumentName(templateSpecializationType->getArg(i));
if (i < templateSpecializationType->getNumArgs() - 1)
templateArgumentNamePart += ", ";
}
templateArgumentNamePart += ">";
std::string declName = typeNameHerarchy.back()->getFullName();
declName = declName.substr(0, declName.rfind("<")); // remove template parameters - does not work for A<ajaj<ajsj>>
declName += templateArgumentNamePart; // add template arguments
typeNameHerarchy.pop();
typeNameHerarchy.push(std::make_shared<NameElement>(declName));
}
}
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::TemplateTypeParm:
{
clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast<clang::TemplateTypeParmType>(type)->getDecl();
CxxDeclNameResolver declNameResolver(templateTypeParmDecl, getIgnoredContextDecls());
NameHierarchy typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::SubstTemplateTypeParm:
{
dataType = qualTypeToDataType(type->getAs<clang::SubstTemplateTypeParmType>()->getReplacementType());
break;
}
case clang::Type::DependentName:
{
const clang::DependentNameType* dependentNameType = clang::dyn_cast<clang::DependentNameType>(type);
clang::NestedNameSpecifier* nns = dependentNameType->getQualifier();
clang::NestedNameSpecifier::SpecifierKind nnsKind = nns->getKind();
NameHierarchy typeNameHerarchy;
switch (nnsKind)
{
case clang::NestedNameSpecifier::Identifier:
typeNameHerarchy.push(std::make_shared<NameElement>(nns->getAsIdentifier()->getName())); // TODO: Test this one.
break;
case clang::NestedNameSpecifier::Namespace:
{
CxxDeclNameResolver declNameResolver(nns->getAsNamespace(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
}
break;
case clang::NestedNameSpecifier::NamespaceAlias:
{
CxxDeclNameResolver declNameResolver(nns->getAsNamespaceAlias(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
}
break;
case clang::NestedNameSpecifier::TypeSpec:
case clang::NestedNameSpecifier::TypeSpecWithTemplate:
typeNameHerarchy = typeToDataType(nns->getAsType())->getTypeNameHierarchy();
break;
case clang::NestedNameSpecifier::Global:
// no context name hierarchy needed.
break;
case clang::NestedNameSpecifier::Super:
{
CxxDeclNameResolver declNameResolver(nns->getAsRecordDecl(), getIgnoredContextDecls());
typeNameHerarchy = declNameResolver.getDeclNameHierarchy();
}
break;
}
typeNameHerarchy.push(std::make_shared<NameElement>(dependentNameType->getIdentifier()->getName().str()));
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
default:
{
LOG_ERROR(std::string("Unhandled kind of type encountered: ") + type->getTypeClassName());
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 typeName = StrOS.str();
NameHierarchy typeNameHerarchy;
typeNameHerarchy.push(std::make_shared<NameElement>(typeName));
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
}
return dataType;
}
@@ -0,0 +1,20 @@
#ifndef CXX_TYPE_NAME_RESOLVER_H
#define CXX_TYPE_NAME_RESOLVER_H
#include "data/parser/cxx/name_resolver/CxxNameResolver.h"
#include "data/type/DataType.h"
class CxxTypeNameResolver: public CxxNameResolver
{
public:
CxxTypeNameResolver();
CxxTypeNameResolver(std::vector<const clang::Decl*> ignoredContextDecls);
~CxxTypeNameResolver();
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType);
private:
std::shared_ptr<DataType> typeToDataType(const clang::Type* type);
};
#endif // CXX_TYPE_NAME_RESOLVER_H
+6 -543
View File
@@ -1,378 +1,22 @@
#include "data/parser/cxx/utilityCxx.h"
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/DeclTemplate.h>
#include <clang/AST/ASTContext.h>
#include "data/type/DataType.h"
#include "data/parser/cxx/name_resolver/CxxDeclNameResolver.h"
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include "data/type/NamedDataType.h"
#include "data/type/ArrayModifiedDataType.h"
#include "data/type/PointerModifiedDataType.h"
#include "data/type/ReferenceModifiedDataType.h"
#include "utility/utilityString.h"
#include "utility/logging/logging.h"
namespace utility
{
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType)
{
std::shared_ptr<DataType> dataType = typeToDataType(qualType.getTypePtr());
if (qualType.isConstQualified())
{
dataType->addQualifier(DataType::QUALIFIER_CONST);
}
return dataType;
}
std::shared_ptr<DataType> typeToDataType(const clang::Type* type)
{
std::shared_ptr<DataType> dataType;
switch (type->getTypeClass())
{
case clang::Type::Paren:
{
dataType = qualTypeToDataType(type->getAs<clang::ParenType>()->getInnerType());
break;
}
case clang::Type::Typedef:
{
dataType = std::make_shared<NamedDataType>(getDeclNameHierarchy(type->getAs<clang::TypedefType>()->getDecl()));
break;
}
case clang::Type::MemberPointer:
{
int ogogo = 0; // test this case!
}
case clang::Type::Pointer:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(type->getPointeeType());
dataType = std::make_shared<PointerModifiedDataType>(innerType);
break;
}
case clang::Type::ConstantArray:
case clang::Type::VariableArray:
case clang::Type::DependentSizedArray:
case clang::Type::IncompleteArray:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(clang::dyn_cast<clang::ArrayType>(type)->getElementType());
dataType = std::make_shared<ArrayModifiedDataType>(innerType);
break;
}
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(type->getPointeeType());
dataType = std::make_shared<ReferenceModifiedDataType>(innerType);
break;
}
case clang::Type::Elaborated:
{
dataType = qualTypeToDataType(clang::dyn_cast<clang::ElaboratedType>(type)->getNamedType());
break;
}
case clang::Type::Enum:
case clang::Type::Record:
{
dataType = std::make_shared<NamedDataType>(getDeclNameHierarchy(type->getAs<clang::TagType>()->getDecl()));
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"
clang::SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
clang::QualType::print(type, clang::Qualifiers(), StrOS, pp, clang::Twine());
std::string typeName = StrOS.str();
NameHierarchy typeNameHerarchy;
typeNameHerarchy.push(std::make_shared<NameElement>(typeName));
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::TemplateSpecialization:
{
NameHierarchy typeNameHerarchy;
const clang::TagType* tagType = type->getAs<clang::TagType>(); // remove this case when NameHierarchy is split into namepart and parameter part
if (tagType)
{
typeNameHerarchy = getDeclNameHierarchy(tagType->getDecl());
}
else // specialization depends on template template parameter type
{
const clang::TemplateSpecializationType* templateSpecializationType = type->getAs<clang::TemplateSpecializationType>();
typeNameHerarchy = getDeclNameHierarchy(templateSpecializationType->getTemplateName().getAsTemplateDecl());
if (typeNameHerarchy.size() > 0)
{
std::string templateArgumentPart = "<";
for (int i = 0; i < templateSpecializationType->getNumArgs(); i++)
{
templateArgumentPart += getTemplateArgumentName(templateSpecializationType->getArg(i));
if (i < templateSpecializationType->getNumArgs() - 1)
templateArgumentPart += ", ";
}
templateArgumentPart += ">";
std::string declName = typeNameHerarchy.back()->getFullName();
declName = declName.substr(0, declName.rfind("<")); // remove template parameters - does not work for A<ajaj<ajsj>>
declName += templateArgumentPart; // add template arguments
typeNameHerarchy.pop();
typeNameHerarchy.push(std::make_shared<NameElement>(declName));
}
}
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::TemplateTypeParm:
{
clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast<clang::TemplateTypeParmType>(type)->getDecl();
std::string typeName = getDeclName(templateTypeParmDecl);
NameHierarchy typeNameHerarchy = getContextNameHierarchyOfTemplateParameter(templateTypeParmDecl);
if (typeNameHerarchy.size() == 0)
{
LOG_ERROR("Unable to resolve type name hierarchy for template parameter \"" + typeName + "\"");
typeNameHerarchy.push(std::make_shared<NameElement>(typeName));
}
else
{
std::string lastContextElementName = typeNameHerarchy.back()->getFullName();
typeNameHerarchy.pop();
typeNameHerarchy.push(std::make_shared<NameElement>(lastContextElementName + "::" + typeName));
}
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::SubstTemplateTypeParm:
{
dataType = qualTypeToDataType(type->getAs<clang::SubstTemplateTypeParmType>()->getReplacementType());
break;
}
case clang::Type::DependentName:
{
const clang::DependentNameType* dependentNameType = clang::dyn_cast<clang::DependentNameType>(type);
clang::NestedNameSpecifier* nns = dependentNameType->getQualifier();
clang::NestedNameSpecifier::SpecifierKind nnsKind = nns->getKind();
NameHierarchy typeNameHerarchy;
switch (nnsKind)
{
case clang::NestedNameSpecifier::Identifier:
typeNameHerarchy.push(std::make_shared<NameElement>(nns->getAsIdentifier()->getName()));
LOG_ERROR("Unable to resolve name of nested name specifier of kind: Identifier"); // this one is not tested yet. tell malte if you get this log error.
break;
case clang::NestedNameSpecifier::Namespace:
typeNameHerarchy = getDeclNameHierarchy(nns->getAsNamespace());
break;
case clang::NestedNameSpecifier::NamespaceAlias:
typeNameHerarchy = getDeclNameHierarchy(nns->getAsNamespaceAlias());
break;
case clang::NestedNameSpecifier::TypeSpec:
case clang::NestedNameSpecifier::TypeSpecWithTemplate:
typeNameHerarchy = typeToDataType(nns->getAsType())->getTypeNameHierarchy();
break;
case clang::NestedNameSpecifier::Global:
// no context name hierarchy needed.
break;
case clang::NestedNameSpecifier::Super:
typeNameHerarchy = getDeclNameHierarchy(nns->getAsRecordDecl());
break;
}
typeNameHerarchy.push(std::make_shared<NameElement>(dependentNameType->getIdentifier()->getName().str()));
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
default:
{
LOG_ERROR(std::string("Unhandled kind of type encountered: ") + type->getTypeClassName());
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 typeName = StrOS.str();
NameHierarchy typeNameHerarchy;
typeNameHerarchy.push(std::make_shared<NameElement>(typeName));
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
}
return dataType;
CxxTypeNameResolver resolver;
return resolver.qualTypeToDataType(qualType);
}
NameHierarchy getDeclNameHierarchy(const clang::Decl* declaration)
{
NameHierarchy contextNameHierarchy;
if (declaration)
{
std::string declName = "";
if (clang::isa<clang::NamedDecl>(declaration))
{
declName = getDeclName(clang::dyn_cast<const clang::NamedDecl>(declaration));
}
else
{
LOG_ERROR("unhandled declaration type: " + std::string(declaration->getDeclKindName()));
}
contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext());
if (clang::isa<clang::NonTypeTemplateParmDecl>(declaration) ||
clang::isa<clang::TemplateTypeParmDecl>(declaration) ||
clang::isa<clang::TemplateTemplateParmDecl>(declaration))
{
std::string lastContextElementName = contextNameHierarchy.back()->getFullName();
contextNameHierarchy.pop();
contextNameHierarchy.push(std::make_shared<NameElement>(lastContextElementName + "::" + declName));
}
else
{
contextNameHierarchy.push(std::make_shared<NameElement>(declName));
}
}
return contextNameHierarchy;
}
NameHierarchy getContextNameHierarchy(const clang::DeclContext* declContext)
{
NameHierarchy contextNameHierarchy;
const clang::DeclContext* parentContext = declContext->getParent();
if (parentContext)
{
contextNameHierarchy = getContextNameHierarchy(parentContext);
}
if (clang::isa<clang::NamedDecl>(declContext))
{
std::string declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declContext));
if (declName != "")
{
contextNameHierarchy.push(std::make_shared<NameElement>(declName));
}
}
return contextNameHierarchy;
}
NameHierarchy getContextNameHierarchyOfTemplateParameter(const clang::NamedDecl* templateParmDecl) // why do we need this??
{
NameHierarchy contextNameHierarchy;
const clang::Decl* parentNode = getAstParentDecl(templateParmDecl);
if (parentNode && clang::isa<clang::NamedDecl>(parentNode))
{
const clang::NamedDecl* parentNamedDecl = clang::dyn_cast<clang::NamedDecl>(parentNode);
contextNameHierarchy = getDeclNameHierarchy(parentNamedDecl);
}
return contextNameHierarchy;
}
std::string getDeclName(const clang::NamedDecl* declaration)
{
std::string declName = declaration->getNameAsString();
clang::Decl::Kind kind = declaration->getKind();
if (clang::isa<clang::CXXRecordDecl>(declaration))
{
clang::ClassTemplateDecl* templateClassDeclaration = clang::dyn_cast<clang::CXXRecordDecl>(declaration)->getDescribedClassTemplate();
if (templateClassDeclaration)
{
declName = getDeclName(templateClassDeclaration);
}
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(declaration))
{
const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl =
clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration);
clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters();
int currentParameterIndex = 0;
std::string specializedParameterNamePart = "<";
int templateArgumentCount = partialSpecializationDecl->getTemplateArgs().size();
const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs();
for (int i = 0; i < templateArgumentCount; i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentList.get(i);
if (templateArgument.isDependent()) // TODO: fix case when arg depends on template parameter of outer template class.
{
specializedParameterNamePart += getTemplateParameterString(parameterList->getParam(currentParameterIndex));
currentParameterIndex++;
}
else
{
specializedParameterNamePart += getTemplateArgumentName(templateArgument);
}
specializedParameterNamePart += (i < templateArgumentCount - 1) ? ", " : "";
}
specializedParameterNamePart += ">";
declName += specializedParameterNamePart;
}
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
{
std::string specializedParameterNamePart = "<";
const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(declaration)->getTemplateArgs();
for (size_t i = 0; i < templateArgumentList.size(); i++)
{
specializedParameterNamePart += getTemplateArgumentName(templateArgumentList.get(i));
specializedParameterNamePart += (i < templateArgumentList.size() - 1) ? ", " : "";
}
specializedParameterNamePart += ">";
declName += specializedParameterNamePart;
}
}
else if (clang::isa<clang::FunctionDecl>(declaration))
{
clang::FunctionTemplateDecl* templateFunctionDeclaration = clang::dyn_cast<clang::FunctionDecl>(declaration)->getDescribedFunctionTemplate();
if (templateFunctionDeclaration)
{
declName = getDeclName(templateFunctionDeclaration);
}
else if (clang::dyn_cast<clang::FunctionDecl>(declaration)->isFunctionTemplateSpecialization())
{
std::string specializedParameterNamePart = "<";
const clang::TemplateArgumentList* templateArgumentList = clang::dyn_cast<clang::FunctionDecl>(declaration)->getTemplateSpecializationArgs();
for (size_t i = 0; i < templateArgumentList->size(); i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentList->get(i);
specializedParameterNamePart += templateArgumentToDataType(templateArgument)->getFullTypeName();
specializedParameterNamePart += (i < templateArgumentList->size() - 1) ? ", " : "";
}
specializedParameterNamePart += ">";
declName += specializedParameterNamePart;
}
}
else if (clang::isa<clang::TemplateDecl>(declaration)) // also triggers on TemplateTemplateParmDecl
{
std::string templateParameterNamePart = "<";
clang::TemplateParameterList* parameterList = clang::dyn_cast<clang::TemplateDecl>(declaration)->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameterNamePart += getTemplateParameterString(parameterList->getParam(i));
templateParameterNamePart += (i < parameterList->size() - 1) ? ", " : "";
}
templateParameterNamePart += ">";
declName += templateParameterNamePart;
}
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());
declName = "anonymous namespace (" + std::string(presumedBegin.getFilename()) + ")";
}
return declName;
CxxDeclNameResolver resolver(declaration);
return resolver.getDeclNameHierarchy();
}
NameHierarchy getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration)
@@ -437,185 +81,4 @@ namespace utility
}
return std::make_shared<NamedDataType>(NameHierarchy());
}
std::string getTemplateParameterString(const clang::NamedDecl* parameter)
{
std::string templateParameterString = "";
clang::Decl::Kind templateParameterKind = parameter->getKind();
switch (templateParameterKind)
{
case clang::Decl::NonTypeTemplateParm:
templateParameterString = getTemplateParameterTypeString(clang::dyn_cast<clang::NonTypeTemplateParmDecl>(parameter));
break;
case clang::Decl::TemplateTypeParm:
templateParameterString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTypeParmDecl>(parameter));
break;
case clang::Decl::TemplateTemplateParm:
templateParameterString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTemplateParmDecl>(parameter));
break;
default:
LOG_ERROR("Unhandled kind of template parameter.");
}
std::string parameterName = parameter->getName();
if (!parameterName.empty())
{
templateParameterString += " " + parameterName;
}
return templateParameterString;
}
std::string getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter)
{
std::string templateParameterTypeString = "";
const clang::QualType parmeterType = parameter->getType();
clang::Type::TypeClass parmeterTypeClass = parmeterType->getTypeClass();
if (parmeterTypeClass == clang::Type::TemplateTypeParm)
{
clang::TemplateTypeParmDecl* parmeterTypeDecl = clang::dyn_cast<clang::TemplateTypeParmType>(parmeterType)->getDecl();
if (haveAstAncestorRelation(getAstParentDecl(parameter), parmeterTypeDecl))
{
templateParameterTypeString = getDeclName(parmeterTypeDecl);
}
}
else if (parmeterTypeClass == clang::Type::DependentName)
{
clang::NestedNameSpecifier* nns = clang::dyn_cast<clang::DependentNameType>(parmeterType)->getQualifier();
clang::NamedDecl* typeParent;
switch (nns->getKind())
{
case clang::NestedNameSpecifier::Identifier:
{
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"
templateParameterTypeString = parmeterType.getAsString(pp);
}
break;
case clang::NestedNameSpecifier::Namespace:
typeParent = nns->getAsNamespace();
break;
case clang::NestedNameSpecifier::NamespaceAlias:
typeParent = nns->getAsNamespaceAlias();
break;
case clang::NestedNameSpecifier::TypeSpec:
case clang::NestedNameSpecifier::TypeSpecWithTemplate:
{
const clang::Type* ssswd = nns->getAsType();
clang::Type::TypeClass szz = ssswd->getTypeClass();
switch (ssswd->getTypeClass())
{
case clang::Type::TemplateTypeParm:
typeParent = clang::dyn_cast<clang::TemplateTypeParmType>(ssswd)->getDecl();
break;
default:
typeParent = nullptr;
LOG_ERROR("aahhh");
}
}
break;
case clang::NestedNameSpecifier::Global:
typeParent = nullptr;
break;
case clang::NestedNameSpecifier::Super:
typeParent = nns->getAsRecordDecl();
break;
}
if (typeParent && haveAstAncestorRelation(getAstParentDecl(parameter), typeParent))
{
templateParameterTypeString = getDeclName(typeParent);
templateParameterTypeString += "::" + clang::dyn_cast<clang::DependentNameType>(parmeterType)->getIdentifier()->getName().str();
}
}
if (templateParameterTypeString.empty()) // this is the default case
{
templateParameterTypeString = qualTypeToDataType(parmeterType)->getFullTypeName();
}
return templateParameterTypeString;
}
std::string getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter)
{
return (parameter->wasDeclaredWithTypename() ? "typename" : "class");
}
std::string getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter)
{
std::string templateParameterTypeString = "template<";
clang::TemplateParameterList* parameterList = parameter->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameterTypeString += getTemplateParameterString(parameterList->getParam(i));
templateParameterTypeString += (i < parameterList->size() - 1) ? ", " : "";
}
templateParameterTypeString += ">";
templateParameterTypeString += " typename"; // TODO: what if template template parameter is defined with class keyword?
return templateParameterTypeString;
}
std::string getTemplateArgumentName(const clang::TemplateArgument& argument)
{
const clang::TemplateArgument::ArgKind kind = argument.getKind();
switch (kind)
{
case clang::TemplateArgument::Type:
return utility::qualTypeToDataType(argument.getAsType())->getFullTypeName();
case clang::TemplateArgument::Integral:
case clang::TemplateArgument::Null:
case clang::TemplateArgument::Declaration:
case clang::TemplateArgument::NullPtr:
case clang::TemplateArgument::Template:
case clang::TemplateArgument::TemplateExpansion:
case clang::TemplateArgument::Expression:
{
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"
std::string buf;
llvm::raw_string_ostream os(buf);
argument.print(pp, os);
return os.str();
}
case clang::TemplateArgument::Pack:
LOG_ERROR("Type of template argument not handled: Pack");
break;
default:
LOG_ERROR("Type of template argument not handled." + argument.getKind());
break;
}
return std::string();
}
bool haveAstAncestorRelation(const clang::Decl* parent, const clang::Decl* child)
{
if (parent)
{
while (child)
{
if (parent == child)
{
return true;
}
child = getAstParentDecl(child);
}
}
return false;
}
const clang::Decl* getAstParentDecl(const clang::Decl* decl)
{
clang::ASTContext& astContext = decl->getASTContext();
llvm::ArrayRef<clang::ast_type_traits::DynTypedNode> parents = astContext.getParents<clang::Decl>(*(decl));
if (parents.size() > 0) // usually this list contains just one parent node.
{
return parents[0].get<clang::Decl>(); // use the fist parent node.
}
return nullptr;
}
}
+1 -13
View File
@@ -15,22 +15,10 @@ class NameHierarchy;
namespace utility
{
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType);
std::shared_ptr<DataType> typeToDataType(const clang::Type* type);
NameHierarchy getDeclNameHierarchy(const clang::Decl* declaration);
NameHierarchy getContextNameHierarchy(const clang::DeclContext* declaration);
NameHierarchy getContextNameHierarchyOfTemplateParameter(const clang::NamedDecl* templateParmDecl);
std::string getDeclName(const clang::NamedDecl* declaration);
NameHierarchy getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration);
std::shared_ptr<DataType> templateArgumentToDataType(const clang::TemplateArgument& argument);
std::string getTemplateParameterString(const clang::NamedDecl* parameter);
std::string getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter);
std::string getTemplateArgumentName(const clang::TemplateArgument& argument);
bool haveAstAncestorRelation(const clang::Decl* parent, const clang::Decl* child);
const clang::Decl* getAstParentDecl(const clang::Decl* decl);
NameHierarchy getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration);
}
#endif // UTILITY_CLANG_H
+101 -67
View File
@@ -1295,6 +1295,32 @@ public:
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<std::nullptr_t T>::T <2:26 2:26>");
}
void test_cxx_parser_finds_non_type_template_parameter_that_depends_on_type_template_parameter_of_template_class()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T1, T1& T2>\n"
"class A\n"
"{};\n"
);
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 2);
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<typename T1, T1 & T2>::T1 <1:20 1:21>");
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A<typename T1, T1 & T2>::T2 <1:28 1:29>");
}
void test_cxx_parser_finds_non_type_template_parameter_that_depends_on_template_template_parameter_of_template_class()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <template<typename> class T1, T1<int>& T2>\n"
"class A\n"
"{};\n"
);
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 2);
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<template<typename> typename T1, T1<int> & T2>::T1<typename> <1:36 1:37>");
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A<template<typename> typename T1, T1<int> & T2>::T2 <1:49 1:50>");
}
void test_cxx_parser_finds_template_template_parameter_of_template_class()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -1354,19 +1380,7 @@ public:
TS_ASSERT_EQUALS(client->typeUses[1], "B<template<typename> typename T>::T<B<template<typename> typename T>::foo<typename U>::U> <8:11 8:14>");
}
void test_cxx_parser_finds_usage_of_template_template_parameter_of_template_class_specialized_with_template_type00000000000666666666666()
void test_cxx_parser_finds_typedef_in_other_class_that_depends_on_own_template_parameter()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
@@ -1390,41 +1404,6 @@ public:
TS_ASSERT_EQUALS(client->typedefs[1], "public A<B<typename U>::U>::type -> B<typename U>::type <9:37 9:40>");
}
void test_cxx_parser_finds_usage_of_template_template_parameter_of_template_class_specialized_with_template_type00ss000666666666666()
{
int zz1 = 0;
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T, T test>\n"
"class A\n"
"{\n"
"};\n"
);
int zz2 = 0;
TS_ASSERT_EQUALS(client->classes.size(), 1);
TS_ASSERT_EQUALS(client->classes[0], "A<typename T, T test> <2:1 <2:7 2:7> 4:1>");
}
void test_cxx_parser_finds_usage_of_template_template_parameter_of_template_class_specialized_with_template_type00sstt000666666666666()
{
int zz1 = 0;
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T, typename T::type test>\n"
"class A\n"
"{\n"
"};\n"
);
int zz2 = 0;
}
void test_cxx_parser_finds_type_template_parameters_of_template_class_with_multiple_parameters()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -1878,6 +1857,45 @@ public:
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "B<A, template<typename> typename U>->B<A, template<typename> typename U>::U<typename> <8:12 8:12>");
}
void test_cxx_parser_finds_non_type_template_argument_that_depends_on_type_template_parameter_of_explicit_partial_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <int T1, typename T2, T2 T3>\n"
"class A\n"
"{\n"
"};\n"
"template <typename T2, T2 T3>\n"
"class A<3, T2, T3>\n"
"{\n"
"};\n"
);
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 3);
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, typename T2, T2 T3>->int <6:9 6:9>");
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, typename T2, T2 T3>->A<3, typename T2, T2 T3>::T2 <6:12 6:12>");
TS_ASSERT_EQUALS(client->templateArgumentTypes[2], "A<3, typename T2, T2 T3>->A<3, typename T2, T2 T3>::T2 <6:16 6:16>");
}
void test_cxx_parser_finds_non_type_template_argument_that_depends_on_template_template_parameter_of_explicit_partial_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <int T1, template<typename> class T2, T2<int> T3>\n"
"class A\n"
"{\n"
"};\n"
"template <template<typename> class T2, T2<int> T3>\n"
"class A<3, T2, T3>\n"
"{\n"
"};\n"
);
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 3);
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, template<typename> typename T2, T2<int> T3>->int <6:9 6:9>");
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, template<typename> typename T2, T2<int> T3>->A<3, template<typename> typename T2, T2<int> T3>::T2<typename> <6:12 6:12>");
TS_ASSERT_EQUALS(client->templateArgumentTypes[2], "A<3, template<typename> typename T2, T2<int> T3>->A<3, template<typename> typename T2, T2<int> T3>::T2<int> <6:16 6:16>");
}
void test_cxx_parser_finds_correct_name_of_explicit_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -1957,25 +1975,24 @@ public:
TS_ASSERT_EQUALS(client->inheritances[0], "B : public A<int> <7:10 7:22>");
}
//___void test_cxx_parser_finds_template_class_specialization_with_template_argument()
//{
// std::shared_ptr<TestParserClient> client = parseCode(
// "template <typename T>\n"
// "class A\n"
// "{\n"
// " T foo;\n"
// "};\n"
// "\n"
// "template <typename U>\n"
// "class B: public A<U>\n"
// "{\n"
// "};\n"
// "B<int> bar;"
// );
// int i = 0;
// //TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
// //TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<U> -> A<T> <2:7 2:7>");
//}
void test_cxx_parser_finds_template_class_specialization_with_template_argument()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
"class A\n"
"{\n"
" T foo;\n"
"};\n"
"\n"
"template <typename U>\n"
"class B: public A<U>\n"
"{\n"
"};\n"
);
TS_ASSERT_EQUALS(client->inheritances.size(), 1);
TS_ASSERT_EQUALS(client->inheritances[0], "B<typename U> : public A<B<typename U>::U> <8:10 8:20>");
}
void test_cxx_parser_finds_template_class_constructor_usage_of_field()
{
@@ -2420,6 +2437,23 @@ public:
TS_ASSERT_EQUALS(client->errors[0], "use of undeclared identifier \'b\' <1:9 1:9>");
}
void ___test_TEST()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <template<template<typename> class> class T>\n"
"class A {\n"
"T<>\n"
"};\n"
"template <template<typename> class T>\n"
"class B {};\n"
"template <typename T>\n"
"class C {};\n"
"A<B> a;\n"
);
int ofo = 0;
}
private:
class TestParserClient: public ParserClient
{