logic: fixed parent node hierarchy for C++ template parameters of variable declarations
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user