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