diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index e02d6e5073a..2846ea59552 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -818,6 +818,10 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope, if (Symbol *inst = instantiateTemplateFunction(name, s->asTemplate())) item.setType(inst->type()); + if (Template *templ = s->asTemplate()) + if (templ->declaration() && templ->declaration()->asClass()) + item.setType(control()->namedType(name)); + result->append(item); } } diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index a2c11b1671e..81b2066634c 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -880,12 +880,18 @@ bool ResolveExpression::visit(CallAST *ast) if (NamedType *namedTy = ty->asNamedType()) { if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) { - foreach (const LookupItem &r, b->find(functionCallOp)) { - Symbol *overload = r.declaration(); - if (Function *funTy = overload->type()->asFunctionType()) { - if (maybeValidPrototype(funTy, actualArgumentCount)) { - if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType()) - addResult(proto->returnType().simplified(), scope); + if (b->templateId() && result.declaration() && result.declaration()->asTemplate()) { + // Template class constructor + addResult(ty.simplified(), scope); + } else { + // operator() + foreach (const LookupItem &r, b->find(functionCallOp)) { + Symbol *overload = r.declaration(); + if (Function *funTy = overload->type()->asFunctionType()) { + if (maybeValidPrototype(funTy, actualArgumentCount)) { + if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType()) + addResult(proto->returnType().simplified(), scope); + } } } } diff --git a/tests/auto/cplusplus/findusages/tst_findusages.cpp b/tests/auto/cplusplus/findusages/tst_findusages.cpp index b09e2cc47fe..2dd9566021c 100644 --- a/tests/auto/cplusplus/findusages/tst_findusages.cpp +++ b/tests/auto/cplusplus/findusages/tst_findusages.cpp @@ -86,6 +86,8 @@ private Q_SLOTS: void functionNameFoundInArguments(); void memberFunctionFalsePositives_QTCREATORBUG2176(); + void resolveTemplateConstructor(); + void templateConstructorVsCallOperator(); // Qt keywords void qproperty_1(); @@ -465,6 +467,112 @@ struct Struct{ QCOMPARE(find.usages()[1].col, 22); } +void tst_FindUsages::resolveTemplateConstructor() +{ + const QByteArray src = + R"( +struct MyStruct { int value; }; +template struct Tmp { + T str; +}; +template struct Tmp2 { + Tmp2(){} + T str; +}; +template struct Tmp3 { + Tmp3(int i){} + T str; +}; +int main() { + auto tmp = Tmp(); + auto tmp2 = Tmp2(); + auto tmp3 = Tmp3(1); + tmp.str.value; + tmp2.str.value; + tmp3.str.value; + Tmp().str.value; + Tmp2().str.value; + Tmp3(1).str.value; +} +)"; + + Document::Ptr doc = Document::create("resolveTemplateConstructor"); + doc->setUtf8Source(src); + doc->parse(); + doc->check(); + + QVERIFY(doc->diagnosticMessages().isEmpty()); + QVERIFY(doc->globalSymbolCount() == 5); + + Class *s = doc->globalSymbolAt(0)->asClass(); + QVERIFY(s); + QCOMPARE(s->name()->identifier()->chars(), "MyStruct"); + QCOMPARE(s->memberCount(), 1); + + Declaration *sv = s->memberAt(0)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "value"); + + Snapshot snapshot; + snapshot.insert(doc); + + FindUsages find(src, doc, snapshot); + find(sv); + QCOMPARE(find.usages().size(), 7); +} + +void tst_FindUsages::templateConstructorVsCallOperator() +{ + const QByteArray src = + R"( +struct MyStruct { int value; }; +template struct Tmp { + T str; + MyStruct operator()() { return MyStruct(); } +}; +struct Simple { + MyStruct str; + MyStruct operator()() { return MyStruct(); } +}; +int main() +{ + Tmp().str.value; + Tmp()().value; + Tmp t; + t().value; + + Simple().str.value; + Simple()().value; + Simple s; + s().value; +} +)"; + + Document::Ptr doc = Document::create("resolveTemplateConstructor"); + doc->setUtf8Source(src); + doc->parse(); + doc->check(); + + QVERIFY(doc->diagnosticMessages().isEmpty()); + QVERIFY(doc->globalSymbolCount() == 4); + + Class *s = doc->globalSymbolAt(0)->asClass(); + QVERIFY(s); + QCOMPARE(s->name()->identifier()->chars(), "MyStruct"); + QCOMPARE(s->memberCount(), 1); + + Declaration *sv = s->memberAt(0)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "value"); + + Snapshot snapshot; + snapshot.insert(doc); + + FindUsages find(src, doc, snapshot); + find(sv); + QCOMPARE(find.usages().size(), 7); +} + #if 0 @interface Clazz {} +(void)method:(int)arg; @end @implementation Clazz +(void)method:(int)arg {