summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2015-04-24 09:55:20 +0300
committerOrgad Shaneh <orgads@gmail.com>2015-05-15 14:21:45 +0000
commit9b30795c02ac659606304f1a101279cd66af5c07 (patch)
tree67a9d988af34cb2f3701302d89a330a07350e12c
parentee37f60bffb14fc20abe63b812dc3b8f20974fe1 (diff)
downloadqt-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.cpp13
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp96
-rw-r--r--src/libs/cplusplus/ResolveExpression.h4
-rw-r--r--src/plugins/cppeditor/cppfollowsymbolundercursor.cpp1
-rw-r--r--src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp4
-rw-r--r--src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp2
-rw-r--r--src/plugins/cpptools/cppcompletion_test.cpp23
-rw-r--r--src/plugins/cpptools/symbolfinder.cpp12
-rw-r--r--src/plugins/cpptools/symbolfinder.h3
-rw-r--r--tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp22
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"