Index: testsuite/g++.dg/tm/pr46269.C
===================================================================
--- testsuite/g++.dg/tm/pr46269.C	(revision 0)
+++ testsuite/g++.dg/tm/pr46269.C	(revision 0)
@@ -0,0 +1,29 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm" }
+
+static inline void atomic_exchange_and_add()
+{   
+  __asm__  ("blah");
+}
+
+template<class T> class shared_ptr
+{
+public:
+  shared_ptr( T * p )
+  { 
+    atomic_exchange_and_add();
+  }
+};
+
+class BuildingCompletedEvent
+{ 
+  public:
+  __attribute__((transaction_callable)) void updateBuildingSite(void);
+  __attribute__((transaction_pure)) BuildingCompletedEvent();
+};
+
+void BuildingCompletedEvent::updateBuildingSite(void)
+{ 
+  shared_ptr<BuildingCompletedEvent> event(new BuildingCompletedEvent());
+}
+
Index: trans-mem.c
===================================================================
--- trans-mem.c	(revision 166604)
+++ trans-mem.c	(working copy)
@@ -1732,7 +1732,8 @@ tm_region_init_1 (struct tm_region *regi
   gimple_stmt_iterator gsi;
   gimple g;
 
-  if (!region || !region->exit_blocks)
+  if (!region
+      || (!region->irr_blocks && !region->exit_blocks))
     return region;
 
   /* Check to see if this is the end of a region by seeing if it 
@@ -1741,7 +1742,9 @@ tm_region_init_1 (struct tm_region *regi
   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
     {
       g = gsi_stmt (gsi);
-      if (gimple_code (g) == GIMPLE_CALL)
+      if (gimple_code (g) == GIMPLE_ASM && region->irr_blocks)
+	bitmap_set_bit (region->irr_blocks, bb->index);
+      else if (gimple_code (g) == GIMPLE_CALL && region->exit_blocks)
 	{
 	  tree fn = gimple_call_fndecl (g);
 	  if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
@@ -1831,6 +1834,9 @@ gate_tm_init (void)
 	obstack_alloc (&tm_obstack.obstack, sizeof (struct tm_region));
       memset (region, 0, sizeof (*region));
       region->entry_block = single_succ (ENTRY_BLOCK_PTR);
+      /* A clone may have irrevocable blocks (i.e. GIMPLE_ASM) even if
+	 we're not technically inside a transaction.  */
+      region->irr_blocks = BITMAP_ALLOC (&tm_obstack);
 
       tm_region_init (region);
     }
@@ -2285,6 +2291,7 @@ execute_tm_mark (void)
   for (region = all_tm_regions; region ; region = region->next)
     {
       tm_log_init ();
+      /* If we have a transaction...  */
       if (region->exit_blocks)
 	{
 	  unsigned int subcode
@@ -2307,9 +2314,17 @@ execute_tm_mark (void)
 	  VEC_free (basic_block, heap, queue);
 	}
       else
+	/* ...otherwise, we're a clone and the entire function is the
+	   region.  */
 	{
 	  FOR_EACH_BB (bb)
-	    expand_block_tm (region, bb);
+	    {
+	      /* Stop at irrevocable blocks.  */
+	      if (region->irr_blocks
+		  && bitmap_bit_p (region->irr_blocks, bb->index))
+		break;
+	      expand_block_tm (region, bb);
+	    }
 	}
       tm_log_emit ();
     }
@@ -3366,17 +3381,22 @@ get_cg_data (struct cgraph_node *node)
   return d;
 }
 
-/* Add NODE to the end of QUEUE, unless IN_QUEUE_P indicates that 
-   it is already present.  */
+/* Add NODE to the end of QUEUE, unless IN_QUEUE_P indicates that it
+   is already present.  Also adds NODE to the end of QUEUE2, but only
+   if QUEUE2 is non-NULL.  */
 
 static void
 maybe_push_queue (struct cgraph_node *node,
-		  cgraph_node_queue *queue_p, bool *in_queue_p)
+		  cgraph_node_queue *queue_p,
+		  cgraph_node_queue *queue2_p,
+		  bool *in_queue_p)
 {
   if (!*in_queue_p)
     {
       *in_queue_p = true;
       VEC_safe_push (cgraph_node_p, heap, *queue_p, node);
+      if (queue2_p != NULL)
+	VEC_safe_push (cgraph_node_p, heap, *queue2_p, node);
     }
 }
 
@@ -3404,16 +3424,18 @@ ipa_tm_scan_calls_transaction (struct cg
 
 	d = get_cg_data (e->callee);
 	d->tm_callers_normal++;
-	maybe_push_queue (e->callee, callees_p, &d->in_callee_queue);
+	maybe_push_queue (e->callee, callees_p, NULL, &d->in_callee_queue);
       }
 }
 
-/* Scan all calls in NODE as if this is the transactional clone,
-   and push the destinations into the callee queue.  */
+/* Scan all calls in NODE as if this is the transactional clone, and
+   push the destinations into the callee queue.  Also, push the
+   destinations into the CALLEES2 queue.  */
 
 static void
