From 8c1a45565c791a2d965ae3905ae485f6a58e0626 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 17 Sep 2012 12:26:49 +0200 Subject: [PATCH] C++11: Accept ref-qualifiers in function declarators. Means void foo() const &; void bar() &&; and the corresponding pointer-to-member declarators now parse. Change-Id: Idbf295bd4f51cd5d9e38efcac1940b8cc2e32fce Reviewed-by: hjk --- src/libs/3rdparty/cplusplus/AST.cpp | 8 +++++++ src/libs/3rdparty/cplusplus/AST.h | 4 ++++ src/libs/3rdparty/cplusplus/ASTClone.cpp | 2 ++ src/libs/3rdparty/cplusplus/ASTMatcher.cpp | 4 ++++ src/libs/3rdparty/cplusplus/Parser.cpp | 21 +++++++++++++++++-- src/libs/3rdparty/cplusplus/Parser.h | 1 + .../cplusplus/cxx11/data/refQualifier.1.cpp | 21 +++++++++++++++++++ tests/auto/cplusplus/cxx11/tst_cxx11.cpp | 1 + tests/tools/cplusplus-dump/dumpers.inc | 4 ++++ 9 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 tests/auto/cplusplus/cxx11/data/refQualifier.1.cpp diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp index 2bd8aa5c349..05c4782f975 100644 --- a/src/libs/3rdparty/cplusplus/AST.cpp +++ b/src/libs/3rdparty/cplusplus/AST.cpp @@ -1369,6 +1369,8 @@ unsigned FunctionDeclaratorAST::firstToken() const if (cv_qualifier_list) if (unsigned candidate = cv_qualifier_list->firstToken()) return candidate; + if (ref_qualifier_token) + return ref_qualifier_token; if (exception_specification) if (unsigned candidate = exception_specification->firstToken()) return candidate; @@ -1393,6 +1395,8 @@ unsigned FunctionDeclaratorAST::lastToken() const if (exception_specification) if (unsigned candidate = exception_specification->lastToken()) return candidate; + if (ref_qualifier_token) + return ref_qualifier_token + 1; if (cv_qualifier_list) if (unsigned candidate = cv_qualifier_list->lastToken()) return candidate; @@ -3067,12 +3071,16 @@ unsigned PointerToMemberAST::firstToken() const if (cv_qualifier_list) if (unsigned candidate = cv_qualifier_list->firstToken()) return candidate; + if (ref_qualifier_token) + return ref_qualifier_token; return 0; } /** \generated */ unsigned PointerToMemberAST::lastToken() const { + if (ref_qualifier_token) + return ref_qualifier_token + 1; if (cv_qualifier_list) if (unsigned candidate = cv_qualifier_list->lastToken()) return candidate; diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index 288002a3ee1..2c7edf14499 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -1457,6 +1457,7 @@ public: ParameterDeclarationClauseAST *parameter_declaration_clause; unsigned rparen_token; SpecifierListAST *cv_qualifier_list; + unsigned ref_qualifier_token; ExceptionSpecificationAST *exception_specification; TrailingReturnTypeAST *trailing_return_type; ExpressionAST *as_cpp_initializer; @@ -1470,6 +1471,7 @@ public: , parameter_declaration_clause(0) , rparen_token(0) , cv_qualifier_list(0) + , ref_qualifier_token(0) , exception_specification(0) , trailing_return_type(0) , as_cpp_initializer(0) @@ -2825,6 +2827,7 @@ public: NestedNameSpecifierListAST *nested_name_specifier_list; unsigned star_token; SpecifierListAST *cv_qualifier_list; + unsigned ref_qualifier_token; public: PointerToMemberAST() @@ -2832,6 +2835,7 @@ public: , nested_name_specifier_list(0) , star_token(0) , cv_qualifier_list(0) + , ref_qualifier_token(0) {} virtual PointerToMemberAST *asPointerToMember() { return this; } diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp index 911cd8cf55f..2a3f95bed0e 100644 --- a/src/libs/3rdparty/cplusplus/ASTClone.cpp +++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp @@ -487,6 +487,7 @@ FunctionDeclaratorAST *FunctionDeclaratorAST::clone(MemoryPool *pool) const for (SpecifierListAST *iter = cv_qualifier_list, **ast_iter = &ast->cv_qualifier_list; iter; iter = iter->next, ast_iter = &(*ast_iter)->next) *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0); + ast->ref_qualifier_token = ref_qualifier_token; if (exception_specification) ast->exception_specification = exception_specification->clone(pool); if (trailing_return_type) @@ -1068,6 +1069,7 @@ PointerToMemberAST *PointerToMemberAST::clone(MemoryPool *pool) const for (SpecifierListAST *iter = cv_qualifier_list, **ast_iter = &ast->cv_qualifier_list; iter; iter = iter->next, ast_iter = &(*ast_iter)->next) *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0); + ast->ref_qualifier_token = ref_qualifier_token; return ast; } diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp index 7a55d0a5798..b168a38fb43 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp @@ -809,6 +809,8 @@ bool ASTMatcher::match(FunctionDeclaratorAST *node, FunctionDeclaratorAST *patte else if (! AST::match(node->cv_qualifier_list, pattern->cv_qualifier_list, this)) return false; + pattern->ref_qualifier_token = node->ref_qualifier_token; + if (! pattern->exception_specification) pattern->exception_specification = node->exception_specification; else if (! AST::match(node->exception_specification, pattern->exception_specification, this)) @@ -1817,6 +1819,8 @@ bool ASTMatcher::match(PointerToMemberAST *node, PointerToMemberAST *pattern) else if (! AST::match(node->cv_qualifier_list, pattern->cv_qualifier_list, this)) return false; + pattern->ref_qualifier_token = node->ref_qualifier_token; + return true; } diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index aab706db65c..16b5ba18e94 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -1176,6 +1176,21 @@ bool Parser::parseCvQualifiers(SpecifierListAST *&node) return start != cursor(); } +bool Parser::parseRefQualifier(unsigned &ref_qualifier) +{ + DEBUG_THIS_RULE(); + + if (!_cxx0xEnabled) + return false; + + if (LA() == T_AMPER || LA() == T_AMPER_AMPER) { + ref_qualifier = consumeToken(); + return true; + } + + return false; +} + /** * \brief Handles override and final from C++ 2011, they are pseudo keywords and has special meaning only in function declaration */ @@ -1474,8 +1489,7 @@ bool Parser::parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specif ast->rparen_token = consumeToken(); // ### parse attributes parseCvQualifiers(ast->cv_qualifier_list); - parseOverrideFinalQualifiers(ast->cv_qualifier_list); - // ### parse ref-qualifiers + parseRefQualifier(ast->ref_qualifier_token); parseExceptionSpecification(ast->exception_specification); if (_cxx0xEnabled && ! node->ptr_operator_list && LA() == T_ARROW) { @@ -1494,6 +1508,8 @@ bool Parser::parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specif parseTrailingReturnType(ast->trailing_return_type); } + parseOverrideFinalQualifiers(ast->cv_qualifier_list); + *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast); postfix_ptr = &(*postfix_ptr)->next; } else if (LA() == T_LBRACKET) { @@ -1579,6 +1595,7 @@ bool Parser::parseAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *dec ast->rparen_token = consumeToken(); } parseCvQualifiers(ast->cv_qualifier_list); + parseRefQualifier(ast->ref_qualifier_token); parseExceptionSpecification(ast->exception_specification); *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast); postfix_ptr = &(*postfix_ptr)->next; diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index c4d65254a03..da472097c7a 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -82,6 +82,7 @@ public: bool parseConstantExpression(ExpressionAST *&node); bool parseCtorInitializer(CtorInitializerAST *&node); bool parseCvQualifiers(SpecifierListAST *&node); + bool parseRefQualifier(unsigned &ref_qualifier); bool parseOverrideFinalQualifiers(SpecifierListAST *&node); bool parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list); bool parseDeclaration(DeclarationAST *&node); diff --git a/tests/auto/cplusplus/cxx11/data/refQualifier.1.cpp b/tests/auto/cplusplus/cxx11/data/refQualifier.1.cpp new file mode 100644 index 00000000000..172ede9ae0b --- /dev/null +++ b/tests/auto/cplusplus/cxx11/data/refQualifier.1.cpp @@ -0,0 +1,21 @@ +void foo() noexcept; +class C { + void foo() const noexcept final override; + void foo() const & noexcept final override; + void foo() const && noexcept final override; + auto foo() const noexcept -> void final override; + auto foo() const & noexcept -> void final override; + auto foo() const && noexcept -> void final override; + void foo(); + void foo() &; + void foo() &&; +}; + +int main() { + void (C::*p)() const; + void (C::*p)() const &; + void (C::*p)() const &&; + void (C::*p)(); + void (C::*p)() &; + void (C::*p)() &&; +} diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp index 36844856225..d1c5889b759 100644 --- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp +++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp @@ -139,6 +139,7 @@ void tst_cxx11::parse_data() QTest::newRow("braceInitializers.1") << "braceInitializers.1.cpp" << "braceInitializers.1.errors.txt"; QTest::newRow("braceInitializers.2") << "braceInitializers.2.cpp" << ""; QTest::newRow("defaultdeleteInitializer.1") << "defaultdeleteInitializer.1.cpp" << ""; + QTest::newRow("refQualifier.1") << "refQualifier.1.cpp" << ""; } void tst_cxx11::parse() diff --git a/tests/tools/cplusplus-dump/dumpers.inc b/tests/tools/cplusplus-dump/dumpers.inc index 3aa9b16cc95..3bddba82479 100644 --- a/tests/tools/cplusplus-dump/dumpers.inc +++ b/tests/tools/cplusplus-dump/dumpers.inc @@ -479,6 +479,8 @@ virtual bool visit(FunctionDeclaratorAST *ast) terminal(ast->rparen_token, ast); for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next) nonterminal(iter->value); + if (ast->ref_qualifier_token) + terminal(ast->ref_qualifier_token, ast); nonterminal(ast->exception_specification); nonterminal(ast->trailing_return_type); nonterminal(ast->as_cpp_initializer); @@ -1028,6 +1030,8 @@ virtual bool visit(PointerToMemberAST *ast) terminal(ast->star_token, ast); for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next) nonterminal(iter->value); + if (ast->ref_qualifier_token) + terminal(ast->ref_qualifier_token, ast); return false; }