diff options
author | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2015-04-24 09:55:20 +0300 |
---|---|---|
committer | Orgad Shaneh <orgads@gmail.com> | 2015-05-15 14:21:45 +0000 |
commit | 9b30795c02ac659606304f1a101279cd66af5c07 (patch) | |
tree | 67a9d988af34cb2f3701302d89a330a07350e12c | |
parent | ee37f60bffb14fc20abe63b812dc3b8f20974fe1 (diff) | |
download | qt-creator-9b30795c02ac659606304f1a101279cd66af5c07.tar.gz |
C++: Fix lookup for instantiation by class object
Task-number: QTCREATORBUG-14352
Change-Id: I2ce4bc1d0dba2414afe050e80607b581686081a9
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
-rw-r--r-- | src/libs/cplusplus/LookupContext.cpp | 13 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 96 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.h | 4 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppfollowsymbolundercursor.cpp | 1 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp | 4 | ||||
-rw-r--r-- | src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp | 2 | ||||
-rw-r--r-- | src/plugins/cpptools/cppcompletion_test.cpp | 23 | ||||
-rw-r--r-- | src/plugins/cpptools/symbolfinder.cpp | 12 | ||||
-rw-r--r-- | src/plugins/cpptools/symbolfinder.h | 3 | ||||
-rw-r--r-- | tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp | 22 |
10 files changed, 99 insertions, 81 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 387d1ec3e7..1c9be7bb1e 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -601,7 +601,7 @@ public: QSet<const Declaration *> _alreadyConsideredTypedefs; Class *_rootClass; - const Name *_name; // For debug + const Name *_name; bool _hasTypedefs; }; @@ -1118,6 +1118,13 @@ LookupScope *LookupScopePrivate::lookupType_helper( return r; } } + + if (_instantiationOrigin) { + if (LookupScope *o = _instantiationOrigin->lookupType_helper( + name, processed, /*searchInEnclosingScope =*/ true, origin)) { + return o; + } + } } if (_parent && searchInEnclosingScope) @@ -1529,6 +1536,10 @@ void Instantiator::instantiate(LookupScopePrivate *lookupScope, if (!clone->enclosingScope()) // Not from the cache but just cloned. clone->setEnclosingScope(s->enclosingScope()); instantiation->_symbols.append(clone); + if (s == instantiation->_rootClass) { + clone->setName(instantiation->_name); + instantiation->_rootClass = clone->asClass(); + } if (Q_UNLIKELY(debug)) { Overview oo; oo.showFunctionSignatures = true; diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 5b5190aba0..c32dacbb1c 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -915,61 +915,47 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu if (accessOp == T_ARROW) { if (PointerType *ptrTy = ty->asPointerType()) { FullySpecifiedType type = ptrTy->elementType(); - if (LookupScope *binding - = findClassForTemplateParameterInExpressionScope(r.binding(), - type)) { - return binding; - } if (LookupScope *binding = findClass(type, scope)) return binding; - } else { - LookupScope *binding - = findClassForTemplateParameterInExpressionScope(r.binding(), - ty); + } else if (LookupScope *binding = findClass(ty, scope, r.binding())) { + // lookup for overloads of operator-> - if (! binding) - binding = findClass(ty, scope, r.binding()); - - if (binding){ - // lookup for overloads of operator-> + const OperatorNameId *arrowOp + = control()->operatorNameId(OperatorNameId::ArrowOp); + foreach (const LookupItem &r, binding->find(arrowOp)) { + Symbol *overload = r.declaration(); + if (! overload) + continue; + Scope *functionScope = overload->enclosingScope(); - const OperatorNameId *arrowOp - = control()->operatorNameId(OperatorNameId::ArrowOp); - foreach (const LookupItem &r, binding->find(arrowOp)) { - Symbol *overload = r.declaration(); - if (! overload) - continue; - Scope *functionScope = overload->enclosingScope(); + if (Function *funTy = overload->type()->asFunctionType()) { + FullySpecifiedType retTy = funTy->returnType().simplified(); - if (Function *funTy = overload->type()->asFunctionType()) { - FullySpecifiedType retTy = funTy->returnType().simplified(); + typeResolver.resolve(&retTy, &functionScope, r.binding()); - typeResolver.resolve(&retTy, &functionScope, r.binding()); + if (! retTy->isPointerType() && ! retTy->isNamedType()) + continue; - if (! retTy->isPointerType() && ! retTy->isNamedType()) - continue; + if (PointerType *ptrTy = retTy->asPointerType()) + retTy = ptrTy->elementType(); - if (PointerType *ptrTy = retTy->asPointerType()) - retTy = ptrTy->elementType(); + if (LookupScope *retBinding = findClass(retTy, functionScope)) + return retBinding; - if (LookupScope *retBinding = findClass(retTy, functionScope)) + if (scope != functionScope) { + if (LookupScope *retBinding = findClass(retTy, scope)) return retBinding; + } - if (scope != functionScope) { - if (LookupScope *retBinding = findClass(retTy, scope)) - return retBinding; - } - - if (LookupScope *origin = binding->instantiationOrigin()) { - foreach (Symbol *originSymbol, origin->symbols()) { - Scope *originScope = originSymbol->asScope(); - if (originScope && originScope != scope - && originScope != functionScope) { - if (LookupScope *retBinding - = findClass(retTy, originScope)) - return retBinding; - } + if (LookupScope *origin = binding->instantiationOrigin()) { + foreach (Symbol *originSymbol, origin->symbols()) { + Scope *originScope = originSymbol->asScope(); + if (originScope && originScope != scope + && originScope != functionScope) { + if (LookupScope *retBinding + = findClass(retTy, originScope)) + return retBinding; } } } @@ -983,12 +969,6 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu ty = ptrTy->elementType(); } - if (LookupScope *binding - = findClassForTemplateParameterInExpressionScope(r.binding(), - ty)) { - return binding; - } - LookupScope *enclosingBinding = 0; if (LookupScope *binding = r.binding()) { if (binding->instantiationOrigin()) @@ -1003,24 +983,6 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu return 0; } -LookupScope *ResolveExpression::findClassForTemplateParameterInExpressionScope( - LookupScope *resultBinding, - const FullySpecifiedType &ty) const -{ - if (resultBinding) { - if (LookupScope *origin = resultBinding->instantiationOrigin()) { - foreach (Symbol *originSymbol, origin->symbols()) { - if (Scope *originScope = originSymbol->asScope()) { - if (LookupScope *retBinding = findClass(ty, originScope)) - return retBinding; - } - } - } - } - - return 0; -} - bool ResolveExpression::visit(PostIncrDecrAST *ast) { const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope); diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index df73ad5ef7..df9ea22020 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -125,10 +125,6 @@ protected: private: - LookupScope *findClassForTemplateParameterInExpressionScope( - LookupScope *resultBinding, - const FullySpecifiedType &ty) const; - Scope *_scope; const LookupContext& _context; Bind bind; diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp index 4d03ac941e..a166e8d641 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp @@ -38,6 +38,7 @@ #include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/ResolveExpression.h> #include <cplusplus/SimpleLexer.h> +#include <cplusplus/Templates.h> #include <cplusplus/TypeOfExpression.h> #include <cpptools/cppmodelmanager.h> #include <cpptools/functionutils.h> diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp index 97db446ac8..3a3b20aeda 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp @@ -152,8 +152,8 @@ public: QTC_ASSERT(m_params.staticClass, return 0); QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0); - Class *functionsClass = m_finder.findMatchingClassDeclaration(m_params.function, - m_params.snapshot); + Class *functionsClass = m_finder.findMatchingClassDeclaration( + m_params.function, m_params.snapshot, &m_params.typeOfExpression->context()); if (!functionsClass) return 0; diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 5d99cff58c..406887e1a7 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -1371,7 +1371,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_data() "template <class T> struct A { virtual void virt() {} };\n" "void f(A<int> *l) { l->$@virt(); }\n") << (OverrideItemList() - << OverrideItem(QLatin1String("A::virt"), 1)); + << OverrideItem(QLatin1String("A<int>::virt"), 1)); /// Check: Static type is nicely resolved, especially for QSharedPointers. QTest::newRow("QSharedPointer") << _( diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 5e9d09a384..8bceee424d 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -332,7 +332,6 @@ void CppToolsPlugin::test_completion() QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "QTCREATORBUG-13757", Abort); QEXPECT_FAIL("enum_in_class_accessed_in_member_func_cxx11", "QTCREATORBUG-13757", Abort); QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_cxx11", "QTCREATORBUG-13757", Abort); - QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort); QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort); QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort); QCOMPARE(actualCompletions, expectedCompletions); @@ -2830,6 +2829,28 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("Foo") << QLatin1String("bar")); + QTest::newRow("instantiation_of_indirect_typedef") << _( + "template<typename _Tp>\n" + "struct Indirect { _Tp t; };\n" + "\n" + "template<typename T>\n" + "struct Temp\n" + "{\n" + " typedef T MyT;\n" + " typedef Indirect<MyT> indirect;\n" + "};\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " Temp<Foo>::indirect i;\n" + " @\n" + "}\n" + ) << _("i.t.") << (QStringList() + << QLatin1String("Foo") + << QLatin1String("bar"));; + QTest::newRow("pointer_indirect_specialization_double_indirection_with_base") << _( "template<typename _Tp>\n" "struct Traits { };\n" diff --git a/src/plugins/cpptools/symbolfinder.cpp b/src/plugins/cpptools/symbolfinder.cpp index 52bad5ab25..26df91bc04 100644 --- a/src/plugins/cpptools/symbolfinder.cpp +++ b/src/plugins/cpptools/symbolfinder.cpp @@ -212,13 +212,15 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration, return 0; } -Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot) +Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot, + const LookupContext *context) { if (!declaration->identifier()) return 0; QString declFile = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength()); + const bool useLocalContext = !context; foreach (const QString &file, fileIterationOrder(declFile, snapshot)) { Document::Ptr doc = snapshot.document(file); if (!doc) { @@ -230,9 +232,13 @@ Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Sna declaration->identifier()->size())) continue; - LookupContext context(doc, snapshot); + QScopedPointer<LookupContext> localContext; + if (useLocalContext) { + localContext.reset(new LookupContext(doc, snapshot)); + context = localContext.data(); + } - LookupScope *type = context.lookupType(declaration); + LookupScope *type = context->lookupType(declaration); if (!type) continue; diff --git a/src/plugins/cpptools/symbolfinder.h b/src/plugins/cpptools/symbolfinder.h index e9c301aaf2..a71d9ed4d2 100644 --- a/src/plugins/cpptools/symbolfinder.h +++ b/src/plugins/cpptools/symbolfinder.h @@ -59,7 +59,8 @@ public: bool strict = false); CPlusPlus::Class *findMatchingClassDeclaration(CPlusPlus::Symbol *declaration, - const CPlusPlus::Snapshot &snapshot); + const CPlusPlus::Snapshot &snapshot, + const CPlusPlus::LookupContext *context = 0); void findMatchingDeclaration(const CPlusPlus::LookupContext &context, CPlusPlus::Function *functionType, diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp index eb88edfb9f..c584dab0fd 100644 --- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp +++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp @@ -118,6 +118,7 @@ public: // Processs source const Document::Ptr document = createDocument(filePath, source); + QVERIFY(document); Snapshot snapshot; snapshot.insert(document); @@ -1202,7 +1203,6 @@ void tst_CheckSymbols::findField() source[position] = ' '; BaseTestCase tc(source); Use use = tc.findUse(line, column); - QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort); QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort); QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort); QVERIFY(use.isValid()); @@ -1281,6 +1281,26 @@ void tst_CheckSymbols::findField_data() "}\n" ); + QTest::newRow("instantiation_of_indirect_typedef") << _( + "template<typename _Tp>\n" + "struct Indirect { _Tp t; };\n" + "\n" + "template<typename T>\n" + "struct Temp\n" + "{\n" + " typedef T MyT;\n" + " typedef Indirect<MyT> indirect;\n" + "};\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " Temp<Foo>::indirect i;\n" + " i.t.@bar;\n" + "}\n" + ); + QTest::newRow("pointer_indirect_specialization_double_indirection") << _( "template<typename _Tp>\n" "struct Traits { };\n" |