logic: fixed respecting the provided order of template arguments of partial template specialization

This commit is contained in:
mlangkabel
2019-10-18 13:05:28 +02:00
committed by Eberhard Graether
parent 0498d68f5b
commit 5a18d0973e
5 changed files with 110 additions and 28 deletions
@@ -2,6 +2,11 @@
#include <sstream>
std::unique_ptr<CxxTypeName> CxxTypeName::getUnsolved()
{
return std::make_unique<CxxTypeName>(L"unsolved-type");
}
std::unique_ptr<CxxTypeName> CxxTypeName::makeUnsolvedIfNull(std::unique_ptr<CxxTypeName> name)
{
if (name)
@@ -9,7 +14,7 @@ std::unique_ptr<CxxTypeName> CxxTypeName::makeUnsolvedIfNull(std::unique_ptr<Cxx
return name;
}
return std::make_unique<CxxTypeName>(L"unsolved-type");
return getUnsolved();
}
CxxTypeName::Modifier::Modifier(std::wstring symbol)
@@ -13,6 +13,7 @@ class CxxTypeName
: public CxxName
{
public:
static std::unique_ptr<CxxTypeName> getUnsolved();
static std::unique_ptr<CxxTypeName> makeUnsolvedIfNull(std::unique_ptr<CxxTypeName> name);
struct Modifier
@@ -102,6 +102,7 @@ std::unique_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
ScopedSwitcher<const clang::NamedDecl*> switcher(m_currentDecl, declaration);
std::wstring declNameString = utility::decodeFromUtf8(declaration->getNameAsString());
if (const clang::TagDecl* tagDecl = clang::dyn_cast_or_null<clang::TagDecl>(declaration))
{
if (const clang::TypedefNameDecl* typedefNameDecl = tagDecl->getTypedefNameForAnonDecl())
@@ -118,6 +119,7 @@ std::unique_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
return getDeclName(templatedDeclaration);
}
}
if (const clang::RecordDecl* recordDecl = clang::dyn_cast_or_null<clang::RecordDecl>(declaration))
{
if (recordDecl->isLambda())
@@ -37,26 +37,57 @@ std::vector<std::wstring> CxxDeclNameResolver::getTemplateParameterStringsOfPart
{
std::vector<std::wstring> templateParameterNames;
clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters();
unsigned int currentParameterIndex = 0;
const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs();
const int templateArgumentCount = templateArgumentList.size();
for (int i = 0; i < templateArgumentCount; i++)
for (int i = 0; i < templateArgumentList.size(); i++)
{
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.
if (templateArgument.isDependent())
{
if (currentParameterIndex < parameterList->size())
if (templateArgument.getKind() == clang::TemplateArgument::Type && !templateArgument.getAsType().isNull())
{
templateParameterNames.push_back(getTemplateParameterString(parameterList->getParam(currentParameterIndex)));
const clang::Type* argumentType = templateArgument.getAsType().getTypePtr();
if (const clang::TemplateTypeParmType* ttpt = clang::dyn_cast<clang::TemplateTypeParmType>(argumentType))
{
if (ttpt->getDepth() == parameterList->getDepth())
{
templateParameterNames.push_back(getTemplateParameterString(parameterList->getParam(ttpt->getIndex())));
}
else
{
// TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter.
templateParameterNames.push_back(L"arg" + std::to_wstring(ttpt->getDepth()) + L"_" + std::to_wstring(ttpt->getIndex()));
}
}
else
{
templateParameterNames.push_back(std::move(CxxTypeName::makeUnsolvedIfNull(CxxTypeNameResolver(this).getName(argumentType))->toString()));
}
}
else if (templateArgument.getKind() == clang::TemplateArgument::Template && !templateArgument.getAsTemplate().isNull())
{
const clang::TemplateTemplateParmDecl* decl = clang::dyn_cast<clang::TemplateTemplateParmDecl>(templateArgument.getAsTemplate().getAsTemplateDecl());
if (decl)
{
if (decl->getDepth() == parameterList->getDepth())
{
templateParameterNames.push_back(getTemplateParameterString(parameterList->getParam(decl->getIndex())));
}
else
{
// TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter.
templateParameterNames.push_back(L"arg" + std::to_wstring(decl->getDepth()) + L"_" + std::to_wstring(decl->getIndex()));
}
}
else
{
templateParameterNames.push_back(getTemplateArgumentName(templateArgument));
}
}
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));
templateParameterNames.push_back(getTemplateArgumentName(templateArgument));
}
currentParameterIndex++;
}
else
{
+60 -17
View File
@@ -16,22 +16,65 @@ class CxxParserTestSuite: public CxxTest::TestSuite
{
public:
//void test_foofooofooofow()
//{
// std::shared_ptr<TestIntermediateStorage> client = parseCode(
// "template <typename T1, typename T2>\n"
// "class vector { };\n"
// "template<class T>\n"
// "struct Alloc { };\n"
// "template<class T>\n"
// "using Vec = vector<T, Alloc<T>>;\n"
// "Vec<int> v;\n"
// );
void test_foofooofooofow()
{
{
std::shared_ptr<TestIntermediateStorage> client = parseCode(
"template <typename T>\n"
"class A {};\n"
"template <typename T1, typename T2>\n"
"class vector { };\n"
"template<class Foo1>\n"
"class vector<Foo1, A<Foo1>> { };\n"
);
// TS_ASSERT(utility::containsElement<std::wstring>(
// client->typeUses, L"B<A, template<typename> typename U> -> A<typename T> <8:9 8:9>"
// ));
//}
TS_ASSERT(utility::containsElement<std::wstring>(
client->classes, L"vector<class Foo1, A<typename T>> <5:1 <6:7 6:12> 6:31>"
));
}
{
std::shared_ptr<TestIntermediateStorage> client = parseCode(
"template <typename T1, typename T2, typename T3>\n"
"class vector { };\n"
"template<class Foo1, class Foo2>\n"
"class vector<Foo2, Foo1, int> { };\n"
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->classes, L"vector<class Foo2, class Foo1, int> <3:1 <4:7 4:12> 4:33>"
));
}
{
std::shared_ptr<TestIntermediateStorage> client = parseCode(
"template <typename T0>\n"
"class foo {\n"
" template <typename T1, typename T2>\n"
" class vector { };\n"
" template<class T1>\n"
" class vector<T0, T1> { };\n"
"};\n"
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->classes, L"foo<typename T0>::vector<arg0_0, class T1> <5:2 <6:8 6:13> 6:25>"
));
}
{
//std::shared_ptr<TestIntermediateStorage> client = parseCode(
// "template <typename T1, typename T2>\n"
// "class vector { };\n"
// "template<class T>\n"
// "struct Alloc { };\n"
// "template<class T>\n"
// "using Vec = vector<T, Alloc<T>>;\n" // record not Vector<vec<T>::T.........
// "Vec<int> v;\n"
//);
//TS_ASSERT(utility::containsElement<std::wstring>(
// client->typeUses, L"B<A, template<typename> typename U> -> A<typename T> <8:9 8:9>"
// ));
}
}
void test_cxx_parser_finds_usage_of_field_in_function_call_arguments()
{
@@ -3614,7 +3657,7 @@ public:
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->typeUses, L"A<&g_p, P * q> -> P g_p <8:10 8:12>" //TODO this is completely wrong? should be a normal usage
client->typeUses, L"A<&g_p, q> -> P g_p <8:10 8:12>" //TODO this is completely wrong? should be a normal usage
));
TS_ASSERT(utility::containsElement<std::wstring>(
client->localSymbols, L"input.cc<7:14> <8:15 8:15>"
@@ -3637,7 +3680,7 @@ public:
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->typeUses, L"A<&g_p, P & q> -> P g_p <8:9 8:11>"
client->typeUses, L"A<&g_p, q> -> P g_p <8:9 8:11>"
));
TS_ASSERT(utility::containsElement<std::wstring>(
client->localSymbols, L"input.cc<7:14> <8:14 8:14>"