Commit 783ec184 authored by Przemyslaw Gorszkowski's avatar Przemyslaw Gorszkowski Committed by Erik Verbruggen

C++: instantiate template functions

Task-number: QTCREATORBUG-9170

Change-Id: I4cac9124558c1d4f0722192246f3fbeea61d3d7d
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent bddaab24
......@@ -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);
}
......@@ -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;
......
......@@ -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);
}
}
}
}
......
......@@ -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")));
}
......@@ -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();
......
......@@ -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 =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment