forked from qt-creator/qt-creator
C++: Fix auto variable resolving for template class constructor call
Code snippet: template<class T> struct MyStruct { int value; }; int main() { auto s = MyStruct<int>(); s.value; // "value" is not found } This fixes find usages for unique_ptr declared as auto like this: auto ptr = std::unique_ptr<MyStruct>(new MyStruct()); ptr->value; Also fixes in-place constructors: std::unique_ptr<MyStruct>(new MyStruct())->value; Fixes: QTCREATORBUG-15364 Change-Id: I8d452a77fe85e63665ec8d4c4afbcf8aad063121 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -880,6 +880,11 @@ bool ResolveExpression::visit(CallAST *ast)
|
||||
|
||||
if (NamedType *namedTy = ty->asNamedType()) {
|
||||
if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), 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()) {
|
||||
@@ -890,6 +895,7 @@ bool ResolveExpression::visit(CallAST *ast)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (Function *funTy = ty->asFunctionType()) {
|
||||
if (maybeValidPrototype(funTy, actualArgumentCount))
|
||||
|
@@ -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 <class T> struct Tmp {
|
||||
T str;
|
||||
};
|
||||
template <class T> struct Tmp2 {
|
||||
Tmp2(){}
|
||||
T str;
|
||||
};
|
||||
template <class T> struct Tmp3 {
|
||||
Tmp3(int i){}
|
||||
T str;
|
||||
};
|
||||
int main() {
|
||||
auto tmp = Tmp<MyStruct>();
|
||||
auto tmp2 = Tmp2<MyStruct>();
|
||||
auto tmp3 = Tmp3<MyStruct>(1);
|
||||
tmp.str.value;
|
||||
tmp2.str.value;
|
||||
tmp3.str.value;
|
||||
Tmp<MyStruct>().str.value;
|
||||
Tmp2<MyStruct>().str.value;
|
||||
Tmp3<MyStruct>(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<class T> struct Tmp {
|
||||
T str;
|
||||
MyStruct operator()() { return MyStruct(); }
|
||||
};
|
||||
struct Simple {
|
||||
MyStruct str;
|
||||
MyStruct operator()() { return MyStruct(); }
|
||||
};
|
||||
int main()
|
||||
{
|
||||
Tmp<MyStruct>().str.value;
|
||||
Tmp<MyStruct>()().value;
|
||||
Tmp<MyStruct> 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 {
|
||||
|
Reference in New Issue
Block a user