summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/cplusplus/LookupContext.cpp36
-rw-r--r--src/libs/cplusplus/LookupContext.h3
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp8
-rw-r--r--src/plugins/cpptools/cppcompletion_test.cpp29
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.h1
-rw-r--r--tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp1
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 =