logic: fixed parent node hierarchy for C++ template parameters of variable declarations

This commit is contained in:
mlangkabel
2017-11-19 20:56:42 +01:00
parent 952ea1651f
commit c512992e2c
3 changed files with 173 additions and 53 deletions
@@ -84,19 +84,30 @@ std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getName(const clang::NamedDecl
{
parentDecl = utility::getFirstDecl(parentDecl);
if (const clang::TemplateDecl* parentTemplateDecl = clang::dyn_cast_or_null<clang::TemplateDecl>(parentDecl))
if (clang::isa<clang::TemplateDecl>(parentDecl))
{
const clang::TemplateDecl* parentTemplateDecl = clang::dyn_cast_or_null<clang::TemplateDecl>(parentDecl);
if (!ignoresContext(parentTemplateDecl) && !ignoresContext(parentTemplateDecl->getTemplatedDecl()))
{
declName->setParent(getName(parentTemplateDecl));
}
break;
}
else if (const clang::ClassTemplatePartialSpecializationDecl* parentTemplateDecl = clang::dyn_cast_or_null<clang::ClassTemplatePartialSpecializationDecl>(parentDecl))
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(parentDecl))
{
const clang::ClassTemplatePartialSpecializationDecl* parentClassTemplateDecl = clang::dyn_cast_or_null<clang::ClassTemplatePartialSpecializationDecl>(parentDecl);
if (!ignoresContext(parentDecl))
{
declName->setParent(getName(parentTemplateDecl));
declName->setParent(getName(parentClassTemplateDecl));
}
break;
}
else if (clang::isa<clang::VarTemplatePartialSpecializationDecl>(parentDecl))
{
const clang::VarTemplatePartialSpecializationDecl* parentVarTemplateDecl = clang::dyn_cast_or_null<clang::VarTemplatePartialSpecializationDecl>(parentDecl);
if (!ignoresContext(parentDecl))
{
declName->setParent(getName(parentVarTemplateDecl));
}
break;
}
@@ -199,39 +210,10 @@ std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
}
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(declaration))
{
const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl =
clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration);
clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters();
unsigned int currentParameterIndex = 0;
std::vector<std::string> templateParameters;
const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs();
const int templateArgumentCount = templateArgumentList.size();
for (int i = 0; i < templateArgumentCount; i++)
{
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(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
{
templateParameters.push_back(getTemplateArgumentName(templateArgument));
}
}
return std::make_shared<CxxDeclName>(declNameString, templateParameters);
const std::vector<std::string> templateParameterNames = getTemplateParameterStringsOfPatrialSpecialitarion(
clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration)
);
return std::make_shared<CxxDeclName>(declNameString, templateParameterNames);
}
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
{
@@ -322,10 +304,6 @@ std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
const clang::FunctionTemplateDecl* functionTemplateDecl = clang::dyn_cast<clang::FunctionTemplateDecl>(declaration);
return getDeclName(functionTemplateDecl->getTemplatedDecl());
}
else if (clang::isa<clang::TemplateDecl>(declaration)) // also triggers on TemplateTemplateParmDecl
{
return std::make_shared<CxxDeclName>(declNameString, getTemplateParameterStrings(clang::dyn_cast<clang::TemplateDecl>(declaration)));
}
else if (clang::isa<clang::FieldDecl>(declaration))
{
const clang::FieldDecl* fieldDecl = clang::dyn_cast<clang::FieldDecl>(declaration);
@@ -400,9 +378,39 @@ std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
}
}
return std::make_shared<CxxVariableDeclName>(varName, std::vector<std::string>(), typeName, isStatic);
std::vector<std::string> templateParameterNames;
if (varDecl->getDescribedVarTemplate())
{
const clang::VarTemplateDecl* templateDeclaration = varDecl->getDescribedVarTemplate();
templateParameterNames = getTemplateParameterStrings(templateDeclaration);
}
else if (clang::isa<clang::VarTemplatePartialSpecializationDecl>(declaration))
{
templateParameterNames = getTemplateParameterStringsOfPatrialSpecialitarion(clang::dyn_cast<clang::VarTemplatePartialSpecializationDecl>(declaration));
}
else if (clang::isa<clang::VarTemplateSpecializationDecl>(declaration))
{
const clang::VarTemplateSpecializationDecl* templateSpecializationDeclaration = clang::dyn_cast_or_null<clang::VarTemplateSpecializationDecl>(varDecl);
const clang::TemplateArgumentList& templateArgumentList = templateSpecializationDeclaration->getTemplateArgs();
for (size_t i = 0; i < templateArgumentList.size(); i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentList.get(i);
templateParameterNames.push_back(getTemplateArgumentName(templateArgument));
}
}
return std::make_shared<CxxVariableDeclName>(varName, templateParameterNames, typeName, isStatic);
}
}
else if (clang::isa<clang::VarTemplateDecl>(declaration))
{
const clang::VarTemplateDecl* varTemplateDecl = clang::dyn_cast<clang::VarTemplateDecl>(declaration);
return getDeclName(varTemplateDecl->getTemplatedDecl());
}
else if (clang::isa<clang::TemplateDecl>(declaration)) // also triggers on TemplateTemplateParmDecl
{
return std::make_shared<CxxDeclName>(declNameString, getTemplateParameterStrings(clang::dyn_cast<clang::TemplateDecl>(declaration)));
}
if (!declNameString.empty())
{
@@ -25,6 +25,8 @@ private:
std::string getDeclarationFileName(const clang::Decl* declaration);
std::string getNameForAnonymousSymbol(const std::string& symbolKindName, const clang::Decl* declaration);
std::vector<std::string> getTemplateParameterStrings(const clang::TemplateDecl* templateDecl);
template <typename T>
std::vector<std::string> getTemplateParameterStringsOfPatrialSpecialitarion(const T* templateDecl);
std::string getTemplateParameterString(const clang::NamedDecl* parameter);
std::string getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter);
@@ -34,4 +36,39 @@ private:
const clang::NamedDecl* m_currentDecl;
};
template <typename T>
std::vector<std::string> CxxDeclNameResolver::getTemplateParameterStringsOfPatrialSpecialitarion(const T* partialSpecializationDecl)
{
std::vector<std::string> 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++)
{
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 (currentParameterIndex < parameterList->size())
{
templateParameterNames.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
{
templateParameterNames.push_back(getTemplateArgumentName(templateArgument));
}
}
return templateParameterNames;
}
#endif // CXX_DECL_NAME_RESOLVER_H
+87 -12
View File
@@ -565,7 +565,7 @@ public:
// TS_ASSERT_EQUALS(client->templateParameterTypes[0], "MyType<class T>::T <1:17 1:17>");
//}
void test_cxx_parser_finds_type_template_parameter_type_of_template_class()
void test_cxx_parser_finds_type_template_parameter_type_of_class_template()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
@@ -579,6 +579,51 @@ public:
));
}
void test_cxx_parser_finds_type_template_parameter_of_explicit_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T, typename U>\n"
"class A\n"
"{\n"
"};\n"
"template <typename T>\n"
"class A<T, int>\n"
"{\n"
"};\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->templateParameterTypes, "A<typename T, int>::T <5:20 5:20>"
));
}
void test_cxx_parser_finds_type_template_parameter_type_of_variable_template()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
"T v;\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->templateParameterTypes, "v<typename T>::T <1:20 1:20>"
));
}
void test_cxx_parser_finds_type_template_parameter_of_explicit_partial_variable_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T, typename Q>\n"
"T t = Q(5);\n"
"\n"
"template <typename R>\n"
"int t<int, R> = 9;\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->templateParameterTypes, "t<int, typename R>::R <4:20 4:20>"
));
}
void test_cxx_parser_finds_type_template_parameter_defined_with_class_keyword()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -804,7 +849,7 @@ public:
));
}
void test_cxx_parser_finds_class_of_explicit_template_specialization()
void test_cxx_parser_finds_explicit_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
@@ -822,7 +867,22 @@ public:
));
}
void test_cxx_parser_finds_class_of_explicit_partial_template_specialization()
void test_cxx_parser_finds_explicit_variable_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
"T t = T(5);\n"
"\n"
"template <>\n"
"int t<int> = 99;\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->globalVariables, "int t<int> <5:5 5:5>"
));
}
void test_cxx_parser_finds_explicit_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T, typename U>\n"
@@ -840,6 +900,21 @@ public:
));
}
void test_cxx_parser_finds_explicit_partial_variable_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T, typename Q>\n"
"T t = Q(5);\n"
"\n"
"template <typename R>\n"
"int t<int, R> = 9;\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->globalVariables, "int t<int, typename R> <5:5 5:5>"
));
}
void test_cxx_parser_finds_correct_field_member_name_of_template_class_in_declaration()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -2477,7 +2552,7 @@ public:
));
}
void test_cxx_parser_finds_usage_of_template_parameters_with_different_depth_of_partial_template_specialization()
void test_cxx_parser_finds_usage_of_template_parameters_with_different_depth_of_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
@@ -3061,7 +3136,7 @@ public:
));
}
void test_cxx_parser_finds_type_template_arguments_of_explicit_partial_template_specialization()
void test_cxx_parser_finds_type_template_arguments_of_explicit_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T, typename U>\n"
@@ -3082,7 +3157,7 @@ public:
));
}
void test_cxx_parser_finds_no_template_argument_for_builtin_non_type_int_template_parameter_of_explicit_partial_template_specialization()
void test_cxx_parser_finds_no_template_argument_for_builtin_non_type_int_template_parameter_of_explicit_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <int T, int U>\n"
@@ -3100,7 +3175,7 @@ public:
));
}
void test_cxx_parser_finds_no_template_argument_for_builtin_non_type_bool_template_parameter_of_explicit_partial_template_specialization()
void test_cxx_parser_finds_no_template_argument_for_builtin_non_type_bool_template_parameter_of_explicit_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <bool T, bool U>\n"
@@ -3118,7 +3193,7 @@ public:
));
}
void test_cxx_parser_finds_template_argument_for_non_type_custom_pointer_template_parameter_of_explicit_partial_template_specialization()
void test_cxx_parser_finds_template_argument_for_non_type_custom_pointer_template_parameter_of_explicit_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"class P\n"
@@ -3141,7 +3216,7 @@ public:
));
}
void test_cxx_parser_finds_template_argument_for_non_type_custom_reference_template_parameter_of_explicit_partial_template_specialization()
void test_cxx_parser_finds_template_argument_for_non_type_custom_reference_template_parameter_of_explicit_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"class P\n"
@@ -3164,7 +3239,7 @@ public:
));
}
void test_cxx_parser_finds_template_argument_for_template_template_parameter_of_explicit_partial_template_specialization()
void test_cxx_parser_finds_template_argument_for_template_template_parameter_of_explicit_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
@@ -3187,7 +3262,7 @@ public:
));
}
void test_cxx_parser_finds_non_type_template_argument_that_depends_on_type_template_parameter_of_explicit_partial_template_specialization()
void test_cxx_parser_finds_non_type_template_argument_that_depends_on_type_template_parameter_of_explicit_partial_class_template_specialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <int T1, typename T2, T2 T3>\n"
@@ -3205,7 +3280,7 @@ public:
));
}
//void _test_cxx_parser_finds_non_type_template_argument_that_depends_on_template_template_parameter_of_explicit_partial_template_specialization()
//void _test_cxx_parser_finds_non_type_template_argument_that_depends_on_template_template_parameter_of_explicit_partial_class_template_specialization()
//{
// std::shared_ptr<TestParserClient> client = parseCode(
// "template <int T1, template<typename> class T2, T2<int> T3>\n"