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);

Reply via email to