diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp index 3aa8a59d..df38fcdf 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp @@ -84,19 +84,30 @@ std::shared_ptr CxxDeclNameResolver::getName(const clang::NamedDecl { parentDecl = utility::getFirstDecl(parentDecl); - if (const clang::TemplateDecl* parentTemplateDecl = clang::dyn_cast_or_null(parentDecl)) + if (clang::isa(parentDecl)) { + const clang::TemplateDecl* parentTemplateDecl = clang::dyn_cast_or_null(parentDecl); if (!ignoresContext(parentTemplateDecl) && !ignoresContext(parentTemplateDecl->getTemplatedDecl())) { declName->setParent(getName(parentTemplateDecl)); } break; } - else if (const clang::ClassTemplatePartialSpecializationDecl* parentTemplateDecl = clang::dyn_cast_or_null(parentDecl)) + else if (clang::isa(parentDecl)) { + const clang::ClassTemplatePartialSpecializationDecl* parentClassTemplateDecl = clang::dyn_cast_or_null(parentDecl); if (!ignoresContext(parentDecl)) { - declName->setParent(getName(parentTemplateDecl)); + declName->setParent(getName(parentClassTemplateDecl)); + } + break; + } + else if (clang::isa(parentDecl)) + { + const clang::VarTemplatePartialSpecializationDecl* parentVarTemplateDecl = clang::dyn_cast_or_null(parentDecl); + if (!ignoresContext(parentDecl)) + { + declName->setParent(getName(parentVarTemplateDecl)); } break; } @@ -199,39 +210,10 @@ std::shared_ptr CxxDeclNameResolver::getDeclName(const clang::Named } else if (clang::isa(declaration)) { - const clang::ClassTemplatePartialSpecializationDecl* partialSpecializationDecl = - clang::dyn_cast(declaration); - - clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters(); - unsigned int currentParameterIndex = 0; - - std::vector 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(declNameString, templateParameters); + const std::vector templateParameterNames = getTemplateParameterStringsOfPatrialSpecialitarion( + clang::dyn_cast(declaration) + ); + return std::make_shared(declNameString, templateParameterNames); } else if (clang::isa(declaration)) { @@ -322,10 +304,6 @@ std::shared_ptr CxxDeclNameResolver::getDeclName(const clang::Named const clang::FunctionTemplateDecl* functionTemplateDecl = clang::dyn_cast(declaration); return getDeclName(functionTemplateDecl->getTemplatedDecl()); } - else if (clang::isa(declaration)) // also triggers on TemplateTemplateParmDecl - { - return std::make_shared(declNameString, getTemplateParameterStrings(clang::dyn_cast(declaration))); - } else if (clang::isa(declaration)) { const clang::FieldDecl* fieldDecl = clang::dyn_cast(declaration); @@ -400,9 +378,39 @@ std::shared_ptr CxxDeclNameResolver::getDeclName(const clang::Named } } - return std::make_shared(varName, std::vector(), typeName, isStatic); + std::vector templateParameterNames; + if (varDecl->getDescribedVarTemplate()) + { + const clang::VarTemplateDecl* templateDeclaration = varDecl->getDescribedVarTemplate(); + templateParameterNames = getTemplateParameterStrings(templateDeclaration); + } + else if (clang::isa(declaration)) + { + templateParameterNames = getTemplateParameterStringsOfPatrialSpecialitarion(clang::dyn_cast(declaration)); + } + else if (clang::isa(declaration)) + { + const clang::VarTemplateSpecializationDecl* templateSpecializationDeclaration = clang::dyn_cast_or_null(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(varName, templateParameterNames, typeName, isStatic); } } + else if (clang::isa(declaration)) + { + const clang::VarTemplateDecl* varTemplateDecl = clang::dyn_cast(declaration); + return getDeclName(varTemplateDecl->getTemplatedDecl()); + } + else if (clang::isa(declaration)) // also triggers on TemplateTemplateParmDecl + { + return std::make_shared(declNameString, getTemplateParameterStrings(clang::dyn_cast(declaration))); + } if (!declNameString.empty()) { diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.h b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.h index bc365b65..ec43a371 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.h +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.h @@ -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 getTemplateParameterStrings(const clang::TemplateDecl* templateDecl); + template + std::vector 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 +std::vector CxxDeclNameResolver::getTemplateParameterStringsOfPatrialSpecialitarion(const T* partialSpecializationDecl) +{ + std::vector 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 diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 2738f3dd..d768bdb7 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -565,7 +565,7 @@ public: // TS_ASSERT_EQUALS(client->templateParameterTypes[0], "MyType::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 client = parseCode( "template \n" @@ -579,6 +579,51 @@ public: )); } + void test_cxx_parser_finds_type_template_parameter_of_explicit_partial_class_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + "};\n" + "template \n" + "class A\n" + "{\n" + "};\n" + ); + + TS_ASSERT(utility::containsElement( + client->templateParameterTypes, "A::T <5:20 5:20>" + )); + } + + void test_cxx_parser_finds_type_template_parameter_type_of_variable_template() + { + std::shared_ptr client = parseCode( + "template \n" + "T v;\n" + ); + + TS_ASSERT(utility::containsElement( + client->templateParameterTypes, "v::T <1:20 1:20>" + )); + } + + void test_cxx_parser_finds_type_template_parameter_of_explicit_partial_variable_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "T t = Q(5);\n" + "\n" + "template \n" + "int t = 9;\n" + ); + + TS_ASSERT(utility::containsElement( + client->templateParameterTypes, "t::R <4:20 4:20>" + )); + } + void test_cxx_parser_finds_type_template_parameter_defined_with_class_keyword() { std::shared_ptr 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 client = parseCode( "template \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 client = parseCode( + "template \n" + "T t = T(5);\n" + "\n" + "template <>\n" + "int t = 99;\n" + ); + + TS_ASSERT(utility::containsElement( + client->globalVariables, "int t <5:5 5:5>" + )); + } + + void test_cxx_parser_finds_explicit_partial_class_template_specialization() { std::shared_ptr client = parseCode( "template \n" @@ -840,6 +900,21 @@ public: )); } + void test_cxx_parser_finds_explicit_partial_variable_template_specialization() + { + std::shared_ptr client = parseCode( + "template \n" + "T t = Q(5);\n" + "\n" + "template \n" + "int t = 9;\n" + ); + + TS_ASSERT(utility::containsElement( + client->globalVariables, "int t <5:5 5:5>" + )); + } + void test_cxx_parser_finds_correct_field_member_name_of_template_class_in_declaration() { std::shared_ptr 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 client = parseCode( "template \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 client = parseCode( "template \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 client = parseCode( "template \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 client = parseCode( "template \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 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 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 client = parseCode( "template \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 client = parseCode( "template \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 client = parseCode( // "template class T2, T2 T3>\n"