From 4da91bef8dc3898c155b0b2047a7254a369654d0 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 24 Sep 2014 10:18:31 +0200 Subject: [PATCH] C++: Fix endless loop in lookup on Windows ...for templates with typedefs referencing the respectively other template (basic_ostream <-> ostreambuf_iterator). Tested with MSVC 2013. Regression introduced by ba42ceb0cb7827a9bbad29a1e08d4a25339ea57d. Task-number: QTCREATORBUG-13064 Task-number: QTCREATORBUG-13065 Change-Id: I71a45c720663a73c3302eb7da731e6ad2d8f0fbd Reviewed-by: Przemyslaw Gorszkowski Reviewed-by: Fawzi Mohamed --- src/libs/cplusplus/LookupContext.cpp | 5 +- .../checksymbols/tst_checksymbols.cpp | 46 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 092e48e86de..aa916113b3b 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -92,7 +92,10 @@ static bool isNestedInstantiationEnclosingTemplate( ClassOrNamespace *nestedClassOrNamespaceInstantiation, ClassOrNamespace *enclosingTemplateClassInstantiation) { - while (enclosingTemplateClassInstantiation) { + QList processed; + while (enclosingTemplateClassInstantiation + && !processed.contains(enclosingTemplateClassInstantiation)) { + processed.append(enclosingTemplateClassInstantiation); if (enclosingTemplateClassInstantiation == nestedClassOrNamespaceInstantiation) return false; enclosingTemplateClassInstantiation = enclosingTemplateClassInstantiation->parent(); diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp index fd3ba9ddccd..b2bb282d63c 100644 --- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp +++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp @@ -191,6 +191,8 @@ private slots: void test_checksymbols_macroUses(); void test_checksymbols_macroUses_data(); + + void test_checksymbols_infiniteLoop(); }; void tst_CheckSymbols::test_checksymbols() @@ -1751,5 +1753,49 @@ void tst_CheckSymbols::test_checksymbols_macroUses_data() << Use(2, 11, 3, Highlighting::MacroUse)); } +void tst_CheckSymbols::test_checksymbols_infiniteLoop() +{ + const QByteArray source1 = + "#include \"file2.h\"\n" + "\n" + "template\n" + "class basic_ios {\n" + " typedef basic_ostream<_Elem, _Traits> _Myos;\n" + "};\n" + "\n" + "template\n" + "class basic_ostream {\n" + " typedef basic_ostream<_Elem, _Traits> _Myt;\n" + " typedef ostreambuf_iterator<_Elem, _Traits> _Iter;\n" + "};\n" + ; + const QString filePath1 = QDir::tempPath() + QLatin1String("/file1.h"); + CppTools::Tests::TestCase::writeFile(filePath1, source1); + + const QByteArray source2 = + "template\n" + "class basic_streambuf {\n" + " typedef basic_streambuf<_Elem, _Traits> _Myt;\n" + "};\n" + "\n" + "template\n" + "class ostreambuf_iterator {\n" + " typedef _Traits traits_type;\n" + " typedef basic_streambuf<_Elem, _Traits> streambuf_type;\n" + " typedef basic_ostream<_Elem, _Traits> ostream_type;\n" + "};\n" + ; + const QString filePath2 = QDir::tempPath() + QLatin1String("/file2.h"); + CppTools::Tests::TestCase::writeFile(filePath2, source2); + + const Document::Ptr document1 = TestCase::createDocument(filePath1, source1); + document1->addIncludeFile(Document::Include("file2.h", filePath2, 1, Client::IncludeLocal)); + Snapshot snapshot; + snapshot.insert(document1); + snapshot.insert(TestCase::createDocument(filePath2, source2)); + + TestCase::runCheckSymbols(document1, snapshot); +} + QTEST_APPLESS_MAIN(tst_CheckSymbols) #include "tst_checksymbols.moc"