C++11: Make expression-list expand to initializer-list.

This will fix a couple more places where brace-init-lists and
pack expansions are allowed but are not currently accepted by
the parser. For example:

foo(abc...);

now parses correctly.

Change-Id: I93710cef35154fea8437329f3174e4a2d56637b8
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Christian Kamm
2012-09-19 10:09:55 +02:00
committed by hjk
parent 0c3acb80c8
commit 2aa27e6d22
4 changed files with 12 additions and 35 deletions

View File

@@ -2651,7 +2651,7 @@ bool Parser::parseInitializer0x(ExpressionAST *&node, unsigned *equals_token)
} }
else if (LA() == T_LPAREN) { else if (LA() == T_LPAREN) {
return parseExpressionListParen0x(node); return parseExpressionListParen(node);
} }
return false; return false;
@@ -2787,7 +2787,7 @@ bool Parser::parseMemInitializer(MemInitializerListAST *&node)
ast->name = name; ast->name = name;
if (LA() == T_LPAREN) { if (LA() == T_LPAREN) {
parseExpressionListParen0x(ast->expression); parseExpressionListParen(ast->expression);
} else if (_cxx0xEnabled && LA() == T_LBRACE) { } else if (_cxx0xEnabled && LA() == T_LBRACE) {
parseBracedInitList0x(ast->expression); parseBracedInitList0x(ast->expression);
} else { } else {
@@ -2834,18 +2834,13 @@ bool Parser::parseTypeIdList(ExpressionListAST *&node)
return false; return false;
} }
// Note that this function doesn't parse a C++11-style expression-list
// yet, so it doesn't allow for brace-initializers.
bool Parser::parseExpressionList(ExpressionListAST *&node) bool Parser::parseExpressionList(ExpressionListAST *&node)
{ {
DEBUG_THIS_RULE(); DEBUG_THIS_RULE();
#ifdef CPLUSPLUS_WITH_CXXOX_INITIALIZER_LIST
if (_cxx0xEnabled) if (_cxx0xEnabled)
return parseInitializerList0x(node); return parseInitializerList0x(node);
#endif
// ### remove me
ExpressionListAST **expression_list_ptr = &node; ExpressionListAST **expression_list_ptr = &node;
ExpressionAST *expression = 0; ExpressionAST *expression = 0;
if (parseAssignmentExpression(expression)) { if (parseAssignmentExpression(expression)) {
@@ -4959,7 +4954,7 @@ bool Parser::parseUnaryExpression(ExpressionAST *&node)
} }
// new-placement ::= T_LPAREN expression-list T_RPAREN // new-placement ::= T_LPAREN expression-list T_RPAREN
bool Parser::parseExpressionListParen(ExpressionListParenAST *&node) bool Parser::parseExpressionListParen(ExpressionAST *&node)
{ {
DEBUG_THIS_RULE(); DEBUG_THIS_RULE();
if (LA() == T_LPAREN) { if (LA() == T_LPAREN) {
@@ -4979,28 +4974,6 @@ bool Parser::parseExpressionListParen(ExpressionListParenAST *&node)
return false; return false;
} }
// like above, but for C++11 where expression-list expands to initializer-list
// and can contain braced-init-list members
bool Parser::parseExpressionListParen0x(ExpressionAST *&node)
{
DEBUG_THIS_RULE();
if (LA() == T_LPAREN) {
unsigned lparen_token = consumeToken();
ExpressionListAST *expression_list = 0;
if (parseInitializerList0x(expression_list) && expression_list && LA() == T_RPAREN) {
unsigned rparen_token = consumeToken();
ExpressionListParenAST *ast = new (_pool) ExpressionListParenAST;
ast->lparen_token = lparen_token;
ast->expression_list = expression_list;
ast->rparen_token = rparen_token;
node = ast;
return true;
}
}
return false;
}
// new-expression ::= T_COLON_COLON? T_NEW new-placement.opt // new-expression ::= T_COLON_COLON? T_NEW new-placement.opt
// new-type-id new-initializer.opt // new-type-id new-initializer.opt
@@ -5018,14 +4991,14 @@ bool Parser::parseNewExpression(ExpressionAST *&node)
ast->new_token = consumeToken(); ast->new_token = consumeToken();
ExpressionListParenAST *parenExpressionList = 0; ExpressionAST *parenExpressionList = 0;
if (parseExpressionListParen(parenExpressionList)) { if (parseExpressionListParen(parenExpressionList)) {
unsigned after_new_placement = cursor(); unsigned after_new_placement = cursor();
NewTypeIdAST *new_type_id = 0; NewTypeIdAST *new_type_id = 0;
if (parseNewTypeId(new_type_id)) { if (parseNewTypeId(new_type_id)) {
ast->new_placement = parenExpressionList; ast->new_placement = parenExpressionList->asExpressionListParen();
ast->new_type_id = new_type_id; ast->new_type_id = new_type_id;
parseNewInitializer(ast->new_initializer); parseNewInitializer(ast->new_initializer);
// recognized new-placement.opt new-type-id new-initializer.opt // recognized new-placement.opt new-type-id new-initializer.opt
@@ -5038,7 +5011,7 @@ bool Parser::parseNewExpression(ExpressionAST *&node)
unsigned lparen_token = consumeToken(); unsigned lparen_token = consumeToken();
ExpressionAST *type_id = 0; ExpressionAST *type_id = 0;
if (parseTypeId(type_id) && LA() == T_RPAREN) { if (parseTypeId(type_id) && LA() == T_RPAREN) {
ast->new_placement = parenExpressionList; ast->new_placement = parenExpressionList->asExpressionListParen();
ast->lparen_token = lparen_token; ast->lparen_token = lparen_token;
ast->type_id = type_id; ast->type_id = type_id;
ast->rparen_token = consumeToken(); ast->rparen_token = consumeToken();

View File

@@ -132,8 +132,7 @@ public:
bool parseNamespaceAliasDefinition(DeclarationAST *&node); bool parseNamespaceAliasDefinition(DeclarationAST *&node);
bool parseNewArrayDeclarator(NewArrayDeclaratorListAST *&node); bool parseNewArrayDeclarator(NewArrayDeclaratorListAST *&node);
bool parseNewExpression(ExpressionAST *&node); bool parseNewExpression(ExpressionAST *&node);
bool parseExpressionListParen(ExpressionListParenAST *&node); bool parseExpressionListParen(ExpressionAST *&node);
bool parseExpressionListParen0x(ExpressionAST *&node);
bool parseNewInitializer(NewInitializerAST *&node); bool parseNewInitializer(NewInitializerAST *&node);
bool parseNewTypeId(NewTypeIdAST *&node); bool parseNewTypeId(NewTypeIdAST *&node);
bool parseOperator(OperatorAST *&node); bool parseOperator(OperatorAST *&node);

View File

@@ -0,0 +1,4 @@
template <class ... Args>
int foo(Args args...) {
bar(args..., {args...}, e, f);
}

View File

@@ -145,6 +145,7 @@ void tst_cxx11::parse_data()
QTest::newRow("aliasDecl.1") << "aliasDecl.1.cpp" << ""; QTest::newRow("aliasDecl.1") << "aliasDecl.1.cpp" << "";
QTest::newRow("enums.1") << "enums.1.cpp" << ""; QTest::newRow("enums.1") << "enums.1.cpp" << "";
QTest::newRow("templateGreaterGreater.1") << "templateGreaterGreater.1.cpp" << ""; QTest::newRow("templateGreaterGreater.1") << "templateGreaterGreater.1.cpp" << "";
QTest::newRow("packExpansion.1") << "packExpansion.1.cpp" << "";
} }
void tst_cxx11::parse() void tst_cxx11::parse()