From d808ebed888891d41173876122f2178023880580 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 14 Oct 2013 15:47:07 +0200 Subject: [PATCH] CppEditor: Fix crash in CompleteSwitchCaseStatement Task-number: QTCREATORBUG-10366 Change-Id: I6d5af5e7a59f3867141c8d7f098128d3db532ee5 Reviewed-by: Erik Verbruggen --- src/libs/cplusplus/LookupContext.cpp | 4 ++ src/plugins/cppeditor/cppeditorplugin.h | 2 + src/plugins/cppeditor/cppquickfix_test.cpp | 68 ++++++++++++++++++++++ src/plugins/cppeditor/cppquickfixes.cpp | 13 ++++- 4 files changed, 84 insertions(+), 3 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 2c34d5e7ad0..09ce5d0f40e 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -864,6 +864,10 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name, return this; } } + foreach (Enum *e, unscopedEnums()) { + if (e->identifier() && e->identifier()->isEqualTo(name->identifier())) + return this; + } if (ClassOrNamespace *e = nestedType(name, origin)) return e; diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index d4c5474c64b..9dccda100e9 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -156,6 +156,8 @@ private slots: void test_quickfix_CompleteSwitchCaseStatement_basic1(); void test_quickfix_CompleteSwitchCaseStatement_basic2(); void test_quickfix_CompleteSwitchCaseStatement_oneValueMissing(); + void test_quickfix_CompleteSwitchCaseStatement_QTCREATORBUG10366_1(); + void test_quickfix_CompleteSwitchCaseStatement_QTCREATORBUG10366_2(); void test_quickfix_GenerateGetterSetter_basicGetterWithPrefix(); void test_quickfix_GenerateGetterSetter_basicGetterWithPrefixAndNamespace(); diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index b1bc78d2920..55fad435e7d 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -461,6 +461,74 @@ void CppEditorPlugin::test_quickfix_CompleteSwitchCaseStatement_oneValueMissing( data.run(&factory); } +/// Checks: Find the correct enum type despite there being a declaration with the same name. +void CppEditorPlugin::test_quickfix_CompleteSwitchCaseStatement_QTCREATORBUG10366_1() +{ + const QByteArray original = + "enum test { TEST_1, TEST_2 };\n" + "\n" + "void f() {\n" + " enum test test;\n" + " @switch (test) {\n" + " }\n" + "}\n" + ; + const QByteArray expected = + "enum test { TEST_1, TEST_2 };\n" + "\n" + "void f() {\n" + " enum test test;\n" + " switch (test) {\n" + " case TEST_1:\n" + " break;\n" + " case TEST_2:\n" + " break;\n" + " }\n" + "}\n" + "\n" + ; + + CompleteSwitchCaseStatement factory; + TestCase data(original, expected); + data.run(&factory); +} + +/// Checks: Find the correct enum type despite there being a declaration with the same name. +void CppEditorPlugin::test_quickfix_CompleteSwitchCaseStatement_QTCREATORBUG10366_2() +{ + const QByteArray original = + "enum test1 { Wrong11, Wrong12 };\n" + "enum test { Right1, Right2 };\n" + "enum test2 { Wrong21, Wrong22 };\n" + "\n" + "int main() {\n" + " enum test test;\n" + " @switch (test) {\n" + " }\n" + "}\n" + ; + const QByteArray expected = + "enum test1 { Wrong11, Wrong12 };\n" + "enum test { Right1, Right2 };\n" + "enum test2 { Wrong21, Wrong22 };\n" + "\n" + "int main() {\n" + " enum test test;\n" + " switch (test) {\n" + " case Right1:\n" + " break;\n" + " case Right2:\n" + " break;\n" + " }\n" + "}\n" + "\n" + ; + + CompleteSwitchCaseStatement factory; + TestCase data(original, expected); + data.run(&factory); +} + /// Checks: /// 1. If the name does not start with ("m_" or "_") and does not /// end with "_", we are forced to prefix the getter with "get". diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index dcdd8796863..6956cb9c784 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -2295,9 +2295,16 @@ Enum *findEnum(const QList &results, const LookupContext &ctxt) if (Enum *e = type->asEnumType()) return e; if (const NamedType *namedType = type->asNamedType()) { - const QList candidates = - ctxt.lookup(namedType->name(), result.scope()); - return findEnum(candidates, ctxt); + if (ClassOrNamespace *con = ctxt.lookupType(namedType->name(), result.scope())) { + const QList enums = con->unscopedEnums(); + const Name *referenceName = namedType->name(); + foreach (Enum *e, enums) { + if (const Name *candidateName = e->name()) { + if (candidateName->isEqualTo(referenceName)) + return e; + } + } + } } }