forked from qt-creator/qt-creator
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: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
22
src/libs/3rdparty/cplusplus/AST.cpp
vendored
22
src/libs/3rdparty/cplusplus/AST.cpp
vendored
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
25
src/libs/3rdparty/cplusplus/AST.h
vendored
25
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -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:
|
||||
|
||||
9
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
9
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -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;
|
||||
|
||||
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
@@ -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())
|
||||
|
||||
15
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
15
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -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;
|
||||
|
||||
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
@@ -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;
|
||||
|
||||
8
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
8
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -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)) {
|
||||
|
||||
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
@@ -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 *) {}
|
||||
|
||||
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
@@ -113,6 +113,7 @@ class NestedNameSpecifierAST;
|
||||
class NewArrayDeclaratorAST;
|
||||
class NewExpressionAST;
|
||||
class NewTypeIdAST;
|
||||
class NoExceptOperatorExpressionAST;
|
||||
class NoExceptSpecificationAST;
|
||||
class NumericLiteralAST;
|
||||
class ObjCClassDeclarationAST;
|
||||
|
||||
21
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
21
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -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()) {
|
||||
|
||||
1
src/libs/3rdparty/cplusplus/Parser.h
vendored
1
src/libs/3rdparty/cplusplus/Parser.h
vendored
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user