mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 07:00:27 +08:00
Support noexcept-specifications for transaction statements and expressions.
gcc/cp/ * semantics.c (finish_transaction_stmt, build_transaction_expr): Accept new noexcept parameter and handle it. * cp-tree.h (finish_transaction_stmt, build_transaction_expr): Adapt declarations. * parser.c (cp_parser_exception_specification_opt): Extract noexcept-specification parsing to ... (cp_parser_noexcept_specification_opt): ...here. Allow for parsing non-constexpr noexcept arguments. (cp_parser_transaction, cp_parser_transaction_expression): Parse and handle noexcept-specifications. (cp_parser_function_transaction): Adapt to finish_transaction_stmt change. * pt.c (tsubst_expr): Adapt to new noexcept parameters when building transactions. gcc/testsuite/ * g++.dg/tm/noexcept-1.C: New test. * g++.dg/tm/noexcept-2.C: New test. * g++.dg/tm/noexcept-3.C: New test. * g++.dg/tm/noexcept-4.C: New test. * g++.dg/tm/noexcept-5.C: New test. From-SVN: r182234
This commit is contained in:
parent
f2162c3daa
commit
f0f3286a5a
@ -1,3 +1,20 @@
|
||||
2011-12-12 Torvald Riegel <triegel@redhat.com>
|
||||
|
||||
* semantics.c (finish_transaction_stmt, build_transaction_expr):
|
||||
Accept new noexcept parameter and handle it.
|
||||
* cp-tree.h (finish_transaction_stmt, build_transaction_expr): Adapt
|
||||
declarations.
|
||||
* parser.c (cp_parser_exception_specification_opt): Extract
|
||||
noexcept-specification parsing to ...
|
||||
(cp_parser_noexcept_specification_opt): ...here. Allow for parsing
|
||||
non-constexpr noexcept arguments.
|
||||
(cp_parser_transaction, cp_parser_transaction_expression): Parse
|
||||
and handle noexcept-specifications.
|
||||
(cp_parser_function_transaction): Adapt to finish_transaction_stmt
|
||||
change.
|
||||
* pt.c (tsubst_expr): Adapt to new noexcept parameters when
|
||||
building transactions.
|
||||
|
||||
2011-12-12 Torvald Riegel <triegel@redhat.com>
|
||||
|
||||
* cp-tree.def (MUST_NOT_THROW_EXPR): Add condition parameter.
|
||||
|
@ -5587,8 +5587,8 @@ extern void finish_omp_barrier (void);
|
||||
extern void finish_omp_flush (void);
|
||||
extern void finish_omp_taskwait (void);
|
||||
extern tree begin_transaction_stmt (location_t, tree *, int);
|
||||
extern void finish_transaction_stmt (tree, tree, int);
|
||||
extern tree build_transaction_expr (location_t, tree, int);
|
||||
extern void finish_transaction_stmt (tree, tree, int, tree);
|
||||
extern tree build_transaction_expr (location_t, tree, int, tree);
|
||||
extern void finish_omp_taskyield (void);
|
||||
extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool);
|
||||
extern tree baselink_for_fns (tree);
|
||||
|
158
gcc/cp/parser.c
158
gcc/cp/parser.c
@ -19564,6 +19564,78 @@ cp_parser_base_specifier (cp_parser* parser)
|
||||
|
||||
/* Exception handling [gram.exception] */
|
||||
|
||||
/* Parse an (optional) noexcept-specification.
|
||||
|
||||
noexcept-specification:
|
||||
noexcept ( constant-expression ) [opt]
|
||||
|
||||
If no noexcept-specification is present, returns NULL_TREE.
|
||||
Otherwise, if REQUIRE_CONSTEXPR is false, then either parse and return any
|
||||
expression if parentheses follow noexcept, or return BOOLEAN_TRUE_NODE if
|
||||
there are no parentheses. CONSUMED_EXPR will be set accordingly.
|
||||
Otherwise, returns a noexcept specification unless RETURN_COND is true,
|
||||
in which case a boolean condition is returned instead. */
|
||||
|
||||
static tree
|
||||
cp_parser_noexcept_specification_opt (cp_parser* parser,
|
||||
bool require_constexpr,
|
||||
bool* consumed_expr,
|
||||
bool return_cond)
|
||||
{
|
||||
cp_token *token;
|
||||
const char *saved_message;
|
||||
|
||||
/* Peek at the next token. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
/* Is it a noexcept-specification? */
|
||||
if (cp_parser_is_keyword (token, RID_NOEXCEPT))
|
||||
{
|
||||
tree expr;
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
|
||||
{
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
if (require_constexpr)
|
||||
{
|
||||
/* Types may not be defined in an exception-specification. */
|
||||
saved_message = parser->type_definition_forbidden_message;
|
||||
parser->type_definition_forbidden_message
|
||||
= G_("types may not be defined in an exception-specification");
|
||||
|
||||
expr = cp_parser_constant_expression (parser, false, NULL);
|
||||
|
||||
/* Restore the saved message. */
|
||||
parser->type_definition_forbidden_message = saved_message;
|
||||
}
|
||||
else
|
||||
{
|
||||
expr = cp_parser_expression (parser, false, NULL);
|
||||
*consumed_expr = true;
|
||||
}
|
||||
|
||||
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
||||
}
|
||||
else
|
||||
{
|
||||
expr = boolean_true_node;
|
||||
if (!require_constexpr)
|
||||
*consumed_expr = false;
|
||||
}
|
||||
|
||||
/* We cannot build a noexcept-spec right away because this will check
|
||||
that expr is a constexpr. */
|
||||
if (!return_cond)
|
||||
return build_noexcept_spec (expr, tf_warning_or_error);
|
||||
else
|
||||
return expr;
|
||||
}
|
||||
else
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Parse an (optional) exception-specification.
|
||||
|
||||
exception-specification:
|
||||
@ -19583,32 +19655,10 @@ cp_parser_exception_specification_opt (cp_parser* parser)
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
/* Is it a noexcept-specification? */
|
||||
if (cp_parser_is_keyword (token, RID_NOEXCEPT))
|
||||
{
|
||||
tree expr;
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
|
||||
{
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
/* Types may not be defined in an exception-specification. */
|
||||
saved_message = parser->type_definition_forbidden_message;
|
||||
parser->type_definition_forbidden_message
|
||||
= G_("types may not be defined in an exception-specification");
|
||||
|
||||
expr = cp_parser_constant_expression (parser, false, NULL);
|
||||
|
||||
/* Restore the saved message. */
|
||||
parser->type_definition_forbidden_message = saved_message;
|
||||
|
||||
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
||||
}
|
||||
else
|
||||
expr = boolean_true_node;
|
||||
|
||||
return build_noexcept_spec (expr, tf_warning_or_error);
|
||||
}
|
||||
type_id_list = cp_parser_noexcept_specification_opt(parser, true, NULL,
|
||||
false);
|
||||
if (type_id_list != NULL_TREE)
|
||||
return type_id_list;
|
||||
|
||||
/* If it's not `throw', then there's no exception-specification. */
|
||||
if (!cp_parser_is_keyword (token, RID_THROW))
|
||||
@ -26837,11 +26887,9 @@ cp_parser_txn_attribute_opt (cp_parser *parser)
|
||||
/* Parse a __transaction_atomic or __transaction_relaxed statement.
|
||||
|
||||
transaction-statement:
|
||||
__transaction_atomic txn-attribute[opt] txn-exception-spec[opt]
|
||||
__transaction_atomic txn-attribute[opt] txn-noexcept-spec[opt]
|
||||
compound-statement
|
||||
__transaction_relaxed txn-exception-spec[opt] compound-statement
|
||||
|
||||
??? The exception specification is not yet implemented.
|
||||
__transaction_relaxed txn-noexcept-spec[opt] compound-statement
|
||||
*/
|
||||
|
||||
static tree
|
||||
@ -26850,7 +26898,7 @@ cp_parser_transaction (cp_parser *parser, enum rid keyword)
|
||||
unsigned char old_in = parser->in_transaction;
|
||||
unsigned char this_in = 1, new_in;
|
||||
cp_token *token;
|
||||
tree stmt, attrs;
|
||||
tree stmt, attrs, noex;
|
||||
|
||||
gcc_assert (keyword == RID_TRANSACTION_ATOMIC
|
||||
|| keyword == RID_TRANSACTION_RELAXED);
|
||||
@ -26868,6 +26916,9 @@ cp_parser_transaction (cp_parser *parser, enum rid keyword)
|
||||
this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
|
||||
}
|
||||
|
||||
/* Parse a noexcept specification. */
|
||||
noex = cp_parser_noexcept_specification_opt (parser, true, NULL, true);
|
||||
|
||||
/* Keep track if we're in the lexical scope of an outer transaction. */
|
||||
new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
|
||||
|
||||
@ -26877,7 +26928,7 @@ cp_parser_transaction (cp_parser *parser, enum rid keyword)
|
||||
cp_parser_compound_statement (parser, NULL, false, false);
|
||||
parser->in_transaction = old_in;
|
||||
|
||||
finish_transaction_stmt (stmt, NULL, this_in);
|
||||
finish_transaction_stmt (stmt, NULL, this_in, noex);
|
||||
|
||||
return stmt;
|
||||
}
|
||||
@ -26885,10 +26936,8 @@ cp_parser_transaction (cp_parser *parser, enum rid keyword)
|
||||
/* Parse a __transaction_atomic or __transaction_relaxed expression.
|
||||
|
||||
transaction-expression:
|
||||
__transaction_atomic txn-exception-spec[opt] ( expression )
|
||||
__transaction_relaxed txn-exception-spec[opt] ( expression )
|
||||
|
||||
??? The exception specification is not yet implemented.
|
||||
__transaction_atomic txn-noexcept-spec[opt] ( expression )
|
||||
__transaction_relaxed txn-noexcept-spec[opt] ( expression )
|
||||
*/
|
||||
|
||||
static tree
|
||||
@ -26897,7 +26946,8 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword)
|
||||
unsigned char old_in = parser->in_transaction;
|
||||
unsigned char this_in = 1;
|
||||
cp_token *token;
|
||||
tree expr;
|
||||
tree expr, noex;
|
||||
bool noex_expr;
|
||||
|
||||
gcc_assert (keyword == RID_TRANSACTION_ATOMIC
|
||||
|| keyword == RID_TRANSACTION_RELAXED);
|
||||
@ -26917,14 +26967,36 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword)
|
||||
if (keyword == RID_TRANSACTION_RELAXED)
|
||||
this_in |= TM_STMT_ATTR_RELAXED;
|
||||
|
||||
/* Set this early. This might mean that we allow transaction_cancel in
|
||||
an expression that we find out later actually has to be a constexpr.
|
||||
However, we expect that cxx_constant_value will be able to deal with
|
||||
this; also, if the noexcept has no constexpr, then what we parse next
|
||||
really is a transaction's body. */
|
||||
parser->in_transaction = this_in;
|
||||
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
|
||||
|
||||
expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
|
||||
finish_parenthesized_expr (expr);
|
||||
expr = build_transaction_expr (token->location, expr, this_in);
|
||||
/* Parse a noexcept specification. */
|
||||
noex = cp_parser_noexcept_specification_opt (parser, false, &noex_expr,
|
||||
true);
|
||||
|
||||
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
||||
if (!noex || !noex_expr
|
||||
|| cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
|
||||
{
|
||||
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
|
||||
|
||||
expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
|
||||
finish_parenthesized_expr (expr);
|
||||
|
||||
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The only expression that is available got parsed for the noexcept
|
||||
already. noexcept is true then. */
|
||||
expr = noex;
|
||||
noex = boolean_true_node;
|
||||
}
|
||||
|
||||
expr = build_transaction_expr (token->location, expr, this_in, noex);
|
||||
parser->in_transaction = old_in;
|
||||
|
||||
if (cp_parser_non_integral_constant_expression (parser, NIC_TRANSACTION))
|
||||
@ -26980,7 +27052,7 @@ cp_parser_function_transaction (cp_parser *parser, enum rid keyword)
|
||||
|
||||
parser->in_transaction = old_in;
|
||||
|
||||
finish_transaction_stmt (stmt, compound_stmt, new_in);
|
||||
finish_transaction_stmt (stmt, compound_stmt, new_in, NULL_TREE);
|
||||
|
||||
return ctor_initializer_p;
|
||||
}
|
||||
|
15
gcc/cp/pt.c
15
gcc/cp/pt.c
@ -13246,15 +13246,24 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
|
||||
|
||||
if (TRANSACTION_EXPR_IS_STMT (t))
|
||||
{
|
||||
tree body = TRANSACTION_EXPR_BODY (t);
|
||||
tree noex = NULL_TREE;
|
||||
if (TREE_CODE (body) == MUST_NOT_THROW_EXPR)
|
||||
{
|
||||
noex = MUST_NOT_THROW_COND (body);
|
||||
if (noex == NULL_TREE)
|
||||
noex = boolean_true_node;
|
||||
body = TREE_OPERAND (body, 0);
|
||||
}
|
||||
stmt = begin_transaction_stmt (input_location, NULL, flags);
|
||||
RECUR (TRANSACTION_EXPR_BODY (t));
|
||||
finish_transaction_stmt (stmt, NULL, flags);
|
||||
RECUR (body);
|
||||
finish_transaction_stmt (stmt, NULL, flags, RECUR (noex));
|
||||
}
|
||||
else
|
||||
{
|
||||
stmt = build_transaction_expr (EXPR_LOCATION (t),
|
||||
RECUR (TRANSACTION_EXPR_BODY (t)),
|
||||
flags);
|
||||
flags, NULL_TREE);
|
||||
return stmt;
|
||||
}
|
||||
}
|
||||
|
@ -5020,27 +5020,47 @@ begin_transaction_stmt (location_t loc, tree *pcompound, int flags)
|
||||
|
||||
/* End a __transaction_atomic or __transaction_relaxed statement.
|
||||
If COMPOUND_STMT is non-null, this is for a function-transaction-block,
|
||||
and we should end the compound. */
|
||||
and we should end the compound. If NOEX is non-NULL, we wrap the body in
|
||||
a MUST_NOT_THROW_EXPR with NOEX as condition. */
|
||||
|
||||
void
|
||||
finish_transaction_stmt (tree stmt, tree compound_stmt, int flags)
|
||||
finish_transaction_stmt (tree stmt, tree compound_stmt, int flags, tree noex)
|
||||
{
|
||||
TRANSACTION_EXPR_BODY (stmt) = pop_stmt_list (TRANSACTION_EXPR_BODY (stmt));
|
||||
TRANSACTION_EXPR_OUTER (stmt) = (flags & TM_STMT_ATTR_OUTER) != 0;
|
||||
TRANSACTION_EXPR_RELAXED (stmt) = (flags & TM_STMT_ATTR_RELAXED) != 0;
|
||||
TRANSACTION_EXPR_IS_STMT (stmt) = 1;
|
||||
|
||||
/* noexcept specifications are not allowed for function transactions. */
|
||||
gcc_assert (!(noex && compound_stmt));
|
||||
if (noex)
|
||||
{
|
||||
tree body = build_must_not_throw_expr (TRANSACTION_EXPR_BODY (stmt),
|
||||
noex);
|
||||
SET_EXPR_LOCATION (body, EXPR_LOCATION (TRANSACTION_EXPR_BODY (stmt)));
|
||||
TREE_SIDE_EFFECTS (body) = 1;
|
||||
TRANSACTION_EXPR_BODY (stmt) = body;
|
||||
}
|
||||
|
||||
if (compound_stmt)
|
||||
finish_compound_stmt (compound_stmt);
|
||||
finish_stmt ();
|
||||
}
|
||||
|
||||
/* Build a __transaction_atomic or __transaction_relaxed expression. */
|
||||
/* Build a __transaction_atomic or __transaction_relaxed expression. If
|
||||
NOEX is non-NULL, we wrap the body in a MUST_NOT_THROW_EXPR with NOEX as
|
||||
condition. */
|
||||
|
||||
tree
|
||||
build_transaction_expr (location_t loc, tree expr, int flags)
|
||||
build_transaction_expr (location_t loc, tree expr, int flags, tree noex)
|
||||
{
|
||||
tree ret;
|
||||
if (noex)
|
||||
{
|
||||
expr = build_must_not_throw_expr (expr, noex);
|
||||
SET_EXPR_LOCATION (expr, loc);
|
||||
TREE_SIDE_EFFECTS (expr) = 1;
|
||||
}
|
||||
ret = build1 (TRANSACTION_EXPR, TREE_TYPE (expr), expr);
|
||||
if (flags & TM_STMT_ATTR_RELAXED)
|
||||
TRANSACTION_EXPR_RELAXED (ret) = 1;
|
||||
|
@ -1,3 +1,11 @@
|
||||
2011-12-12 Torvald Riegel <triegel@redhat.com>
|
||||
|
||||
* g++.dg/tm/noexcept-1.C: New test.
|
||||
* g++.dg/tm/noexcept-2.C: New test.
|
||||
* g++.dg/tm/noexcept-3.C: New test.
|
||||
* g++.dg/tm/noexcept-4.C: New test.
|
||||
* g++.dg/tm/noexcept-5.C: New test.
|
||||
|
||||
2011-12-12 Torvald Riegel <triegel@redhat.com>
|
||||
|
||||
* c-c++-common/tm/20111206.c: New test.
|
||||
|
38
gcc/testsuite/g++.dg/tm/noexcept-1.C
Normal file
38
gcc/testsuite/g++.dg/tm/noexcept-1.C
Normal file
@ -0,0 +1,38 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fgnu-tm -O -std=c++0x -fdump-tree-tmmark -fdump-tree-tmlower" }
|
||||
|
||||
struct TrueFalse
|
||||
{
|
||||
static constexpr bool v() { return true; }
|
||||
};
|
||||
|
||||
int global;
|
||||
|
||||
template<typename T> int foo()
|
||||
{
|
||||
__transaction_atomic noexcept(T::v()) { global += 1; }
|
||||
return __transaction_atomic noexcept(T::v()) (global + 2);
|
||||
}
|
||||
|
||||
int f1()
|
||||
{
|
||||
return foo<TrueFalse>();
|
||||
}
|
||||
|
||||
int f2()
|
||||
{
|
||||
return __transaction_atomic noexcept(true) (global + 3)
|
||||
+ __transaction_atomic noexcept(TrueFalse::v()) (global + 4);
|
||||
}
|
||||
|
||||
int f3()
|
||||
{
|
||||
__transaction_atomic noexcept(true) { global += 5; }
|
||||
__transaction_atomic noexcept(TrueFalse::v()) { global += 6; }
|
||||
return global;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 6 "tmlower" } } */
|
||||
/* { dg-final { scan-tree-dump-times "ITM_RU" 6 "tmmark" } } */
|
||||
/* { dg-final { cleanup-tree-dump "tmmark" } } */
|
||||
/* { dg-final { cleanup-tree-dump "tmlower" } } */
|
20
gcc/testsuite/g++.dg/tm/noexcept-2.C
Normal file
20
gcc/testsuite/g++.dg/tm/noexcept-2.C
Normal file
@ -0,0 +1,20 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fgnu-tm -std=c++0x" }
|
||||
|
||||
// All of these must fail, because they are not constant expressions.
|
||||
template<typename T> int foo(int x, T t)
|
||||
{
|
||||
__transaction_atomic noexcept(t) { x++; } /* { dg-error "not a constant" } */
|
||||
return __transaction_atomic noexcept(t) (x+1); /* { dg-error "not a constant" } */
|
||||
}
|
||||
|
||||
int bar(int x)
|
||||
{
|
||||
__transaction_atomic noexcept(x == 23) { x++; } /* { dg-error "not a constant" } */
|
||||
return __transaction_atomic noexcept(x == 42) (x+1); /* { dg-error "not a constant" } */
|
||||
}
|
||||
|
||||
int f(int x)
|
||||
{
|
||||
return foo<bool>(x, true);
|
||||
}
|
40
gcc/testsuite/g++.dg/tm/noexcept-3.C
Normal file
40
gcc/testsuite/g++.dg/tm/noexcept-3.C
Normal file
@ -0,0 +1,40 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fgnu-tm -O -std=c++0x -fdump-tree-tmmark -fdump-tree-tmlower" }
|
||||
|
||||
// Same as noexcept-1.C but all noexcepts are false.
|
||||
|
||||
struct TrueFalse
|
||||
{
|
||||
static constexpr bool v() { return false; }
|
||||
};
|
||||
|
||||
int global;
|
||||
|
||||
template<typename T> int foo()
|
||||
{
|
||||
__transaction_atomic noexcept(T::v()) { global += 1; }
|
||||
return __transaction_atomic noexcept(T::v()) (global + 2);
|
||||
}
|
||||
|
||||
int f1()
|
||||
{
|
||||
return foo<TrueFalse>();
|
||||
}
|
||||
|
||||
int f2()
|
||||
{
|
||||
return __transaction_atomic noexcept(false) (global + 3)
|
||||
+ __transaction_atomic noexcept(TrueFalse::v()) (global + 4);
|
||||
}
|
||||
|
||||
int f3()
|
||||
{
|
||||
__transaction_atomic noexcept(false) { global += 5; }
|
||||
__transaction_atomic noexcept(TrueFalse::v()) { global += 6; }
|
||||
return global;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 0 "tmlower" } } */
|
||||
/* { dg-final { scan-tree-dump-times "ITM_RU" 6 "tmmark" } } */
|
||||
/* { dg-final { cleanup-tree-dump "tmmark" } } */
|
||||
/* { dg-final { cleanup-tree-dump "tmlower" } } */
|
35
gcc/testsuite/g++.dg/tm/noexcept-4.C
Normal file
35
gcc/testsuite/g++.dg/tm/noexcept-4.C
Normal file
@ -0,0 +1,35 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fgnu-tm -O -std=c++0x -fdump-tree-tmmark -fdump-tree-tmlower" }
|
||||
|
||||
// Similar to noexcept-1.C but without an explicit (true) for noexcept.
|
||||
|
||||
struct TrueFalse
|
||||
{
|
||||
static constexpr bool v() { return true; }
|
||||
};
|
||||
|
||||
int global;
|
||||
|
||||
template<typename T> int foo()
|
||||
{
|
||||
__transaction_atomic noexcept { global += 1; }
|
||||
return __transaction_atomic noexcept (global + 2)
|
||||
+ __transaction_atomic noexcept (global + 3);
|
||||
}
|
||||
|
||||
int f1()
|
||||
{
|
||||
return foo<TrueFalse>();
|
||||
}
|
||||
|
||||
int f3()
|
||||
{
|
||||
__transaction_atomic noexcept { global += 4; }
|
||||
return __transaction_atomic noexcept (global + 5)
|
||||
+ __transaction_atomic noexcept (global + 6);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 6 "tmlower" } } */
|
||||
/* { dg-final { scan-tree-dump-times "ITM_RU" 6 "tmmark" } } */
|
||||
/* { dg-final { cleanup-tree-dump "tmmark" } } */
|
||||
/* { dg-final { cleanup-tree-dump "tmlower" } } */
|
21
gcc/testsuite/g++.dg/tm/noexcept-5.C
Normal file
21
gcc/testsuite/g++.dg/tm/noexcept-5.C
Normal file
@ -0,0 +1,21 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fgnu-tm -O -std=c++0x -fdump-tree-tmmark -fdump-tree-tmlower" }
|
||||
|
||||
int global;
|
||||
|
||||
void f2(int x)
|
||||
{
|
||||
__transaction_atomic
|
||||
{
|
||||
__transaction_atomic noexcept(true)
|
||||
{
|
||||
global += 1;
|
||||
if (x)
|
||||
throw 23;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 1 "tmlower" } } */
|
||||
/* { dg-final { scan-tree-dump-times "ITM_RU" 1 "tmmark" } } */
|
||||
/* { dg-final { cleanup-tree-dump "tmmark" } } */
|
||||
/* { dg-final { cleanup-tree-dump "tmlower" } } */
|
Loading…
x
Reference in New Issue
Block a user