summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@qt.io>2017-07-05 12:10:17 +0200
committerNikolai Kosjar <nikolai.kosjar@qt.io>2017-07-06 09:18:39 +0000
commitf51d7a2314fc7174f02cda2b448931fa5eb6721d (patch)
tree830c726b2d2f6b29281159fe0e00c4bbc3c125d0
parentcfb5f610a128db31b6dbf5e5e0184d9b5e6dfd39 (diff)
downloadqt-creator-f51d7a2314fc7174f02cda2b448931fa5eb6721d.tar.gz
C++: Fix crash for invalid code
...due to indirect recursion: ... CPlusPlus::ClassOrNamespace::lookupType LookupContext.cpp 833 0x7fffd6c954cc CPlusPlus::ClassOrNamespace::nestedType LookupContext.cpp 1364 0x7fffd6c94bc6 CPlusPlus::ClassOrNamespace::lookupType_helper LookupContext.cpp 955 0x7fffd6c9517f CPlusPlus::ClassOrNamespace::lookupType_helper LookupContext.cpp 983 0x7fffd6c952ad CPlusPlus::ClassOrNamespace::lookupType LookupContext.cpp 833 0x7fffd6c954cc CPlusPlus::ClassOrNamespace::nestedType LookupContext.cpp 1364 0x7fffd6c94bc6 CPlusPlus::ClassOrNamespace::lookupType_helper LookupContext.cpp 955 0x7fffd6c9517f CPlusPlus::ClassOrNamespace::lookupType_helper LookupContext.cpp 983 0x7fffd6c952ad CPlusPlus::ClassOrNamespace::lookupType LookupContext.cpp 833 0x7fffd6c954cc ... ClassOrNamespace::lookupType(const Name *) already guards with a list of entries already processed, but some calls deeper the list is not passed on and lookupType() starts again with an empty list. Handle that case, too. Task-number: QTCREATORBUG-18499 Change-Id: Iab8978f6ac1d0aea16f49b3547415f43de887b07 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
-rw-r--r--src/libs/cplusplus/LookupContext.cpp20
-rw-r--r--src/libs/cplusplus/LookupContext.h3
2 files changed, 14 insertions, 9 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index cb2aead5a3..0e9fccead2 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -952,7 +952,7 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
return this;
}
- if (ClassOrNamespace *e = nestedType(name, origin))
+ if (ClassOrNamespace *e = nestedType(name, processed, origin))
return e;
if (_templateId) {
@@ -1074,7 +1074,9 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateNestedAnonymousType(
}
}
-ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin)
+ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
+ QSet<ClassOrNamespace *> *processed,
+ ClassOrNamespace *origin)
{
Q_ASSERT(name != 0);
Q_ASSERT(name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId());
@@ -1184,11 +1186,11 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
instantiation->_name = templId;
instantiation->_templateId = templId;
- QSet<ClassOrNamespace *> processed;
+ QSet<ClassOrNamespace *> otherProcessed;
while (!origin->_symbols.isEmpty() && origin->_symbols[0]->isBlock()) {
- if (processed.contains(origin))
+ if (otherProcessed.contains(origin))
break;
- processed.insert(origin);
+ otherProcessed.insert(origin);
origin = origin->parent();
}
@@ -1310,7 +1312,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
// Another template that uses the dependent name.
// Ex.: template <class T> class A : public B<T> {};
if (baseTemplId->identifier() != templId->identifier())
- baseBinding = nestedType(baseName, origin);
+ baseBinding = nestedType(baseName, processed, origin);
} else if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) {
// Qualified names in general.
// Ex.: template <class T> class A : public B<T>::Type {};
@@ -1361,7 +1363,8 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
}
if (binding) {
- ClassOrNamespace * baseBinding = binding->lookupType(baseName);
+ ClassOrNamespace * baseBinding
+ = binding->lookupType_helper(baseName, processed, true, this);
if (baseBinding && !knownUsings.contains(baseBinding))
reference->addUsing(baseBinding);
}
@@ -1518,7 +1521,8 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNa
return findOrCreateType(q->base(), origin)->findOrCreateType(q->name(), origin, clazz);
} else if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
- ClassOrNamespace *e = nestedType(name, origin);
+ QSet<ClassOrNamespace *> processed;
+ ClassOrNamespace *e = nestedType(name, &processed, origin);
if (! e) {
e = _factory->allocClassOrNamespace(this);
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 7273fe57d0..b13df5da29 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -121,7 +121,8 @@ private:
ClassOrNamespace *findBlock_helper(Block *block, QSet<ClassOrNamespace *> *processed,
bool searchInEnclosingScope);
- ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin);
+ ClassOrNamespace *nestedType(const Name *name, QSet<ClassOrNamespace *> *processed,
+ ClassOrNamespace *origin);
void instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass,
Clone &cloner,