-ipa_tm_scan_calls_clone (struct cgraph_node *node, 
-			 cgraph_node_queue *callees_p)
+ipa_tm_scan_calls_clone (struct cgraph_node *node,
+			 cgraph_node_queue *callees_p,
+			 cgraph_node_queue *callees2_p)
 {
   struct cgraph_edge *e;
 
@@ -3428,7 +3450,8 @@ ipa_tm_scan_calls_clone (struct cgraph_n
 	  struct tm_ipa_cg_data *d = get_cg_data (e->callee);
 
 	  d->tm_callers_clone++;
-	  maybe_push_queue (e->callee, callees_p, &d->in_callee_queue);
+	  maybe_push_queue (e->callee, callees_p, callees2_p,
+			    &d->in_callee_queue);
 	}
     }
 }
@@ -3454,7 +3477,7 @@ ipa_tm_note_irrevocable (struct cgraph_n
 	continue;
       if (gimple_call_in_transaction_p (e->call_stmt))
 	d->want_irr_scan_normal = true;
-      maybe_push_queue (e->caller, worklist_p, &d->in_worklist);
+      maybe_push_queue (e->caller, worklist_p, NULL, &d->in_worklist);
     }
 }
 
@@ -3659,6 +3682,10 @@ ipa_tm_scan_irr_function (struct cgraph_
   VEC (basic_block, heap) *queue;
   bool ret = false;
 
+  /* Skip things like new/delete operators.  */
+  if (!DECL_STRUCT_FUNCTION (node->decl))
+    return false;
+
   current_function_decl = node->decl;
   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
   calculate_dominance_info (CDI_DOMINATORS);
@@ -3714,21 +3741,21 @@ ipa_tm_scan_irr_function (struct cgraph_
 	d->irrevocable_blocks_clone = new_irr;
       else
 	d->irrevocable_blocks_normal = new_irr;
+
+      if (dump_file)
+	{
+	  const char *dname;
+	  bitmap_iterator bmi;
+	  unsigned i;
+
+	  dname = lang_hooks.decl_printable_name (current_function_decl, 2);
+	  EXECUTE_IF_SET_IN_BITMAP (new_irr, 0, i, bmi)
+	    fprintf (dump_file, "%s: bb %d goes irrevocable\n", dname, i);
+	}
     }
   else
     BITMAP_FREE (new_irr);
 
-  if (dump_file)
-    {
-      const char *dname;
-      bitmap_iterator bmi;
-      unsigned i;
-
-      dname = lang_hooks.decl_printable_name (current_function_decl, 2);
-      EXECUTE_IF_SET_IN_BITMAP (new_irr, 0, i, bmi)
-	fprintf (dump_file, "%s: bb %d goes irrevocable\n", dname, i);
-    }
-
   VEC_free (basic_block, heap, queue);
   pop_cfun ();
   current_function_decl = NULL;
@@ -4353,7 +4380,7 @@ ipa_tm_execute (void)
 	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
       {
 	d = get_cg_data (node);
-	maybe_push_queue (node, &tm_callees, &d->in_callee_queue);
+	maybe_push_queue (node, &tm_callees, NULL, &d->in_callee_queue);
       }
 
   /* For all local reachable functions...  */
@@ -4386,6 +4413,7 @@ ipa_tm_execute (void)
   /* For every local function on the callee list, scan as if we will be
      creating a transactional clone, queueing all new functions we find
      along the way.  */
+  worklist = VEC_copy (cgraph_node_p, heap, tm_callees);
   for (i = 0; i < VEC_length (cgraph_node_p, tm_callees); ++i)
     {
       node = VEC_index (cgraph_node_p, tm_callees, i);
@@ -4399,7 +4427,7 @@ ipa_tm_execute (void)
 	      && !tree_versionable_function_p (node->decl)))
 	ipa_tm_note_irrevocable (node, &worklist);
       else if (a >= AVAIL_OVERWRITABLE && !d->is_irrevocable)
-	ipa_tm_scan_calls_clone (node, &tm_callees);
+	ipa_tm_scan_calls_clone (node, &tm_callees, &worklist);
     }
 
   /* Iterate scans until no more work to be done.  Prefer not to use
@@ -4438,7 +4466,7 @@ ipa_tm_execute (void)
 	{
 	  d = get_cg_data (node);
 	  gcc_assert (d->in_worklist == false);
-	  maybe_push_queue (node, &worklist, &d->in_worklist);
+	  maybe_push_queue (node, &worklist, NULL, &d->in_worklist);
 	}
     }
 
@@ -4461,7 +4489,7 @@ ipa_tm_execute (void)
       for (e = node->callers; e ; e = e->next_caller)
 	if (!is_tm_safe (e->caller->decl)
 	    && !e->caller->local.tm_may_enter_irr)
-	  maybe_push_queue (e->caller, &worklist, &d->in_worklist);
+	  maybe_push_queue (e->caller, &worklist, NULL, &d->in_worklist);
     }
 
   /* Now validate all tm_safe functions, and all atomic regions in
