diff options
-rw-r--r-- | src/libs/cplusplus/LookupContext.cpp | 36 | ||||
-rw-r--r-- | src/libs/cplusplus/LookupContext.h | 3 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 8 | ||||
-rw-r--r-- | src/plugins/cpptools/cppcompletion_test.cpp | 29 | ||||
-rw-r--r-- | src/plugins/cpptools/cpptoolsplugin.h | 1 | ||||
-rw-r--r-- | tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp | 1 |
6 files changed, 77 insertions, 1 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 086c4dc7c8..fdcd0e286f 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -692,6 +692,16 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope, item.setType(ty); // override the type. } + // instantiate function template + if (name->isTemplateNameId() && s->isTemplate() && s->asTemplate()->declaration() + && s->asTemplate()->declaration()->isFunction()) { + const TemplateNameId *instantiation = name->asTemplateNameId(); + Template *specialization = s->asTemplate(); + Symbol *instantiatedFunctionTemplate = instantiateTemplateFunction(instantiation, + specialization); + item.setType(instantiatedFunctionTemplate->type()); // override the type. + } + result->append(item); } } @@ -1603,3 +1613,29 @@ bool CreateBindings::visit(ObjCMethod *) return false; } +Symbol *CreateBindings::instantiateTemplateFunction(const TemplateNameId *instantiation, + Template *specialization) const +{ + const unsigned argumentCountOfInitialization = instantiation->templateArgumentCount(); + const unsigned argumentCountOfSpecialization = specialization->templateParameterCount(); + + Clone cloner(_control.data()); + Subst subst(_control.data()); + for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) { + const TypenameArgument *tParam + = specialization->templateParameterAt(i)->asTypenameArgument(); + if (!tParam) + continue; + const Name *name = tParam->name(); + if (!name) + continue; + + FullySpecifiedType ty = (i < argumentCountOfInitialization) ? + instantiation->templateArgumentAt(i): + cloner.type(tParam->type(), &subst); + + subst.bind(cloner.name(name, &subst), ty); + } + return cloner.symbol(specialization, &subst); +} + diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index a372634053..921c605b14 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -253,6 +253,9 @@ protected: virtual bool visit(ObjCMethod *); private: + Symbol *instantiateTemplateFunction(const TemplateNameId *instantiation, + Template *specialization) const; + Snapshot _snapshot; QSharedPointer<Control> _control; QSet<Namespace *> _processed; diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 029bcee00d..81df5e2351 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -697,6 +697,14 @@ bool ResolveExpression::visit(CallAST *ast) // Constructor call FullySpecifiedType ctorTy = control()->namedType(classTy->name()); addResult(ctorTy, scope); + } else if (Template *templateTy = ty->asTemplateType()) { + // template function + if (Symbol *declaration = templateTy->declaration()) { + if (Function *funTy = declaration->asFunction()) { + if (maybeValidPrototype(funTy, actualArgumentCount)) + addResult(funTy->returnType().simplified(), scope); + } + } } } diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 385777de30..c1012f3527 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -2047,3 +2047,32 @@ void CppToolsPlugin::test_completion_instantiate_template_with_anonymous_class() QCOMPARE(completions.size(), 1); QVERIFY(completions.contains(QLatin1String("S"))); } + +void CppToolsPlugin::test_completion_instantiate_template_function() +{ + TestData data; + data.srcText = + "template <typename T>\n" + "T* templateFunction() { return 0; }\n" + "struct A { int a; };\n" + "void foo()\n" + "{\n" + " @\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("templateFunction<A>()->"); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 2); + QVERIFY(completions.contains(QLatin1String("A"))); + QVERIFY(completions.contains(QLatin1String("a"))); +} diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index d3eb847e30..a8ab4bbc29 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -127,6 +127,7 @@ private slots: void test_completion_type_and_using_declaration(); void test_completion_type_and_using_declaration_data(); void test_completion_instantiate_template_with_anonymous_class(); + void test_completion_instantiate_template_function(); void test_format_pointerdeclaration_in_simpledeclarations(); void test_format_pointerdeclaration_in_simpledeclarations_data(); diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp index 8360c25c05..7924cfbbb1 100644 --- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp +++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp @@ -1702,7 +1702,6 @@ void tst_CheckSymbols::test_checksymbols_crashWhenUsingNamespaceClass_QTCREATORB TestData::check(source, expectedUses); } - void tst_CheckSymbols::test_checksymbols_crashWhenUsingNamespaceClass_QTCREATORBUG9323_insideFunction() { const QByteArray source = |