Commit c33000b0 authored by Milian Wolff's avatar Milian Wolff
Browse files

c++11 support: handle noexcept-specification and noexcept-expression in our parser

This is particularly useful with new GCC toolchain version 4.7.0, where these keywords
are frequently used throughout STL.

thanks to Ivan Shapovalov for the patch, I just cleaned it up a bit and added a unit test

REVIEW: 104498
CCBUG: 297604
parent 056c6b71
......@@ -540,6 +540,12 @@ public:
// the exception spec is variadic (pack expansion)
uint ellipsis;
const ListNode<TypeIdAST*> *type_ids;
// noexcept token
uint no_except;
// if set, this is actually a noexcept(...) expression
// and the ast node below points to the ...
ExpressionAST *noexcept_expression;
};
class ExpressionOrDeclarationStatementAST : public StatementAST
......
......@@ -321,15 +321,32 @@ void CodeGenerator::visitEnumerator(EnumeratorAST* node)
void CodeGenerator::visitExceptionSpecification(ExceptionSpecificationAST* node)
{
printToken(Token_throw);
if (node->no_except)
{
printToken(Token_noexcept);
m_output << "(";
if (node->noexcept_expression)
{
m_output << "(";
DefaultVisitor::visitExceptionSpecification(node);
print(node->ellipsis);
m_output << ")";
}
}
DefaultVisitor::visitExceptionSpecification(node);
else
{
printToken(Token_throw);
m_output << ")";
m_output << "(";
print(node->ellipsis);
DefaultVisitor::visitExceptionSpecification(node);
m_output << ")";
}
}
void CodeGenerator::visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST* node)
......
......@@ -145,6 +145,7 @@ void DefaultVisitor::visitEnumerator(EnumeratorAST *node)
void DefaultVisitor::visitExceptionSpecification(ExceptionSpecificationAST *node)
{
visit(node->noexcept_expression);
visitNodes(this, node->type_ids);
}
......
......@@ -213,6 +213,7 @@ KDevVarLengthArray<KDevVarLengthArray<QPair<uint, TOKEN_KIND>, 10 >, index_size
ADD_TOKEN(mutable);
ADD_TOKEN(namespace);
ADD_TOKEN(new);
ADD_TOKEN(noexcept);
ADD_TOKEN(not);
ADD_TOKEN(not_eq);
ADD_TOKEN(nullptr);
......
......@@ -2440,33 +2440,61 @@ bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node)
{
uint start = session->token_stream->cursor();
CHECK(Token_throw);
ADVANCE('(', "(");
ExceptionSpecificationAST *ast
= CreateNode<ExceptionSpecificationAST>(session->mempool);
if (session->token_stream->lookAhead() == Token_ellipsis)
if (session->token_stream->lookAhead() == Token_throw)
{
ast->ellipsis = session->token_stream->cursor();
advance();
}
parseTypeIdList(ast->type_ids);
ADVANCE('(', "(");
ExceptionSpecificationAST *ast
= CreateNode<ExceptionSpecificationAST>(session->mempool);
if (!ast->ellipsis && session->token_stream->lookAhead() == Token_ellipsis)
if (session->token_stream->lookAhead() == Token_ellipsis)
{
ast->ellipsis = session->token_stream->cursor();
advance();
}
parseTypeIdList(ast->type_ids);
if (!ast->ellipsis && session->token_stream->lookAhead() == Token_ellipsis)
{
ast->ellipsis = session->token_stream->cursor();
advance();
}
ADVANCE(')', ")");
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
else if (session->token_stream->lookAhead() == Token_noexcept)
{
ast->ellipsis = session->token_stream->cursor();
ExceptionSpecificationAST *ast
= CreateNode<ExceptionSpecificationAST>(session->mempool);
ast->no_except = session->token_stream->cursor();
advance();
}
if (session->token_stream->lookAhead() == '(')
{
advance();
parseExpression(ast->noexcept_expression);
CHECK(')');
}
ADVANCE(')', ")");
UPDATE_POS (ast, start, _M_last_valid_token+1);
node = ast;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
return true;
return false;
}
bool Parser::parseEnumerator(EnumeratorAST *&node)
......@@ -4489,6 +4517,29 @@ bool Parser::parseUnaryExpression(ExpressionAST *&node)
return true;
}
case Token_noexcept: // same as generic case, but parentheses are not optional
{
advance();
if (session->token_stream->lookAhead() != '(')
{
tokenRequiredError ('(');
return false;
}
ExpressionAST *expr = 0;
if (!parseUnaryExpression(expr))
return false;
UnaryExpressionAST *ast = CreateNode<UnaryExpressionAST>(session->mempool);
ast->op = Token_noexcept;
ast->expression = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
default:
break;
}
......
......@@ -126,6 +126,7 @@ private slots:
void classVirtSpec();
void classVirtSpec_data();
void testUsingAlias();
void testNoexcept();
//END C++2011 Support
protected:
......
......@@ -548,4 +548,14 @@ void TestParser::testUsingAlias()
QVERIFY(ast);
dump(ast);
QVERIFY(control.problems().isEmpty());
}
\ No newline at end of file
}
void TestParser::testNoexcept()
{
TranslationUnitAST* ast = parse( "void f1() noexcept;\n"
"void f2() noexcept(false);\n"
"class a { void m1() noexcept; void m2() noexcept(true); };" );
QVERIFY(ast);
dump(ast);
QVERIFY(control.problems().isEmpty());
}
......@@ -84,6 +84,7 @@ static char const * const _S_token_names[] = {
"mutable",
"namespace",
"new",
"noexcept",
"not",
"not_eq",
"nullptr",
......@@ -202,6 +203,7 @@ static char const * const _S_token_texts[] = {
"mutable",
"namespace",
"new",
"noexcept",
"!",
"!=",
"nullptr",
......
......@@ -90,6 +90,7 @@ enum TOKEN_KIND
Token_mutable,
Token_namespace,
Token_new,
Token_noexcept,
Token_not,
Token_not_eq,
Token_nullptr,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment