From 10e947f65f19ec61e29afbaf167bf3439b5bea11 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lassi=20H=C3=A4m=C3=A4l=C3=A4inen?=
 <lassi.m.hamalainen@gmail.com>
Date: Sun, 15 Nov 2015 00:16:34 +0200
Subject: [PATCH] C++: Fix crashes with the pattern "enum class operator A"

Parser parsed the pattern as an enum declaration the name of
which is a conversion operator. Add check to disallow keywords
after enum-key (enum, enum class, enum struct).
Add tests tst_AST::enumDeclaration and
invalidEnumClassDeclaration.

Task-number: QTCREATORBUG-15341
Change-Id: Ia037f00184c1d7e5b0374f39331bb6748f8d90b1
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
---
 src/libs/3rdparty/cplusplus/Parser.cpp |  5 +++++
 tests/auto/cplusplus/ast/tst_ast.cpp   | 24 ++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp
index 6fccebb0155..901f5ac2c1f 100644
--- a/src/libs/3rdparty/cplusplus/Parser.cpp
+++ b/src/libs/3rdparty/cplusplus/Parser.cpp
@@ -1789,6 +1789,11 @@ bool Parser::parseEnumSpecifier(SpecifierListAST *&node)
         if (_languageFeatures.cxx11Enabled && (LA() == T_CLASS || LA() == T_STRUCT))
             ast->key_token = consumeToken();
 
+
+        if (tok().isKeyword()) {
+            error(cursor(), "expected identifier before '%s'", tok().spell());
+            return false;
+        }
         parseName(ast->name);
 
         if (_languageFeatures.cxx11Enabled && LA() == T_COLON) {
diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp
index a2219e7cfc6..aa42b2b3ec2 100644
--- a/tests/auto/cplusplus/ast/tst_ast.cpp
+++ b/tests/auto/cplusplus/ast/tst_ast.cpp
@@ -208,6 +208,8 @@ private slots:
     void expensiveExpression();
     void invalidCode_data();
     void invalidCode();
+    void enumDeclaration();
+    void invalidEnumClassDeclaration();
 };
 
 void tst_AST::gcc_attributes_1()
@@ -1982,6 +1984,28 @@ void tst_AST::invalidCode()
     QVERIFY(diag.errorCount != 0);
 }
 
+void tst_AST::enumDeclaration()
+{
+    QSharedPointer<TranslationUnit> unit(parseStatement(
+         //Unnamed
+         "enum { ENUMERATOR0 };\n"
+         "enum Enum { ENUMERATOR1 };\n"
+         "enum EnumWithBase : int { ENUMERATOR2 };\n"
+         "enum enum : int { ENUMERATOR2a };\n"
+         "enum class EnumClass { ENUMERATOR3 = 10 };\n", true));
+
+    QVERIFY(unit->ast());
+    QCOMPARE(diag.errorCount, 0);
+}
+
+void tst_AST::invalidEnumClassDeclaration()
+{
+    QSharedPointer<TranslationUnit> unit(parseStatement(
+        "enum class operator A { };", true));
+
+    QVERIFY(diag.errorCount != 0);
+}
+
 void tst_AST::initTestCase()
 {
     control.setDiagnosticClient(&diag);
-- 
GitLab