Jason, all the compiler changes (including C++) are in a separate post:
http://gcc.gnu.org/ml/gcc-patches/2011-11/msg00380.html
If you would prefer, I can reply to this message and provide the C++
changelog entries separately.
Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c (.../trunk) (revision 180744)
+++ gcc/cp/class.c (.../branches/transactional-memory) (revision
180773)
@@ -1227,13 +1227,12 @@ check_bases (tree t,
int* no_const_asn_ref_p)
{
int i;
- int seen_non_virtual_nearly_empty_base_p;
+ bool seen_non_virtual_nearly_empty_base_p = 0;
+ int seen_tm_mask = 0;
tree base_binfo;
tree binfo;
tree field = NULL_TREE;
- seen_non_virtual_nearly_empty_base_p = 0;
-
if (!CLASSTYPE_NON_STD_LAYOUT (t))
for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
@@ -1338,6 +1337,23 @@ check_bases (tree t,
break;
}
}
+
+ /* Don't bother collecting tm attributes if transactional memory
+ support is not enabled. */
+ if (flag_tm)
+ {
+ tree tm_attr = find_tm_attribute (TYPE_ATTRIBUTES (basetype));
+ if (tm_attr)
+ seen_tm_mask |= tm_attr_to_mask (tm_attr);
+ }
+ }
+
+ /* If one of the base classes had TM attributes, and the current class
+ doesn't define its own, then the current class inherits one. */
+ if (seen_tm_mask && !find_tm_attribute (TYPE_ATTRIBUTES (t)))
+ {
+ tree tm_attr = tm_mask_to_attr (seen_tm_mask & -seen_tm_mask);
+ TYPE_ATTRIBUTES (t) = tree_cons (tm_attr, NULL, TYPE_ATTRIBUTES (t));
}
}
@@ -4252,6 +4268,137 @@ clone_constructors_and_destructors (tree
clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
}
+/* Subroutine of set_one_vmethod_tm_attributes. Search base classes
+ of TYPE for virtual functions which FNDECL overrides. Return a
+ mask of the tm attributes found therein. */
+
+static int
+look_for_tm_attr_overrides (tree type, tree fndecl)
+{
+ tree binfo = TYPE_BINFO (type);
+ tree base_binfo;
+ int ix, found = 0;
+
+ for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ++ix)
+ {
+ tree o, basetype = BINFO_TYPE (base_binfo);
+
+ if (!TYPE_POLYMORPHIC_P (basetype))
+ continue;
+
+ o = look_for_overrides_here (basetype, fndecl);
+ if (o)
+ found |= tm_attr_to_mask (find_tm_attribute
+ (TYPE_ATTRIBUTES (TREE_TYPE (o))));
+ else
+ found |= look_for_tm_attr_overrides (basetype, fndecl);
+ }
+
+ return found;
+}
+
+/* Subroutine of set_method_tm_attributes. Handle the checks and
+ inheritance for one virtual method FNDECL. */
+
+static void
+set_one_vmethod_tm_attributes (tree type, tree fndecl)
+{
+ tree tm_attr;
+ int found, have;
+
+ found = look_for_tm_attr_overrides (type, fndecl);
+
+ /* If FNDECL doesn't actually override anything (i.e. T is the
+ class that first declares FNDECL virtual), then we're done. */
+ if (found == 0)
+ return;
+
+ tm_attr = find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl)));
+ have = tm_attr_to_mask (tm_attr);
+
+ /* Intel STM Language Extension 3.0, Section 4.2 table 4:
+ tm_pure must match exactly, otherwise no weakening of
+ tm_safe > tm_callable > nothing. */
+ /* ??? The tm_pure attribute didn't make the transition to the
+ multivendor language spec. */
+ if (have == TM_ATTR_PURE)
+ {
+ if (found != TM_ATTR_PURE)
+ {
+ found &= -found;
+ goto err_override;
+ }
+ }
+ /* If the overridden function is tm_pure, then FNDECL must be. */
+ else if (found == TM_ATTR_PURE && tm_attr)
+ goto err_override;
+ /* Look for base class combinations that cannot be satisfied. */
+ else if (found != TM_ATTR_PURE && (found & TM_ATTR_PURE))
+ {
+ found &= ~TM_ATTR_PURE;
+ found &= -found;
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "method overrides both %<transaction_pure%> and %qE methods",
+ tm_mask_to_attr (found));
+ }
+ /* If FNDECL did not declare an attribute, then inherit the most
+ restrictive one. */
+ else if (tm_attr == NULL)
+ {
+ apply_tm_attr (fndecl, tm_mask_to_attr (found & -found));
+ }
+ /* Otherwise validate that we're not weaker than a function
+ that is being overridden. */
+ else
+ {
+ found &= -found;
+ if (found <= TM_ATTR_CALLABLE && have > found)
+ goto err_override;
+ }
+ return;
+
+ err_override:
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "method declared %qE overriding %qE method",
+ tm_attr, tm_mask_to_attr (found));
+}
+
+/* For each of the methods in T, propagate a class-level tm attribute. */
+
+static void
+set_method_tm_attributes (tree t)
+{
+ tree class_tm_attr, fndecl;
+
+ /* Don't bother collecting tm attributes if transactional memory
+ support is not enabled. */
+ if (!flag_tm)
+ return;
+
+ /* Process virtual methods first, as they inherit directly from the
+ base virtual function and also require validation of new
attributes. */
+ if (TYPE_CONTAINS_VPTR_P (t))
+ {
+ tree vchain;
+ for (vchain = BINFO_VIRTUALS (TYPE_BINFO (t)); vchain;
+ vchain = TREE_CHAIN (vchain))
+ set_one_vmethod_tm_attributes (t, BV_FN (vchain));
+ }
+
+ /* If the class doesn't have an attribute, nothing more to do. */
+ class_tm_attr = find_tm_attribute (TYPE_ATTRIBUTES (t));
+ if (class_tm_attr == NULL)
+ return;
+
+ /* Any method that does not yet have a tm attribute inherits
+ the one from the class. */
+ for (fndecl = TYPE_METHODS (t); fndecl; fndecl = TREE_CHAIN (fndecl))
+ {
+ if (!find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
+ apply_tm_attr (fndecl, class_tm_attr);
+ }
+}
+
/* Returns true iff class T has a user-defined constructor other than
the default constructor. */
@@ -5835,6 +5982,7 @@ finish_struct_1 (tree t)
}
finish_struct_bits (t);
+ set_method_tm_attributes (t);
/* Complete the rtl for any static member objects of the type we're
working on. */
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c (.../trunk) (revision 180744)
+++ gcc/cp/decl.c (.../branches/transactional-memory) (revision
180773)
@@ -4001,6 +4001,8 @@ push_cp_library_fn (enum tree_code opera
operator_code,
type);
pushdecl (fn);
+ if (flag_tm)
+ apply_tm_attr (fn, get_identifier ("transaction_safe"));
return fn;
}
Index: gcc/cp/except.c
===================================================================
--- gcc/cp/except.c (.../trunk) (revision 180744)
+++ gcc/cp/except.c (.../branches/transactional-memory) (revision
180773)
@@ -173,6 +173,9 @@ do_get_exception_ptr (void)
{
/* Declare void* __cxa_get_exception_ptr (void *) throw(). */
fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
+
+ if (flag_tm)
+ apply_tm_attr (fn, get_identifier ("transaction_pure"));
}
return cp_build_function_call_nary (fn, tf_warning_or_error,
@@ -192,6 +195,17 @@ do_begin_catch (void)
{
/* Declare void* __cxa_begin_catch (void *) throw(). */
fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
+
+ /* Create its transactional-memory equivalent. */
+ if (flag_tm)
+ {
+ tree fn2 = get_identifier ("_ITM_cxa_begin_catch");
+ if (!get_global_value_if_present (fn2, &fn2))
+ fn2 = declare_nothrow_library_fn (fn2, ptr_type_node,
+ ptr_type_node);
+ apply_tm_attr (fn2, get_identifier ("transaction_pure"));
+ record_tm_replacement (fn, fn2);
+ }
}
return cp_build_function_call_nary (fn, tf_warning_or_error,
@@ -231,6 +245,19 @@ do_end_catch (tree type)
fn = push_void_library_fn (fn, void_list_node);
/* This can throw if the destructor for the exception throws. */
TREE_NOTHROW (fn) = 0;
+
+ /* Create its transactional-memory equivalent. */
+ if (flag_tm)
+ {
+ tree fn2 = get_identifier ("_ITM_cxa_end_catch");
+ if (!get_global_value_if_present (fn2, &fn2))
+ {
+ fn2 = push_void_library_fn (fn2, void_list_node);
+ TREE_NOTHROW (fn2) = 0;
+ }
+ apply_tm_attr (fn2, get_identifier ("transaction_pure"));
+ record_tm_replacement (fn, fn2);
+ }
}
cleanup = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
@@ -581,6 +608,16 @@ do_allocate_exception (tree type)
{
/* Declare void *__cxa_allocate_exception(size_t) throw(). */
fn = declare_nothrow_library_fn (fn, ptr_type_node, size_type_node);
+
+ if (flag_tm)
+ {
+ tree fn2 = get_identifier ("_ITM_cxa_allocate_exception");
+ if (!get_global_value_if_present (fn2, &fn2))
+ fn2 = declare_nothrow_library_fn (fn2, ptr_type_node,
+ size_type_node);
+ apply_tm_attr (fn2, get_identifier ("transaction_pure"));
+ record_tm_replacement (fn, fn2);
+ }
}
return cp_build_function_call_nary (fn, tf_warning_or_error,
@@ -712,6 +749,15 @@ build_throw (tree exp)
ptr_type_node, ptr_type_node,
cleanup_type, NULL_TREE);
fn = push_throw_library_fn (fn, tmp);
+
+ if (flag_tm)
+ {
+ tree fn2 = get_identifier ("_ITM_cxa_throw");
+ if (!get_global_value_if_present (fn2, &fn2))
+ fn2 = push_throw_library_fn (fn2, tmp);
+ apply_tm_attr (fn2, get_identifier ("transaction_pure"));
+ record_tm_replacement (fn, fn2);
+ }
}
/* [except.throw]
@@ -831,6 +877,9 @@ build_throw (tree exp)
(fn, build_function_type_list (void_type_node, NULL_TREE));
}
+ if (flag_tm)
+ apply_tm_attr (fn, get_identifier ("transaction_pure"));
+
/* ??? Indicate that this function call allows exceptions of the
type
of the enclosing catch block (if known). */
exp = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (.../trunk) (revision 180744)
+++ gcc/cp/pt.c (.../branches/transactional-memory) (revision 180773)
@@ -12952,6 +12952,18 @@ tsubst_expr (tree t, tree args, tsubst_f
}
break;
+ case TRANSACTION_EXPR:
+ {
+ int flags = 0;
+ flags |= (TRANSACTION_EXPR_OUTER (t) ? TM_STMT_ATTR_OUTER : 0);
+ flags |= (TRANSACTION_EXPR_RELAXED (t) ? TM_STMT_ATTR_RELAXED : 0);
+
+ stmt = begin_transaction_stmt (input_location, NULL, flags);
+ tmp = RECUR (TRANSACTION_EXPR_BODY (t));
+ finish_transaction_stmt (stmt, NULL, flags);
+ }
+ break;
+
case EXPR_PACK_EXPANSION:
error ("invalid use of pack expansion expression");
return error_mark_node;
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c (.../trunk) (revision 180744)
+++ gcc/cp/semantics.c (.../branches/transactional-memory) (revision
180773)
@@ -4965,6 +4965,50 @@ finish_omp_taskyield (void)
finish_expr_stmt (stmt);
}
+/* Begin a __transaction_atomic or __transaction_relaxed statement.
+ If PCOMPOUND is non-null, this is for a function-transaction-block,
and we
+ should create an extra compound stmt. */
+
+tree
+begin_transaction_stmt (location_t loc, tree *pcompound, int flags)
+{
+ tree r;
+
+ if (pcompound)
+ *pcompound = begin_compound_stmt (0);
+
+ r = build_stmt (loc, TRANSACTION_EXPR, NULL_TREE);
+
+ /* Only add the statement to the function if support enabled. */
+ if (flag_tm)
+ add_stmt (r);
+ else
+ error_at (loc, ((flags & TM_STMT_ATTR_RELAXED) != 0 ?
+ "%<__transaction_relaxed%> without transactional memory "
+ "support enabled"
+ : "%<__transaction_atomic%> without transactional memory "
+ "support enabled"));
+
+ TRANSACTION_EXPR_BODY (r) = push_stmt_list ();
+ return r;
+}
+
+/* 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. */
+
+void
+finish_transaction_stmt (tree stmt, tree compound_stmt, int flags)
+{
+ 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;
+
+ if (compound_stmt)
+ finish_compound_stmt (compound_stmt);
+ finish_stmt ();
+}
+
void
init_cp_semantics (void)
{
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c (.../trunk) (revision 180744)
+++ gcc/cp/parser.c (.../branches/transactional-memory) (revision
180773)
@@ -172,6 +172,10 @@ typedef enum required_token {
RT_JUMP, /* jump-statement */
RT_CLASS_KEY, /* class-key */
RT_CLASS_TYPENAME_TEMPLATE /* class, typename, or template */
+
+ , RT_TRANSACTION_ATOMIC, /* __transaction_atomic */
+ RT_TRANSACTION_RELAXED, /* __transaction_relaxed */
+ RT_TRANSACTION_CANCEL /* __transaction_cancel */
} required_token;
/* Prototypes. */
@@ -2104,6 +2108,17 @@ static bool cp_parser_extension_opt
static void cp_parser_label_declaration
(cp_parser *);
+/* Transactional Memory Extensions */
+
+static tree cp_parser_transaction
+ (cp_parser *, enum rid);
+static tree cp_parser_transaction_expression
+ (cp_parser *, enum rid);
+static bool cp_parser_function_transaction
+ (cp_parser *, enum rid);
+static tree cp_parser_transaction_cancel
+ (cp_parser *);
+
enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
static bool cp_parser_pragma
(cp_parser *, enum pragma_context);
@@ -6362,6 +6377,10 @@ cp_parser_unary_expression (cp_parser *p
}
break;
+ case RID_TRANSACTION_ATOMIC:
+ case RID_TRANSACTION_RELAXED:
+ return cp_parser_transaction_expression (parser, keyword);
+
case RID_NOEXCEPT:
{
tree expr;
@@ -8496,6 +8515,11 @@ cp_parser_lambda_body (cp_parser* parser
declaration-statement
try-block
+ TM Extension:
+
+ statement:
+ atomic-statement
+
IN_COMPOUND is true when the statement is nested inside a
cp_parser_compound_statement; this matters for certain pragmas.
@@ -8572,6 +8596,14 @@ cp_parser_statement (cp_parser* parser,
cp_parser_declaration_statement (parser);
return;
+ case RID_TRANSACTION_ATOMIC:
+ case RID_TRANSACTION_RELAXED:
+ statement = cp_parser_transaction (parser, keyword);
+ break;
+ case RID_TRANSACTION_CANCEL:
+ statement = cp_parser_transaction_cancel (parser);
+ break;
+
default:
/* It might be a keyword like `int' that can start a
declaration-statement. */
@@ -15082,6 +15114,11 @@ cp_parser_asm_definition (cp_parser* par
function-definition:
__extension__ function-definition
+ TM Extension:
+
+ function-definition:
+ decl-specifier-seq [opt] declarator function-atomic-block
+
The DECL_SPECIFIERS apply to this declarator. Returns a
representation of the entity declared. If MEMBER_P is TRUE, then
this declarator appears in a class scope. The new DECL created by
@@ -20780,12 +20817,19 @@ cp_parser_function_definition_after_decl
start_lambda_scope (current_function_decl);
- /* If the next token is `try', then we are looking at a
- function-try-block. */
- if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY))
+ /* If the next token is `try', `__transaction_atomic', or
+ `__transaction_relaxed`, then we are looking at either
function-try-block
+ or function-transaction-block. Note that all of these include the
+ function-body. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer,
RID_TRANSACTION_ATOMIC))
+ ctor_initializer_p = cp_parser_function_transaction (parser,
+ RID_TRANSACTION_ATOMIC);
+ else if (cp_lexer_next_token_is_keyword (parser->lexer,
+ RID_TRANSACTION_RELAXED))
+ ctor_initializer_p = cp_parser_function_transaction (parser,
+ RID_TRANSACTION_RELAXED);
+ else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY))
ctor_initializer_p = cp_parser_function_try_block (parser);
- /* A function-try-block includes the function-body, so we only do
- this next part if we're not processing a function-try-block. */
else
ctor_initializer_p
= cp_parser_ctor_initializer_opt_and_function_body (parser);
@@ -21939,6 +21983,12 @@ cp_parser_required_error (cp_parser *par
case RT_AT_THROW:
cp_parser_error (parser, "expected %<@throw%>");
return;
+ case RT_TRANSACTION_ATOMIC:
+ cp_parser_error (parser, "expected %<__transaction_atomic%>");
+ return;
+ case RT_TRANSACTION_RELAXED:
+ cp_parser_error (parser, "expected %<__transaction_relaxed%>");
+ return;
default:
break;
}
@@ -22169,6 +22219,10 @@ cp_parser_token_starts_function_definiti
|| token->type == CPP_COLON
/* A function-try-block begins with `try'. */
|| token->keyword == RID_TRY
+ /* A function-transaction-block begins with `__transaction_atomic'
+ or `__transaction_relaxed'. */
+ || token->keyword == RID_TRANSACTION_ATOMIC
+ || token->keyword == RID_TRANSACTION_RELAXED
/* The named return value extension begins with `return'. */
|| token->keyword == RID_RETURN);
}
@@ -26489,6 +26543,270 @@ cp_parser_omp_construct (cp_parser *pars
SET_EXPR_LOCATION (stmt, pragma_tok->location);
}
+/* Transactional Memory parsing routines. */
+
+/* Parse a transaction attribute.
+
+ txn-attribute:
+ attribute
+ [ [ identifier ] ]
+
+ ??? Simplify this when C++0x bracket attributes are
+ implemented properly. */
+
+static tree
+cp_parser_txn_attribute_opt (cp_parser *parser)
+{
+ cp_token *token;
+ tree attr_name, attr = NULL;
+
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+ return cp_parser_attributes_opt (parser);
+
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_SQUARE))
+ return NULL_TREE;
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE))
+ goto error1;
+
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_NAME || token->type == CPP_KEYWORD)
+ {
+ token = cp_lexer_consume_token (parser->lexer);
+
+ attr_name = (token->type == CPP_KEYWORD
+ /* For keywords, use the canonical spelling,
+ not the parsed identifier. */
+ ? ridpointers[(int) token->keyword]
+ : token->u.value);
+ attr = build_tree_list (attr_name, NULL_TREE);
+ }
+ else
+ cp_parser_error (parser, "expected identifier");
+
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+ error1:
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+ return attr;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed statement.
+
+ transaction-statement:
+ __transaction_atomic txn-attribute[opt] txn-exception-spec[opt]
+ compound-statement
+ __transaction_relaxed txn-exception-spec[opt] compound-statement
+
+ ??? The exception specification is not yet implemented.
+*/
+
+static tree
+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;
+
+ gcc_assert (keyword == RID_TRANSACTION_ATOMIC
+ || keyword == RID_TRANSACTION_RELAXED);
+ token = cp_parser_require_keyword (parser, keyword,
+ (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC
+ : RT_TRANSACTION_RELAXED));
+ gcc_assert (token != NULL);
+
+ if (keyword == RID_TRANSACTION_RELAXED)
+ this_in |= TM_STMT_ATTR_RELAXED;
+ else
+ {
+ attrs = cp_parser_txn_attribute_opt (parser);
+ if (attrs)
+ this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
+ }
+
+ /* Keep track if we're in the lexical scope of an outer transaction. */
+ new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
+
+ stmt = begin_transaction_stmt (token->location, NULL, this_in);
+
+ parser->in_transaction = new_in;
+ cp_parser_compound_statement (parser, NULL, false, false);
+ parser->in_transaction = old_in;
+
+ finish_transaction_stmt (stmt, NULL, this_in);
+
+ return stmt;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed expression.
+
+ transaction-expression:
+ __transaction_atomic txn-exception-spec[opt] compound-statement
+ __transaction_relaxed txn-exception-spec[opt] compound-statement
+
+ ??? The exception specification is not yet implemented.
+*/
+
+static tree
+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 ret, attrs;
+
+ gcc_assert (keyword == RID_TRANSACTION_ATOMIC
+ || keyword == RID_TRANSACTION_RELAXED);
+ token = cp_parser_require_keyword (parser, keyword,
+ (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC
+ : RT_TRANSACTION_RELAXED));
+ gcc_assert (token != NULL);
+
+ if (keyword == RID_TRANSACTION_RELAXED)
+ this_in |= TM_STMT_ATTR_RELAXED;
+ else
+ {
+ attrs = cp_parser_txn_attribute_opt (parser);
+ if (attrs)
+ this_in |= parse_tm_stmt_attr (attrs, 0);
+ }
+
+ parser->in_transaction = this_in;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ tree expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ ret = build1 (TRANSACTION_EXPR, TREE_TYPE (expr), expr);
+ if (this_in & TM_STMT_ATTR_RELAXED)
+ TRANSACTION_EXPR_RELAXED (ret) = 1;
+ SET_EXPR_LOCATION (ret, token->location);
+ }
+ else
+ {
+ cp_parser_error (parser, "expected %<(%>");
+ ret = error_mark_node;
+ }
+ parser->in_transaction = old_in;
+
+ return ret;
+}
+
+/* Parse a function-transaction-block.
+
+ function-transaction-block:
+ __transaction_atomic txn-attribute[opt] ctor-initializer[opt]
+ function-body
+ __transaction_atomic txn-attribute[opt] function-try-block
+ __transaction_relaxed ctor-initializer[opt] function-body
+ __transaction_relaxed function-try-block
+*/
+
+static bool
+cp_parser_function_transaction (cp_parser *parser, enum rid keyword)
+{
+ unsigned char old_in = parser->in_transaction;
+ unsigned char new_in = 1;
+ tree compound_stmt, stmt, attrs;
+ bool ctor_initializer_p;
+ cp_token *token;
+
+ gcc_assert (keyword == RID_TRANSACTION_ATOMIC
+ || keyword == RID_TRANSACTION_RELAXED);
+ token = cp_parser_require_keyword (parser, keyword,
+ (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC
+ : RT_TRANSACTION_RELAXED));
+ gcc_assert (token != NULL);
+
+ if (keyword == RID_TRANSACTION_RELAXED)
+ new_in |= TM_STMT_ATTR_RELAXED;
+ else
+ {
+ attrs = cp_parser_txn_attribute_opt (parser);
+ if (attrs)
+ new_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
+ }
+
+ stmt = begin_transaction_stmt (token->location, &compound_stmt, new_in);
+
+ parser->in_transaction = new_in;
+
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY))
+ ctor_initializer_p = cp_parser_function_try_block (parser);
+ else
+ ctor_initializer_p
+ = cp_parser_ctor_initializer_opt_and_function_body (parser);
+
+ parser->in_transaction = old_in;
+
+ finish_transaction_stmt (stmt, compound_stmt, new_in);
+
+ return ctor_initializer_p;
+}
+
+/* Parse a __transaction_cancel statement.
+
+ cancel-statement:
+ __transaction_cancel txn-attribute[opt] ;
+ __transaction_cancel txn-attribute[opt] throw-expression ;
+
+ ??? Cancel and throw is not yet implemented. */
+
+static tree
+cp_parser_transaction_cancel (cp_parser *parser)
+{
+ cp_token *token;
+ bool is_outer = false;
+ tree stmt, attrs;
+
+ token = cp_parser_require_keyword (parser, RID_TRANSACTION_CANCEL,
+ RT_TRANSACTION_CANCEL);
+ gcc_assert (token != NULL);
+
+ attrs = cp_parser_txn_attribute_opt (parser);
+ if (attrs)
+ is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
+
+ /* ??? Parse cancel-and-throw here. */
+
+ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+
+ if (!flag_tm)
+ {
+ error_at (token->location, "%<__transaction_cancel%> without "
+ "transactional memory support enabled");
+ return error_mark_node;
+ }
+ else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
+ {
+ error_at (token->location, "%<__transaction_cancel%> within a "
+ "%<__transaction_relaxed%>");
+ return error_mark_node;
+ }
+ else if (is_outer)
+ {
+ if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
+ && !is_tm_may_cancel_outer (current_function_decl))
+ {
+ error_at (token->location, "outer %<__transaction_cancel%> not "
+ "within outer %<__transaction_atomic%>");
+ error_at (token->location,
+ " or a %<transaction_may_cancel_outer%> function");
+ return error_mark_node;
+ }
+ }
+ else if (parser->in_transaction == 0)
+ {
+ error_at (token->location, "%<__transaction_cancel%> not within "
+ "%<__transaction_atomic%>");
+ return error_mark_node;
+ }
+
+ stmt = build_tm_abort_call (token->location, is_outer);
+ add_stmt (stmt);
+ finish_stmt ();
+
+ return stmt;
+}
+
/* The parser. */
static GTY (()) cp_parser *the_parser;
Index: gcc/cp/parser.h
===================================================================
--- gcc/cp/parser.h (.../trunk) (revision 180744)
+++ gcc/cp/parser.h (.../branches/transactional-memory) (revision
180773)
@@ -329,6 +329,10 @@ typedef struct GTY(()) cp_parser {
a local class. */
bool in_function_body;
+ /* Nonzero if we're processing a __transaction_atomic or
+ __transaction_relaxed statement. */
+ unsigned char in_transaction;
+
/* TRUE if we can auto-correct a colon to a scope operator. */
bool colon_corrects_to_scope_p;
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c (.../trunk) (revision 180744)
+++ gcc/cp/call.c (.../branches/transactional-memory) (revision
180773)
@@ -3826,6 +3826,9 @@ build_new_function_call (tree fn, VEC(tr
return error_mark_node;
}
+ if (flag_tm)
+ tm_malloc_replacement (fn);
+
/* If this function was found without using argument dependent
lookup, then we want to ignore any undeclared friend
functions. */
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h (.../trunk) (revision 180744)
+++ gcc/cp/cp-tree.h (.../branches/transactional-memory) (revision
180773)
@@ -5525,6 +5525,8 @@ extern void finish_omp_atomic (enum tr
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 void finish_omp_taskyield (void);
extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool);
extern tree baselink_for_fns (tree);