OK.
On Mon, Jul 18, 2016 at 5:14 PM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > This patch fixes two issues: > 1) as shown in the first testcase, cp_parser_save_member_function_body > adds the catch (....) { ... } tokens into the saved token range > even when there is no function try block (missing try keyword) > 2) if the method starts with __transaction_{atomic,relaxed}, and > e.g. contains {}s somewhere in the mem-initializers, then > cp_parser_save_member_function_body stops saving the tokens early > instead of late > > The following patch attempts to handle the same cases > cp_parser_function_definition_after_declarator handles (ok, ignores > the already unsupported return extension) - note that > cp_parser_txn_attribute_opt handles only a small subset of C++11 attributes > (and only once, not multiple times). > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2016-07-18 Jakub Jelinek <ja...@redhat.com> > > PR c++/71909 > * parser.c (cp_parser_save_member_function_body): Consume > __transaction_relaxed or __transaction_atomic with optional > attribute. Only skip catch with block if try keyword is seen. > > * g++.dg/parse/pr71909.C: New test. > * g++.dg/tm/pr71909.C: New test. > > --- gcc/cp/parser.c.jj 2016-07-16 10:41:04.000000000 +0200 > +++ gcc/cp/parser.c 2016-07-18 11:47:49.487748010 +0200 > @@ -26044,6 +26044,7 @@ cp_parser_save_member_function_body (cp_ > cp_token *first; > cp_token *last; > tree fn; > + bool function_try_block = false; > > /* Create the FUNCTION_DECL. */ > fn = grokmethod (decl_specifiers, declarator, attributes); > @@ -26065,9 +26066,43 @@ cp_parser_save_member_function_body (cp_ > /* Save away the tokens that make up the body of the > function. */ > first = parser->lexer->next_token; > + > + if (cp_lexer_next_token_is_keyword (parser->lexer, > RID_TRANSACTION_RELAXED)) > + cp_lexer_consume_token (parser->lexer); > + else if (cp_lexer_next_token_is_keyword (parser->lexer, > + RID_TRANSACTION_ATOMIC)) > + { > + cp_lexer_consume_token (parser->lexer); > + /* Match cp_parser_txn_attribute_opt [[ identifier ]]. */ > + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE) > + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_SQUARE) > + && (cp_lexer_nth_token_is (parser->lexer, 3, CPP_NAME) > + || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD)) > + && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_SQUARE) > + && cp_lexer_nth_token_is (parser->lexer, 5, CPP_CLOSE_SQUARE)) > + { > + cp_lexer_consume_token (parser->lexer); > + cp_lexer_consume_token (parser->lexer); > + cp_lexer_consume_token (parser->lexer); > + cp_lexer_consume_token (parser->lexer); > + cp_lexer_consume_token (parser->lexer); > + } > + else > + while (cp_next_tokens_can_be_gnu_attribute_p (parser) > + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)) > + { > + cp_lexer_consume_token (parser->lexer); > + if (cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0)) > + break; > + } > + } > + > /* Handle function try blocks. */ > if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY)) > - cp_lexer_consume_token (parser->lexer); > + { > + cp_lexer_consume_token (parser->lexer); > + function_try_block = true; > + } > /* We can have braced-init-list mem-initializers before the fn body. */ > if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) > { > @@ -26085,8 +26120,9 @@ cp_parser_save_member_function_body (cp_ > } > cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0); > /* Handle function try blocks. */ > - while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH)) > - cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0); > + if (function_try_block) > + while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH)) > + cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0); > last = parser->lexer->next_token; > > /* Save away the inline definition; we will process it when the > --- gcc/testsuite/g++.dg/parse/pr71909.C.jj 2016-07-18 11:55:51.169600236 > +0200 > +++ gcc/testsuite/g++.dg/parse/pr71909.C 2016-07-18 11:57:09.555599364 > +0200 > @@ -0,0 +1,22 @@ > +// PR c++/71909 > +// { dg-do compile } > + > +struct S > +{ > + S () try : m (0) {} > + catch (...) {} > + void foo () try {} > + catch (int) {} > + catch (...) {} > + int m; > +}; > + > +struct T > +{ > + T () : m (0) {} > + catch (...) {} // { dg-error "expected unqualified-id before" } > + void foo () {} > + catch (int) {} // { dg-error "expected unqualified-id before" } > + catch (...) {} // { dg-error "expected unqualified-id before" } > + int m; > +}; > --- gcc/testsuite/g++.dg/tm/pr71909.C.jj 2016-07-18 12:01:59.888892245 > +0200 > +++ gcc/testsuite/g++.dg/tm/pr71909.C 2016-07-18 12:01:14.000000000 +0200 > @@ -0,0 +1,18 @@ > +// PR c++/71909 > +// { dg-do compile { target c++11 } } > +// { dg-options "-fgnu-tm" } > + > +struct S > +{ > + S () __transaction_atomic [[outer]] try : m {0} {} catch (int) {} catch > (...) {} > + int m; > +}; > + > +struct T > +{ > + T () __transaction_atomic __attribute__((outer)) try : m {0} {} catch > (int) {} catch (...) {} > + int m; > +}; > + > +void foo () __transaction_atomic [[outer]] try {} catch (int) {} catch (...) > {} > +void bar () __transaction_atomic __attribute__((outer)) try {} catch (int) > {} catch (...) {} > > Jakub