summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@digia.com>2014-06-17 18:18:54 -0400
committerNikolai Kosjar <nikolai.kosjar@digia.com>2014-06-24 16:14:40 +0200
commit38b8940bd4531071ddc395fa7b29d5f364b53b3a (patch)
tree225306acfd38a4638c0bd1ee11bb25a3d972ed6c
parentd4c62539fdfb191ff1f24236006d6af432b01f14 (diff)
downloadqt-creator-38b8940bd4531071ddc395fa7b29d5f364b53b3a.tar.gz
C++: Fix parsing designators vs lambdas
The introduction of C99 designators led to parsing problems with lambdas that were passed in as a function arguments. Fixed by prefering to parse without designators first. This will be cleaner/clearer once the appropriate "LanguageFeatures" from the Project Parts will be passed in. Change-Id: Ia9cb7c4a4c9345e729cf2044e1e5411fe63e33ec Reviewed-by: Wang Hoi <wanghoi@126.com> Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
-rw-r--r--src/libs/3rdparty/cplusplus/Parser.cpp51
-rw-r--r--tests/auto/cplusplus/cxx11/data/lambda.1.cpp1
-rw-r--r--tests/auto/cplusplus/cxx11/tst_cxx11.cpp29
3 files changed, 65 insertions, 16 deletions
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp
index 0163046176..c09a2cabc9 100644
--- a/src/libs/3rdparty/cplusplus/Parser.cpp
+++ b/src/libs/3rdparty/cplusplus/Parser.cpp
@@ -2653,10 +2653,13 @@ bool Parser::parseBraceOrEqualInitializer0x(ExpressionAST *&node)
bool Parser::parseInitializerClause0x(ExpressionAST *&node)
{
+ DEBUG_THIS_RULE();
if (LA() == T_LBRACE)
return parseBracedInitList0x(node);
- return parseAssignmentExpression(node);
+ if (parseAssignmentExpression(node))
+ return true;
+ return parseDesignatedInitializer(node);
}
bool Parser::parseInitializerList0x(ExpressionListAST *&node)
@@ -2664,7 +2667,7 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node)
ExpressionListAST **expression_list_ptr = &node;
ExpressionAST *expression = 0;
- if (parseDesignatedInitializer(expression)) {
+ if (parseInitializerClause0x(expression)) {
*expression_list_ptr = new (_pool) ExpressionListAST;
(*expression_list_ptr)->value = expression;
expression_list_ptr = &(*expression_list_ptr)->next;
@@ -2675,7 +2678,7 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node)
while (LA() == T_COMMA && LA(2) != T_RBRACE) {
consumeToken(); // consume T_COMMA
- if (parseDesignatedInitializer(expression)) {
+ if (parseInitializerClause0x(expression)) {
*expression_list_ptr = new (_pool) ExpressionListAST;
(*expression_list_ptr)->value = expression;
@@ -2692,6 +2695,7 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node)
bool Parser::parseBracedInitList0x(ExpressionAST *&node)
{
+ DEBUG_THIS_RULE();
if (LA() != T_LBRACE)
return false;
@@ -5490,20 +5494,30 @@ bool Parser::parseDesignatedInitializer(ExpressionAST *&node)
{
DEBUG_THIS_RULE();
if (!_languageFeatures.c99Enabled || (LA() != T_DOT && LA() != T_LBRACKET))
- return parseInitializerClause0x(node);
+ return false;
DesignatedInitializerAST *ast = new (_pool) DesignatedInitializerAST;
DesignatorListAST **designator_list_ptr = &ast->designator_list;
DesignatorAST *designator = 0;
+ const unsigned start = cursor();
while (parseDesignator(designator)) {
*designator_list_ptr = new (_pool) DesignatorListAST;
(*designator_list_ptr)->value = designator;
designator_list_ptr = &(*designator_list_ptr)->next;
}
- match(T_EQUAL, &ast->equal_token);
- parseInitializerClause0x(ast->initializer);
- node = ast;
- return true;
+ if (start == cursor())
+ return false;
+
+ if (LA() == T_EQUAL) {
+ ast->equal_token = consumeToken();
+ if (parseAssignmentExpression(ast->initializer)) {
+ node = ast;
+ return true;
+ }
+ }
+
+ rewind(start);
+ return false;
}
// designator ::= T_DOT T_IDENTIFIER
@@ -5511,21 +5525,28 @@ bool Parser::parseDesignatedInitializer(ExpressionAST *&node)
//
bool Parser::parseDesignator(DesignatorAST *&node)
{
- DesignatorAST *ast = new (_pool) DesignatorAST;
+ DEBUG_THIS_RULE();
+ const unsigned start = cursor();
if (LA() == T_DOT) {
+ DesignatorAST *ast = new (_pool) DesignatorAST;
ast->type = DesignatorAST::Dot;
ast->u.dot.dot_token = consumeToken();
match(T_IDENTIFIER, &ast->u.dot.identifier_token);
+ node = ast;
+ return true;
} else if (LA() == T_LBRACKET) {
+ DesignatorAST *ast = new (_pool) DesignatorAST;
ast->type = DesignatorAST::Bracket;
ast->u.bracket.lbracket_token = consumeToken();
- parseConstantExpression(ast->u.bracket.expression);
- match(T_RBRACKET, &ast->u.bracket.rbracket_token);
- } else {
- return false;
+ if (parseConditionalExpression(ast->u.bracket.expression)) {
+ match(T_RBRACKET, &ast->u.bracket.rbracket_token);
+ node = ast;
+ return true;
+ }
}
- node = ast;
- return true;
+
+ rewind(start);
+ return false;
}
// objc-class-declaraton ::= T_AT_CLASS (T_IDENTIFIER @ T_COMMA) T_SEMICOLON
diff --git a/tests/auto/cplusplus/cxx11/data/lambda.1.cpp b/tests/auto/cplusplus/cxx11/data/lambda.1.cpp
new file mode 100644
index 0000000000..e8993dd6c9
--- /dev/null
+++ b/tests/auto/cplusplus/cxx11/data/lambda.1.cpp
@@ -0,0 +1 @@
+Foo foo([&](int a) { ++a; });
diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
index 5f2e67c33f..69dbac85f8 100644
--- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
+++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
@@ -98,13 +98,14 @@ class tst_cxx11: public QObject
}
};
- Document::Ptr document(const QString &fileName, QByteArray *errors = 0)
+ Document::Ptr document(const QString &fileName, QByteArray *errors = 0, bool c99Enabled = false)
{
Document::Ptr doc = Document::create(fileName);
QFile file(testdata(fileName));
if (file.open(QFile::ReadOnly)) {
LanguageFeatures features;
features.cxx11Enabled = true;
+ features.c99Enabled = c99Enabled;
Client client(errors);
doc->control()->setDiagnosticClient(&client);
doc->setUtf8Source(QTextStream(&file).readAll().toUtf8());
@@ -124,6 +125,9 @@ private Q_SLOTS:
void parse_data();
void parse();
+ void parseWithC99Enabled_data();
+ void parseWithC99Enabled();
+
//
// checks for the semantic
//
@@ -169,6 +173,29 @@ void tst_cxx11::parse()
VERIFY_ERRORS();
}
+void tst_cxx11::parseWithC99Enabled_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("errorFile");
+
+ QTest::newRow("lambda.1") << "lambda.1.cpp" << "";
+}
+
+void tst_cxx11::parseWithC99Enabled()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, errorFile);
+
+ const bool c99Enabled = true;
+ QByteArray errors;
+ Document::Ptr doc = document(file, &errors, c99Enabled);
+
+ if (! qgetenv("DEBUG").isNull())
+ printf("%s\n", errors.constData());
+
+ VERIFY_ERRORS();
+}
+
//
// check the visibility of symbols declared inside inline namespaces
//