From f51d7a2314fc7174f02cda2b448931fa5eb6721d Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 5 Jul 2017 12:10:17 +0200 Subject: 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 --- src/libs/cplusplus/LookupContext.cpp | 20 ++++++++++++-------- src/libs/cplusplus/LookupContext.h | 3 ++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index cb2aead5a35..0e9fccead2d 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 *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 processed; + QSet 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 A : public B {}; 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 A : public B::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 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 7273fe57d02..b13df5da29a 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -121,7 +121,8 @@ private: ClassOrNamespace *findBlock_helper(Block *block, QSet *processed, bool searchInEnclosingScope); - ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin); + ClassOrNamespace *nestedType(const Name *name, QSet *processed, + ClassOrNamespace *origin); void instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass, Clone &cloner, -- cgit v1.2.3