diff --git a/src/libs/cplusplus/TypeResolver.cpp b/src/libs/cplusplus/TypeResolver.cpp index dab2016b38e9802ed46bdf3690913475864a13bc..c837c0f938980fcfa6c71f43f8490c9052db14ab 100644 --- a/src/libs/cplusplus/TypeResolver.cpp +++ b/src/libs/cplusplus/TypeResolver.cpp @@ -210,6 +210,10 @@ bool TypeResolver::findTypedef(const QList<LookupItem> &namedTypeItems, FullySpe { foreach (const LookupItem &it, namedTypeItems) { Symbol *declaration = it.declaration(); + if (!declaration) + continue; + if (Template *specialization = declaration->asTemplate()) + declaration = specialization->declaration(); if (!declaration || (!declaration->isTypedef() && !declaration->type().isDecltype())) continue; if (visited.contains(declaration)) @@ -237,7 +241,7 @@ bool TypeResolver::findTypedef(const QList<LookupItem> &namedTypeItems, FullySpe return true; } } else { - *type = declaration->type(); + *type = it.type(); } *scope = it.scope(); diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 00b796f0a854f382deeeb7f095391b043cbf1477..cc98254c76000dc27f236f55aaa3ed8e5c98d076 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -2917,6 +2917,87 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("Foo") << QLatin1String("bar")); + QTest::newRow("template_using_instantiation") << _( + "template<typename _Tp>\n" + "using T = _Tp;\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " T<Foo> p;\n" + " @\n" + "}\n" + ) << _("p.") << (QStringList() + << QLatin1String("Foo") + << QLatin1String("bar")); + + QTest::newRow("nested_template_using_instantiation") << _( + "struct Parent {\n" + " template<typename _Tp>\n" + " using T = _Tp;\n" + "};\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " Parent::T<Foo> p;\n" + " @;\n" + "}\n" + ) << _("p.") << (QStringList() + << QLatin1String("Foo") + << QLatin1String("bar")); + + QTest::newRow("nested_template_using_instantiation_in_template_class") << _( + "template<typename ParentT>\n" + "struct Parent {\n" + " template<typename _Tp>\n" + " using T = _Tp;\n" + "};\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " Parent<Foo>::T<Foo> p;\n" + " @;\n" + "}\n" + ) << _("p.") << (QStringList() + << QLatin1String("Foo") + << QLatin1String("bar")); + + QTest::newRow("recursive_nested_template_using_instantiation") << _( + "struct Foo { int bar; };\n" + "\n" + "struct A { typedef Foo value_type; };\n" + "\n" + "template<typename T>\n" + "struct Traits\n" + "{\n" + " typedef Foo value_type;\n" + "\n" + " template<typename _Tp>\n" + " using U = T;\n" + "};\n" + "\n" + "template<typename T>\n" + "struct Temp\n" + "{\n" + " typedef Traits<T> TraitsT;\n" + " typedef typename T::value_type value_type;\n" + " typedef typename TraitsT::template U<Foo> rebind;\n" + "};\n" + "\n" + "void func()\n" + "{\n" + " typename Temp<typename Temp<A>::rebind>::value_type p;\n" + " @\n" + "}\n" + ) << _("p.") << (QStringList() + << QLatin1String("Foo") + << QLatin1String("bar")); + QTest::newRow("qualified_name_in_nested_type") << _( "template<typename _Tp>\n" "struct Temp {\n"