logic: fixed infinite recursion while solving c++ template parameter names (issue #553)
This commit is contained in:
@@ -37,6 +37,8 @@ add_files(
|
|||||||
data/parser/cxx/name_resolver/CxxSpecifierNameResolver.h
|
data/parser/cxx/name_resolver/CxxSpecifierNameResolver.h
|
||||||
data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp
|
data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp
|
||||||
data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h
|
data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h
|
||||||
|
data/parser/cxx/name_resolver/CxxTemplateParameterStringResolver.cpp
|
||||||
|
data/parser/cxx/name_resolver/CxxTemplateParameterStringResolver.h
|
||||||
data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp
|
data/parser/cxx/name_resolver/CxxTypeNameResolver.cpp
|
||||||
data/parser/cxx/name_resolver/CxxTypeNameResolver.h
|
data/parser/cxx/name_resolver/CxxTypeNameResolver.h
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "data/parser/cxx/name/CxxStaticFunctionDeclName.h"
|
#include "data/parser/cxx/name/CxxStaticFunctionDeclName.h"
|
||||||
#include "data/parser/cxx/name_resolver/CxxSpecifierNameResolver.h"
|
#include "data/parser/cxx/name_resolver/CxxSpecifierNameResolver.h"
|
||||||
#include "data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h"
|
#include "data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.h"
|
||||||
|
#include "data/parser/cxx/name_resolver/CxxTemplateParameterStringResolver.h"
|
||||||
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
|
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
|
||||||
#include "data/parser/cxx/CanonicalFilePathCache.h"
|
#include "data/parser/cxx/CanonicalFilePathCache.h"
|
||||||
#include "data/parser/cxx/utilityClang.h"
|
#include "data/parser/cxx/utilityClang.h"
|
||||||
@@ -29,10 +30,6 @@ CxxDeclNameResolver::CxxDeclNameResolver(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CxxDeclNameResolver::~CxxDeclNameResolver()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getName(const clang::NamedDecl* declaration)
|
std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getName(const clang::NamedDecl* declaration)
|
||||||
{
|
{
|
||||||
declaration = utility::getFirstDecl(declaration);
|
declaration = utility::getFirstDecl(declaration);
|
||||||
@@ -480,89 +477,18 @@ std::vector<std::wstring> CxxDeclNameResolver::getTemplateParameterStrings(const
|
|||||||
|
|
||||||
std::wstring CxxDeclNameResolver::getTemplateParameterString(const clang::NamedDecl* parameter)
|
std::wstring CxxDeclNameResolver::getTemplateParameterString(const clang::NamedDecl* parameter)
|
||||||
{
|
{
|
||||||
std::wstring templateParameterTypeString;
|
CxxTemplateParameterStringResolver parameterStringResolver(getCanonicalFilePathCache(), getIgnoredContextDecls());
|
||||||
|
if (clang::isa<clang::TemplateDecl>(m_currentDecl) && clang::dyn_cast<clang::TemplateDecl>(m_currentDecl)->getTemplatedDecl())
|
||||||
if (parameter)
|
|
||||||
{
|
{
|
||||||
const clang::Decl::Kind templateParameterKind = parameter->getKind();
|
parameterStringResolver.ignoreContextDecl(clang::dyn_cast<clang::TemplateDecl>(m_currentDecl)->getTemplatedDecl());
|
||||||
switch (templateParameterKind)
|
|
||||||
{
|
|
||||||
case clang::Decl::NonTypeTemplateParm:
|
|
||||||
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::NonTypeTemplateParmDecl>(parameter));
|
|
||||||
break;
|
|
||||||
case clang::Decl::TemplateTypeParm:
|
|
||||||
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTypeParmDecl>(parameter));
|
|
||||||
break;
|
|
||||||
case clang::Decl::TemplateTemplateParm:
|
|
||||||
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTemplateParmDecl>(parameter));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// LOG_ERROR("Unhandled kind of template parameter.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring parameterName = utility::decodeFromUtf8(parameter->getName());
|
|
||||||
if (!parameterName.empty())
|
|
||||||
{
|
|
||||||
templateParameterTypeString += L" " + parameterName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return templateParameterTypeString;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring CxxDeclNameResolver::getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter)
|
|
||||||
{
|
|
||||||
CxxTypeNameResolver typeNameResolver(getCanonicalFilePathCache(), getIgnoredContextDecls());
|
|
||||||
|
|
||||||
if (clang::isa<clang::TemplateDecl>(m_currentDecl))
|
|
||||||
{
|
|
||||||
typeNameResolver.ignoreContextDecl(clang::dyn_cast<clang::TemplateDecl>(m_currentDecl)->getTemplatedDecl());
|
|
||||||
}
|
}
|
||||||
else // works for partial template specializations
|
else // works for partial template specializations
|
||||||
{
|
{
|
||||||
typeNameResolver.ignoreContextDecl(m_currentDecl);
|
parameterStringResolver.ignoreContextDecl(m_currentDecl);
|
||||||
}
|
}
|
||||||
|
parameterStringResolver.ignoreContextDecl(parameter);
|
||||||
|
|
||||||
std::wstring typeString;
|
return parameterStringResolver.getTemplateParameterString(parameter);
|
||||||
|
|
||||||
std::shared_ptr<CxxTypeName> typeName = CxxTypeName::makeUnsolvedIfNull(typeNameResolver.getName(parameter->getType()));
|
|
||||||
typeString = typeName->toString();
|
|
||||||
|
|
||||||
if (parameter->isTemplateParameterPack())
|
|
||||||
{
|
|
||||||
typeString += L"...";
|
|
||||||
}
|
|
||||||
return typeString;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring CxxDeclNameResolver::getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter)
|
|
||||||
{
|
|
||||||
std::wstring typeString = (parameter->wasDeclaredWithTypename() ? L"typename" : L"class");
|
|
||||||
if (parameter->isTemplateParameterPack())
|
|
||||||
{
|
|
||||||
typeString += L"...";
|
|
||||||
}
|
|
||||||
return typeString;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring CxxDeclNameResolver::getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter)
|
|
||||||
{
|
|
||||||
std::wstring templateParameterTypeString = L"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) ? L", " : L"";
|
|
||||||
}
|
|
||||||
templateParameterTypeString += L">";
|
|
||||||
templateParameterTypeString += L" typename"; // TODO: what if template template parameter is defined with class keyword?
|
|
||||||
|
|
||||||
if (parameter->isTemplateParameterPack())
|
|
||||||
{
|
|
||||||
templateParameterTypeString += L"...";
|
|
||||||
}
|
|
||||||
|
|
||||||
return templateParameterTypeString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring CxxDeclNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument)
|
std::wstring CxxDeclNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument)
|
||||||
@@ -570,3 +496,5 @@ std::wstring CxxDeclNameResolver::getTemplateArgumentName(const clang::TemplateA
|
|||||||
CxxTemplateArgumentNameResolver resolver(getCanonicalFilePathCache(), getIgnoredContextDecls());
|
CxxTemplateArgumentNameResolver resolver(getCanonicalFilePathCache(), getIgnoredContextDecls());
|
||||||
return resolver.getTemplateArgumentName(argument);
|
return resolver.getTemplateArgumentName(argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ public:
|
|||||||
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
||||||
std::vector<const clang::Decl*> ignoredContextDecls
|
std::vector<const clang::Decl*> ignoredContextDecls
|
||||||
);
|
);
|
||||||
virtual ~CxxDeclNameResolver();
|
|
||||||
|
|
||||||
std::shared_ptr<CxxDeclName> getName(const clang::NamedDecl* declaration);
|
std::shared_ptr<CxxDeclName> getName(const clang::NamedDecl* declaration);
|
||||||
|
|
||||||
@@ -30,9 +29,6 @@ private:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<std::wstring> getTemplateParameterStringsOfPatrialSpecialitarion(const T* templateDecl);
|
std::vector<std::wstring> getTemplateParameterStringsOfPatrialSpecialitarion(const T* templateDecl);
|
||||||
std::wstring getTemplateParameterString(const clang::NamedDecl* parameter);
|
std::wstring getTemplateParameterString(const clang::NamedDecl* parameter);
|
||||||
std::wstring getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter);
|
|
||||||
std::wstring getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter);
|
|
||||||
std::wstring getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter);
|
|
||||||
std::wstring getTemplateArgumentName(const clang::TemplateArgument& argument);
|
std::wstring getTemplateArgumentName(const clang::TemplateArgument& argument);
|
||||||
|
|
||||||
const clang::NamedDecl* m_currentDecl;
|
const clang::NamedDecl* m_currentDecl;
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ CxxNameResolver::CxxNameResolver(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CxxNameResolver::~CxxNameResolver()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CxxNameResolver::ignoreContextDecl(const clang::Decl* decl)
|
void CxxNameResolver::ignoreContextDecl(const clang::Decl* decl)
|
||||||
{
|
{
|
||||||
if (decl)
|
if (decl)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public:
|
|||||||
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
||||||
std::vector<const clang::Decl*> ignoredContextDecls
|
std::vector<const clang::Decl*> ignoredContextDecls
|
||||||
);
|
);
|
||||||
virtual ~CxxNameResolver();
|
virtual ~CxxNameResolver() = default;
|
||||||
|
|
||||||
void ignoreContextDecl(const clang::Decl* decl);
|
void ignoreContextDecl(const clang::Decl* decl);
|
||||||
bool ignoresContext(const clang::Decl* decl);
|
bool ignoresContext(const clang::Decl* decl);
|
||||||
|
|||||||
@@ -21,10 +21,6 @@ CxxSpecifierNameResolver::CxxSpecifierNameResolver(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CxxSpecifierNameResolver::~CxxSpecifierNameResolver()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<CxxName> CxxSpecifierNameResolver::getName(const clang::NestedNameSpecifier* nestedNameSpecifier)
|
std::shared_ptr<CxxName> CxxSpecifierNameResolver::getName(const clang::NestedNameSpecifier* nestedNameSpecifier)
|
||||||
{
|
{
|
||||||
std::shared_ptr<CxxName> name;
|
std::shared_ptr<CxxName> name;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ public:
|
|||||||
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
||||||
std::vector<const clang::Decl*> ignoredContextDecls
|
std::vector<const clang::Decl*> ignoredContextDecls
|
||||||
);
|
);
|
||||||
virtual ~CxxSpecifierNameResolver();
|
|
||||||
|
|
||||||
std::shared_ptr<CxxName> getName(const clang::NestedNameSpecifier* nestedNameSpecifier);
|
std::shared_ptr<CxxName> getName(const clang::NestedNameSpecifier* nestedNameSpecifier);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,10 +19,6 @@ CxxTemplateArgumentNameResolver::CxxTemplateArgumentNameResolver(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CxxTemplateArgumentNameResolver::~CxxTemplateArgumentNameResolver()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument)
|
std::wstring CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument)
|
||||||
{
|
{
|
||||||
// This doesn't work correctly if the template argument is dependent.
|
// This doesn't work correctly if the template argument is dependent.
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ public:
|
|||||||
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
||||||
std::vector<const clang::Decl*> ignoredContextDecls
|
std::vector<const clang::Decl*> ignoredContextDecls
|
||||||
);
|
);
|
||||||
virtual ~CxxTemplateArgumentNameResolver();
|
|
||||||
|
|
||||||
std::wstring getTemplateArgumentName(const clang::TemplateArgument& argument);
|
std::wstring getTemplateArgumentName(const clang::TemplateArgument& argument);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
#include "data/parser/cxx/name_resolver/CxxTemplateParameterStringResolver.h"
|
||||||
|
|
||||||
|
#include <clang/AST/PrettyPrinter.h>
|
||||||
|
#include <clang/AST/DeclTemplate.h>
|
||||||
|
|
||||||
|
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
|
||||||
|
#include "utility/utilityString.h"
|
||||||
|
|
||||||
|
CxxTemplateParameterStringResolver::CxxTemplateParameterStringResolver(std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache)
|
||||||
|
: CxxNameResolver(canonicalFilePathCache, std::vector<const clang::Decl*>())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CxxTemplateParameterStringResolver::CxxTemplateParameterStringResolver(
|
||||||
|
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
||||||
|
std::vector<const clang::Decl*> ignoredContextDecls
|
||||||
|
)
|
||||||
|
: CxxNameResolver(canonicalFilePathCache, ignoredContextDecls)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring CxxTemplateParameterStringResolver::getTemplateParameterString(const clang::NamedDecl* parameter)
|
||||||
|
{
|
||||||
|
std::wstring templateParameterTypeString;
|
||||||
|
|
||||||
|
if (parameter)
|
||||||
|
{
|
||||||
|
const std::wstring parameterName = utility::decodeFromUtf8(parameter->getName());
|
||||||
|
|
||||||
|
const clang::Decl::Kind templateParameterKind = parameter->getKind();
|
||||||
|
switch (templateParameterKind)
|
||||||
|
{
|
||||||
|
case clang::Decl::NonTypeTemplateParm:
|
||||||
|
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::NonTypeTemplateParmDecl>(parameter));
|
||||||
|
break;
|
||||||
|
case clang::Decl::TemplateTypeParm:
|
||||||
|
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTypeParmDecl>(parameter));
|
||||||
|
break;
|
||||||
|
case clang::Decl::TemplateTemplateParm:
|
||||||
|
templateParameterTypeString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTemplateParmDecl>(parameter));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// LOG_ERROR("Unhandled kind of template parameter.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parameterName.empty())
|
||||||
|
{
|
||||||
|
templateParameterTypeString += L" " + parameterName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return templateParameterTypeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring CxxTemplateParameterStringResolver::getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter)
|
||||||
|
{
|
||||||
|
CxxTypeNameResolver typeNameResolver(getCanonicalFilePathCache(), getIgnoredContextDecls());
|
||||||
|
std::shared_ptr<CxxTypeName> typeName = CxxTypeName::makeUnsolvedIfNull(typeNameResolver.getName(parameter->getType()));
|
||||||
|
|
||||||
|
std::wstring typeString = typeName->toString();
|
||||||
|
|
||||||
|
if (parameter->isTemplateParameterPack())
|
||||||
|
{
|
||||||
|
typeString += L"...";
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring CxxTemplateParameterStringResolver::getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter)
|
||||||
|
{
|
||||||
|
std::wstring typeString = (parameter->wasDeclaredWithTypename() ? L"typename" : L"class");
|
||||||
|
|
||||||
|
if (parameter->isTemplateParameterPack())
|
||||||
|
{
|
||||||
|
typeString += L"...";
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring CxxTemplateParameterStringResolver::getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter)
|
||||||
|
{
|
||||||
|
std::wstring templateParameterTypeString = L"template<";
|
||||||
|
clang::TemplateParameterList* parameterList = parameter->getTemplateParameters();
|
||||||
|
for (size_t i = 0; i < parameterList->size(); i++)
|
||||||
|
{
|
||||||
|
CxxTemplateParameterStringResolver parameterStringResolver(getCanonicalFilePathCache(), getIgnoredContextDecls());
|
||||||
|
parameterStringResolver.ignoreContextDecl(parameterList->getParam(i));
|
||||||
|
|
||||||
|
templateParameterTypeString += parameterStringResolver.getTemplateParameterString(parameterList->getParam(i));
|
||||||
|
templateParameterTypeString += (i < parameterList->size() - 1) ? L", " : L"";
|
||||||
|
}
|
||||||
|
templateParameterTypeString += L">";
|
||||||
|
templateParameterTypeString += L" typename"; // TODO: what if template template parameter is defined with class keyword?
|
||||||
|
|
||||||
|
if (parameter->isTemplateParameterPack())
|
||||||
|
{
|
||||||
|
templateParameterTypeString += L"...";
|
||||||
|
}
|
||||||
|
|
||||||
|
return templateParameterTypeString;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef CXX_TEMPLATE_PARAMETER_STRING_RESOLVER_H
|
||||||
|
#define CXX_TEMPLATE_PARAMETER_STRING_RESOLVER_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "data/parser/cxx/name_resolver/CxxNameResolver.h"
|
||||||
|
|
||||||
|
class DataType;
|
||||||
|
|
||||||
|
class CxxTemplateParameterStringResolver: public CxxNameResolver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CxxTemplateParameterStringResolver(std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache);
|
||||||
|
CxxTemplateParameterStringResolver(
|
||||||
|
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
||||||
|
std::vector<const clang::Decl*> ignoredContextDecls
|
||||||
|
);
|
||||||
|
|
||||||
|
std::wstring getTemplateParameterString(const clang::NamedDecl* parameter);
|
||||||
|
std::wstring getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter);
|
||||||
|
std::wstring getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter);
|
||||||
|
std::wstring getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CXX_TEMPLATE_PARAMETER_STRING_RESOLVER_H
|
||||||
@@ -23,10 +23,6 @@ CxxTypeNameResolver::CxxTypeNameResolver(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CxxTypeNameResolver::~CxxTypeNameResolver()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<CxxTypeName> CxxTypeNameResolver::getName(const clang::QualType& qualType)
|
std::shared_ptr<CxxTypeName> CxxTypeNameResolver::getName(const clang::QualType& qualType)
|
||||||
{
|
{
|
||||||
std::shared_ptr<CxxTypeName> typeName = getName(qualType.getTypePtr());
|
std::shared_ptr<CxxTypeName> typeName = getName(qualType.getTypePtr());
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ public:
|
|||||||
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache,
|
||||||
std::vector<const clang::Decl*> ignoredContextDecls
|
std::vector<const clang::Decl*> ignoredContextDecls
|
||||||
);
|
);
|
||||||
virtual ~CxxTypeNameResolver();
|
|
||||||
|
|
||||||
std::shared_ptr<CxxTypeName> getName(const clang::QualType& qualType);
|
std::shared_ptr<CxxTypeName> getName(const clang::QualType& qualType);
|
||||||
std::shared_ptr<CxxTypeName> getName(const clang::Type* type);
|
std::shared_ptr<CxxTypeName> getName(const clang::Type* type);
|
||||||
|
|||||||
@@ -860,6 +860,20 @@ public:
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_cxx_parser_finds_non_type_template_parameter_that_depends_on_type_template_parameter_of_template_template_parameter()
|
||||||
|
{
|
||||||
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
|
"template <template<typename T, T R>typename S>\n"
|
||||||
|
"class A\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
TS_ASSERT(utility::containsElement<std::wstring>(
|
||||||
|
client->templateParameterTypes, L"A<template<typename T, T R> typename S>::S<typename T, T R> <1:45 1:45>"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
void test_cxx_parser_finds_template_argument_of_dependent_non_type_template_parameter()
|
void test_cxx_parser_finds_template_argument_of_dependent_non_type_template_parameter()
|
||||||
{
|
{
|
||||||
std::shared_ptr<TestParserClient> client = parseCode(
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
|
|||||||
Reference in New Issue
Block a user