Commit 158b07c9 authored by Claus Steuer's avatar Claus Steuer

C++: Support noexcept operator

The code model failed to parse the noexcept operator which is often
used in noexcept specifiers, e.g.: "void f() noexcept(noexcept(g()));"
Consequently some c++11 headers such as unordered_map, array
and unordered_set could not be parsed and no code completition was
available. I have created the NoExceptOperatorExpressionAST class
which is created whenever a noexcept token is found in an
expression with operator precedence. The noExcept test case
in the cplusplus/cxx11 test now contains a function that
uses the noexcept operator.

Fixed noexcept operator parsing

Added the test requested by Sergey Shambir, which then revealed that
i had not implemeneted the noexpect operator parsing according to the
c++ specification.
As stated here http://cpp0x.centaur.ath.cx/expr.unary.noexcept.html
the noexcept operator is a unary-expression that contains an
expression (and not a constant-expression). This should now be fixed.

Change-Id: Id4a99a43b660bd83e7680274491d99a698b57094
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@theqtcompany.com>
parent b1f69749
......@@ -4560,3 +4560,25 @@ unsigned AlignmentSpecifierAST::lastToken() const
return 1;
}
/** \generated */
unsigned NoExceptOperatorExpressionAST::firstToken() const
{
if (noexcept_token)
return noexcept_token;
if (expression)
if (unsigned candidate = expression->firstToken())
return candidate;
return 0;
}
/** \generated */
unsigned NoExceptOperatorExpressionAST::lastToken() const
{
if (expression)
if (unsigned candidate = expression->lastToken())
return candidate;
if (noexcept_token)
return noexcept_token + 1;
return 1;
}
......@@ -206,6 +206,7 @@ public:
virtual NewArrayDeclaratorAST *asNewArrayDeclarator() { return 0; }
virtual NewExpressionAST *asNewExpression() { return 0; }
virtual NewTypeIdAST *asNewTypeId() { return 0; }
virtual NoExceptOperatorExpressionAST *asNoExceptOperatorExpression() { return 0; }
virtual NoExceptSpecificationAST *asNoExceptSpecification() { return 0; }
virtual NumericLiteralAST *asNumericLiteral() { return 0; }
virtual ObjCClassDeclarationAST *asObjCClassDeclaration() { return 0; }
......@@ -3397,6 +3398,30 @@ protected:
virtual bool match0(AST *, ASTMatcher *);
};
class CPLUSPLUS_EXPORT NoExceptOperatorExpressionAST: public ExpressionAST
{
public:
unsigned noexcept_token;
ExpressionAST *expression;
public:
NoExceptOperatorExpressionAST()
: noexcept_token(0)
, expression(0)
{}
virtual NoExceptOperatorExpressionAST *asNoExceptOperatorExpression() { return this; }
virtual unsigned firstToken() const;
virtual unsigned lastToken() const;
virtual NoExceptOperatorExpressionAST *clone(MemoryPool *pool) const;
protected:
virtual void accept0(ASTVisitor *visitor);
virtual bool match0(AST *, ASTMatcher *);
};
class CPLUSPLUS_EXPORT TranslationUnitAST: public AST
{
public:
......
......@@ -1267,6 +1267,15 @@ ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const
return ast;
}
NoExceptOperatorExpressionAST *NoExceptOperatorExpressionAST::clone(MemoryPool *pool) const
{
NoExceptOperatorExpressionAST *ast = new (pool) NoExceptOperatorExpressionAST;
ast->noexcept_token = noexcept_token;
if (expression)
ast->expression = expression->clone(pool);
return ast;
}
TranslationUnitAST *TranslationUnitAST::clone(MemoryPool *pool) const
{
TranslationUnitAST *ast = new (pool) TranslationUnitAST;
......
......@@ -880,6 +880,14 @@ bool ThrowExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
return false;
}
bool NoExceptOperatorExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (NoExceptOperatorExpressionAST *_other = pattern->asNoExceptOperatorExpression())
return matcher->match(this, _other);
return false;
}
bool TranslationUnitAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (TranslationUnitAST *_other = pattern->asTranslationUnit())
......
......@@ -2145,6 +2145,21 @@ bool ASTMatcher::match(ThrowExpressionAST *node, ThrowExpressionAST *pattern)
return true;
}
bool ASTMatcher::match(NoExceptOperatorExpressionAST *node, NoExceptOperatorExpressionAST *pattern)
{
(void) node;
(void) pattern;
pattern->noexcept_token = node->noexcept_token;
if (! pattern->expression)
pattern->expression = node->expression;
else if (! AST::match(node->expression, pattern->expression, this))
return false;
return true;
}
bool ASTMatcher::match(TranslationUnitAST *node, TranslationUnitAST *pattern)
{
(void) node;
......
......@@ -106,6 +106,7 @@ public:
virtual bool match(NewArrayDeclaratorAST *node, NewArrayDeclaratorAST *pattern);
virtual bool match(NewExpressionAST *node, NewExpressionAST *pattern);
virtual bool match(NewTypeIdAST *node, NewTypeIdAST *pattern);
virtual bool match(NoExceptOperatorExpressionAST *node, NoExceptOperatorExpressionAST *pattern);
virtual bool match(NoExceptSpecificationAST *node, NoExceptSpecificationAST *pattern);
virtual bool match(NumericLiteralAST *node, NumericLiteralAST *pattern);
virtual bool match(ObjCClassDeclarationAST *node, ObjCClassDeclarationAST *pattern);
......
......@@ -837,6 +837,13 @@ public:
return ast;
}
NoExceptOperatorExpressionAST *NoExceptOperatorExpression(ExpressionAST *expression = 0)
{
NoExceptOperatorExpressionAST *ast = new (&pool) NoExceptOperatorExpressionAST;
ast->expression = expression;
return ast;
}
TranslationUnitAST *TranslationUnit(DeclarationListAST *declaration_list = 0)
{
TranslationUnitAST *ast = new (&pool) TranslationUnitAST;
......
......@@ -930,6 +930,14 @@ void ThrowExpressionAST::accept0(ASTVisitor *visitor)
visitor->endVisit(this);
}
void NoExceptOperatorExpressionAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
accept(expression, visitor);
}
visitor->endVisit(this);
}
void TranslationUnitAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
......
......@@ -148,6 +148,7 @@ public:
virtual bool visit(NewArrayDeclaratorAST *) { return true; }
virtual bool visit(NewExpressionAST *) { return true; }
virtual bool visit(NewTypeIdAST *) { return true; }
virtual bool visit(NoExceptOperatorExpressionAST *) { return true; }
virtual bool visit(NoExceptSpecificationAST *) { return true; }
virtual bool visit(NumericLiteralAST *) { return true; }
virtual bool visit(ObjCClassDeclarationAST *) { return true; }
......@@ -298,6 +299,7 @@ public:
virtual void endVisit(NewArrayDeclaratorAST *) {}
virtual void endVisit(NewExpressionAST *) {}
virtual void endVisit(NewTypeIdAST *) {}
virtual void endVisit(NoExceptOperatorExpressionAST *) {}
virtual void endVisit(NoExceptSpecificationAST *) {}
virtual void endVisit(NumericLiteralAST *) {}
virtual void endVisit(ObjCClassDeclarationAST *) {}
......
......@@ -113,6 +113,7 @@ class NestedNameSpecifierAST;
class NewArrayDeclaratorAST;
class NewExpressionAST;
class NewTypeIdAST;
class NoExceptOperatorExpressionAST;
class NoExceptSpecificationAST;
class NumericLiteralAST;
class ObjCClassDeclarationAST;
......
......@@ -5238,6 +5238,14 @@ bool Parser::parseUnaryExpression(ExpressionAST *&node)
return true;
}
case T_NOEXCEPT: {
if (!_languageFeatures.cxx11Enabled)
break;
return parseNoExceptOperatorExpression(node);
}
default:
break;
} // switch
......@@ -5674,6 +5682,19 @@ bool Parser::parseThrowExpression(ExpressionAST *&node)
return false;
}
bool Parser::parseNoExceptOperatorExpression(ExpressionAST *&node)
{
DEBUG_THIS_RULE();
if (_languageFeatures.cxx11Enabled && LA() == T_NOEXCEPT) {
NoExceptOperatorExpressionAST *ast = new (_pool) NoExceptOperatorExpressionAST;
ast->noexcept_token = consumeToken();
parseExpression(ast->expression);
node = ast;
return true;
}
return false;
}
bool Parser::lookAtObjCSelector() const
{
switch (LA()) {
......
......@@ -155,6 +155,7 @@ public:
bool parseTemplateParameter(DeclarationAST *&node);
bool parseTemplateParameterList(DeclarationListAST *&node);
bool parseThrowExpression(ExpressionAST *&node);
bool parseNoExceptOperatorExpression(ExpressionAST *&node);
bool parseTryBlockStatement(StatementAST *&node, CtorInitializerAST **placeholder);
bool parseCatchClause(CatchClauseListAST *&node);
bool parseTypeId(ExpressionAST *&node);
......
......@@ -1381,6 +1381,12 @@ bool FindUsages::visit(ThrowExpressionAST *ast)
return false;
}
bool FindUsages::visit(NoExceptOperatorExpressionAST* ast)
{
this->expression(ast->expression);
return false;
}
bool FindUsages::visit(TypeIdAST *ast)
{
for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) {
......
......@@ -205,6 +205,7 @@ protected:
virtual bool visit(NestedExpressionAST *ast);
virtual bool visit(StringLiteralAST *ast);
virtual bool visit(ThrowExpressionAST *ast);
virtual bool visit(NoExceptOperatorExpressionAST *ast);
virtual bool visit(TypeIdAST *ast);
virtual bool visit(UnaryExpressionAST *ast);
virtual bool visit(ObjCMessageExpressionAST *ast);
......
......@@ -1237,6 +1237,14 @@ virtual bool visit(ThrowExpressionAST *ast)
return false;
}
virtual bool visit(NoExceptOperatorExpressionAST *ast)
{
if (ast->noexcept_token)
terminal(ast->noexcept_token, ast);
nonterminal(ast->expression);
return false;
}
virtual bool visit(TranslationUnitAST *ast)
{
for (DeclarationListAST *iter = ast->declaration_list; iter; iter = iter->next)
......
......@@ -3,3 +3,11 @@ void f() noexcept {
void g() noexcept(1) {
}
void h() noexcept(noexcept(f())) {
}
int main() {
bool noExcept_hf = noexcept(h()) && noexcept(f());
}
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