forked from qt-creator/qt-creator
C++: instantiate template functions
Task-number: QTCREATORBUG-9170 Change-Id: I4cac9124558c1d4f0722192246f3fbeea61d3d7d Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
committed by
Erik Verbruggen
parent
bddaab248b
commit
783ec18424
@@ -692,6 +692,16 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
|||||||
item.setType(ty); // override the type.
|
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);
|
result->append(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1603,3 +1613,29 @@ bool CreateBindings::visit(ObjCMethod *)
|
|||||||
return false;
|
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 *);
|
virtual bool visit(ObjCMethod *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Symbol *instantiateTemplateFunction(const TemplateNameId *instantiation,
|
||||||
|
Template *specialization) const;
|
||||||
|
|
||||||
Snapshot _snapshot;
|
Snapshot _snapshot;
|
||||||
QSharedPointer<Control> _control;
|
QSharedPointer<Control> _control;
|
||||||
QSet<Namespace *> _processed;
|
QSet<Namespace *> _processed;
|
||||||
|
|||||||
@@ -697,6 +697,14 @@ bool ResolveExpression::visit(CallAST *ast)
|
|||||||
// Constructor call
|
// Constructor call
|
||||||
FullySpecifiedType ctorTy = control()->namedType(classTy->name());
|
FullySpecifiedType ctorTy = control()->namedType(classTy->name());
|
||||||
addResult(ctorTy, scope);
|
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);
|
QCOMPARE(completions.size(), 1);
|
||||||
QVERIFY(completions.contains(QLatin1String("S")));
|
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();
|
||||||
void test_completion_type_and_using_declaration_data();
|
void test_completion_type_and_using_declaration_data();
|
||||||
void test_completion_instantiate_template_with_anonymous_class();
|
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();
|
||||||
void test_format_pointerdeclaration_in_simpledeclarations_data();
|
void test_format_pointerdeclaration_in_simpledeclarations_data();
|
||||||
|
|||||||
@@ -1702,7 +1702,6 @@ void tst_CheckSymbols::test_checksymbols_crashWhenUsingNamespaceClass_QTCREATORB
|
|||||||
|
|
||||||
TestData::check(source, expectedUses);
|
TestData::check(source, expectedUses);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_CheckSymbols::test_checksymbols_crashWhenUsingNamespaceClass_QTCREATORBUG9323_insideFunction()
|
void tst_CheckSymbols::test_checksymbols_crashWhenUsingNamespaceClass_QTCREATORBUG9323_insideFunction()
|
||||||
{
|
{
|
||||||
const QByteArray source =
|
const QByteArray source =
|
||||||
|
|||||||
Reference in New Issue
Block a user