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()))
|
if (Symbol *inst = instantiateTemplateFunction(name, s->asTemplate()))
|
||||||
item.setType(inst->type());
|
item.setType(inst->type());
|
||||||
|
|
||||||
|
if (Template *templ = s->asTemplate())
|
||||||
|
if (templ->declaration() && templ->declaration()->asClass())
|
||||||
|
item.setType(control()->namedType(name));
|
||||||
|
|
||||||
result->append(item);
|
result->append(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -880,6 +880,11 @@ bool ResolveExpression::visit(CallAST *ast)
|
|||||||
|
|
||||||
if (NamedType *namedTy = ty->asNamedType()) {
|
if (NamedType *namedTy = ty->asNamedType()) {
|
||||||
if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
|
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)) {
|
foreach (const LookupItem &r, b->find(functionCallOp)) {
|
||||||
Symbol *overload = r.declaration();
|
Symbol *overload = r.declaration();
|
||||||
if (Function *funTy = overload->type()->asFunctionType()) {
|
if (Function *funTy = overload->type()->asFunctionType()) {
|
||||||
@@ -890,6 +895,7 @@ bool ResolveExpression::visit(CallAST *ast)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (Function *funTy = ty->asFunctionType()) {
|
} else if (Function *funTy = ty->asFunctionType()) {
|
||||||
if (maybeValidPrototype(funTy, actualArgumentCount))
|
if (maybeValidPrototype(funTy, actualArgumentCount))
|
||||||
|
@@ -86,6 +86,8 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
void functionNameFoundInArguments();
|
void functionNameFoundInArguments();
|
||||||
void memberFunctionFalsePositives_QTCREATORBUG2176();
|
void memberFunctionFalsePositives_QTCREATORBUG2176();
|
||||||
|
void resolveTemplateConstructor();
|
||||||
|
void templateConstructorVsCallOperator();
|
||||||
|
|
||||||
// Qt keywords
|
// Qt keywords
|
||||||
void qproperty_1();
|
void qproperty_1();
|
||||||
@@ -465,6 +467,112 @@ struct Struct{
|
|||||||
QCOMPARE(find.usages()[1].col, 22);
|
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
|
#if 0
|
||||||
@interface Clazz {} +(void)method:(int)arg; @end
|
@interface Clazz {} +(void)method:(int)arg; @end
|
||||||
@implementation Clazz +(void)method:(int)arg {
|
@implementation Clazz +(void)method:(int)arg {
|
||||||
|
Reference in New Issue
Block a user