aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2016-07-20 16:01:30 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2016-07-20 16:01:30 +0200
commit7419f4417a33ff9143317794aa985f7681d1e2a0 (patch)
tree1d243343f1193d9977b24d69c9e1935d177ad3d1 /gcc
parent109d2197c31b766daf9c7b138bc7eeaab12985df (diff)
downloadgcc-7419f4417a33ff9143317794aa985f7681d1e2a0.zip
gcc-7419f4417a33ff9143317794aa985f7681d1e2a0.tar.gz
gcc-7419f4417a33ff9143317794aa985f7681d1e2a0.tar.bz2
re PR c++/71909 (g++ accepts an unreachable function catch block that lacks a corresponding try)
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. From-SVN: r238521
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/parser.c42
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/parse/pr71909.C22
-rw-r--r--gcc/testsuite/g++.dg/tm/pr71909.C18
5 files changed, 88 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7b90320..cc5df6e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2016-07-20 Jakub Jelinek <jakub@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.
+
PR c++/50060
* constexpr.c (cxx_eval_builtin_function_call): Pass false as lval
when evaluating call arguments. Use fold_builtin_call_array instead
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 0a0f67b..84dad48 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -26044,6 +26044,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
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_parser* parser,
/* 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_parser* parser,
}
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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 41042eb..5ea90bf 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2016-07-20 Jakub Jelinek <jakub@redhat.com>
+ PR c++/71909
+ * g++.dg/parse/pr71909.C: New test.
+ * g++.dg/tm/pr71909.C: New test.
+
PR c++/50060
* g++.dg/cpp0x/constexpr-50060.C: New test.
* g++.dg/cpp1y/constexpr-50060.C: New test.
diff --git a/gcc/testsuite/g++.dg/parse/pr71909.C b/gcc/testsuite/g++.dg/parse/pr71909.C
new file mode 100644
index 0000000..ee592bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr71909.C
@@ -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;
+};
diff --git a/gcc/testsuite/g++.dg/tm/pr71909.C b/gcc/testsuite/g++.dg/tm/pr71909.C
new file mode 100644
index 0000000..941f231
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tm/pr71909.C
@@ -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 (...) {}