Patchwork [trans-mem] PR46646

login
register
mail settings
Submitter Aldy Hernandez
Date Dec. 14, 2010, 2:17 p.m.
Message ID <4D077C86.20609@redhat.com>
Download mbox | patch
Permalink /patch/75492/
State New
Headers show

Comments

Aldy Hernandez - Dec. 14, 2010, 2:17 p.m.
Another case of C++ objects that need to be marked as transaction-pure, 
so they can appear inside transactions.

Real-time approval from rth.  How cool is that?

Committing.
PR/46646
	* tree.c (build_common_builtin_nodes): Set __builtin_eh_pointer to
	transaction_pure.
	* tree.h (apply_tm_attr): Protoize.
	* cp/cp-tree.h (apply_tm_attr): Remove.
	* cp/except.c (build_throw): Make __cxa_rethrow pure.
	(apply_tm_attr): Move to...
	* attribs.c: ...here.

Patch

Index: attribs.c
===================================================================
--- attribs.c	(revision 167791)
+++ attribs.c	(working copy)
@@ -468,3 +468,12 @@  decl_attributes (tree *node, tree attrib
 
   return returned_attrs;
 }
+
+/* Subroutine of set_method_tm_attributes.  Apply TM attribute ATTR
+   to the method FNDECL.  */
+
+void
+apply_tm_attr (tree fndecl, tree attr)
+{
+  decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
+}
Index: tree.c
===================================================================
--- tree.c	(revision 167791)
+++ tree.c	(working copy)
@@ -9132,6 +9132,9 @@  build_common_builtin_nodes (void)
   ftype = build_function_type (ptr_type_node, tmp);
   local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER,
 			"__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW);
+  if (flag_tm)
+    apply_tm_attr (built_in_decls [BUILT_IN_EH_POINTER],
+		   get_identifier ("transaction_pure"));
 
   tmp2 = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0);
   ftype = build_function_type (tmp2, tmp);
Index: tree.h
===================================================================
--- tree.h	(revision 167793)
+++ tree.h	(working copy)
@@ -5172,6 +5172,8 @@  extern const struct attribute_spec *look
    a decl attribute to the declaration rather than to its type).  */
 extern tree decl_attributes (tree *, tree, int);
 
+extern void apply_tm_attr (tree, tree);
+
 /* In integrate.c */
 extern void set_decl_abstract_flags (tree, int);
 extern void set_decl_origin_self (tree);
Index: testsuite/g++.dg/tm/pr46646.C
===================================================================
--- testsuite/g++.dg/tm/pr46646.C	(revision 0)
+++ testsuite/g++.dg/tm/pr46646.C	(revision 0)
@@ -0,0 +1,890 @@ 
+// { dg-do compile }
+// { dg-options "-fgnu-tm -O0"}
+
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  template<class _T1, class _T2>
+    struct pair
+    {
+      typedef _T1 first_type;
+      typedef _T2 second_type;
+      _T1 first;
+      _T2 second;
+      pair()
+      : first(), second() { }
+      pair(const _T1& __a, const _T2& __b)
+      : first(__a), second(__b) { }
+    };
+}
+       
+       
+typedef long int ptrdiff_t;
+typedef __SIZE_TYPE__ size_t;
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  using ::ptrdiff_t;
+  using ::size_t;
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  struct input_iterator_tag { };
+  struct output_iterator_tag { };
+  struct forward_iterator_tag : public input_iterator_tag { };
+  struct bidirectional_iterator_tag : public forward_iterator_tag { };
+  struct random_access_iterator_tag : public bidirectional_iterator_tag { };
+  template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t,
+           typename _Pointer = _Tp*, typename _Reference = _Tp&>
+    struct iterator
+    {
+      typedef _Category iterator_category;
+      typedef _Tp value_type;
+      typedef _Distance difference_type;
+      typedef _Pointer pointer;
+      typedef _Reference reference;
+    };
+  template<typename _Iterator>
+    struct iterator_traits
+    {
+      typedef typename _Iterator::iterator_category iterator_category;
+      typedef typename _Iterator::value_type value_type;
+      typedef typename _Iterator::difference_type difference_type;
+      typedef typename _Iterator::pointer pointer;
+      typedef typename _Iterator::reference reference;
+    };
+  template<typename _Tp>
+    struct iterator_traits<_Tp*>
+    {
+      typedef random_access_iterator_tag iterator_category;
+      typedef _Tp value_type;
+      typedef ptrdiff_t difference_type;
+      typedef _Tp* pointer;
+      typedef _Tp& reference;
+    };
+  template<typename _Tp>
+    struct iterator_traits<const _Tp*>
+    {
+      typedef random_access_iterator_tag iterator_category;
+      typedef _Tp value_type;
+      typedef ptrdiff_t difference_type;
+      typedef const _Tp* pointer;
+      typedef const _Tp& reference;
+    };
+  template<typename _Iter>
+    inline typename iterator_traits<_Iter>::iterator_category
+    __iterator_category(const _Iter&)
+    { return typename iterator_traits<_Iter>::iterator_category(); }
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  template<typename _Iterator>
+    class reverse_iterator
+    : public iterator<typename iterator_traits<_Iterator>::iterator_category,
+        typename iterator_traits<_Iterator>::value_type,
+        typename iterator_traits<_Iterator>::difference_type,
+        typename iterator_traits<_Iterator>::pointer,
+                      typename iterator_traits<_Iterator>::reference>
+    {
+    protected:
+      _Iterator current;
+      typedef iterator_traits<_Iterator> __traits_type;
+    public:
+      typedef _Iterator iterator_type;
+      typedef typename __traits_type::difference_type difference_type;
+      typedef typename __traits_type::pointer pointer;
+      typedef typename __traits_type::reference reference;
+      reverse_iterator() : current() { }
+      explicit
+      reverse_iterator(iterator_type __x) : current(__x) { }
+      reverse_iterator(const reverse_iterator& __x)
+      : current(__x.current) { }
+      template<typename _Iter>
+        reverse_iterator(const reverse_iterator<_Iter>& __x)
+ : current(__x.base()) { }
+      iterator_type
+      base() const
+      { return current; }
+      reference
+      operator*() const
+      {
+ _Iterator __tmp = current;
+ return *--__tmp;
+      }
+      pointer
+      operator->() const
+      { return &(operator*()); }
+      reverse_iterator&
+      operator++()
+      {
+ --current;
+ return *this;
+      }
+      reverse_iterator
+      operator++(int)
+      {
+ reverse_iterator __tmp = *this;
+ --current;
+ return __tmp;
+      }
+      reverse_iterator&
+      operator--()
+      {
+ ++current;
+ return *this;
+      }
+      reverse_iterator
+      operator--(int)
+      {
+ reverse_iterator __tmp = *this;
+ ++current;
+ return __tmp;
+      }
+      reverse_iterator
+      operator+(difference_type __n) const
+      { return reverse_iterator(current - __n); }
+      reverse_iterator&
+      operator+=(difference_type __n)
+      {
+ current -= __n;
+ return *this;
+      }
+      reverse_iterator
+      operator-(difference_type __n) const
+      { return reverse_iterator(current + __n); }
+      reverse_iterator&
+      operator-=(difference_type __n)
+      {
+ current += __n;
+ return *this;
+      }
+      reference
+      operator[](difference_type __n) const
+      { return *(*this + __n); }
+    };
+}
+       
+       
+       
+extern "C++" {
+namespace std
+{
+  class exception
+  {
+  public:
+    exception() throw() { }
+    virtual ~exception() throw();
+    virtual const char* what() const throw();
+  };
+  class bad_exception : public exception
+  {
+  public:
+    bad_exception() throw() { }
+    virtual ~bad_exception() throw();
+    virtual const char* what() const throw();
+  };
+  typedef void (*terminate_handler) ();
+  typedef void (*unexpected_handler) ();
+  terminate_handler set_terminate(terminate_handler) throw();
+  void terminate() throw() __attribute__ ((__noreturn__));
+  unexpected_handler set_unexpected(unexpected_handler) throw();
+  void unexpected() __attribute__ ((__noreturn__));
+  bool uncaught_exception() throw() __attribute__ ((__pure__));
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) {
+  void __verbose_terminate_handler();
+}
+}
+extern "C++" {
+namespace std
+{
+  class bad_alloc : public exception
+  {
+  public:
+    bad_alloc() throw() { }
+    virtual ~bad_alloc() throw();
+    virtual const char* what() const throw();
+  };
+  struct nothrow_t { };
+  extern const nothrow_t nothrow;
+  typedef void (*new_handler)();
+  new_handler set_new_handler(new_handler) throw();
+}
+
+void* operator new(std::size_t, const std::nothrow_t&) throw();
+void* operator new[](std::size_t, const std::nothrow_t&) throw();
+void operator delete(void*, const std::nothrow_t&) throw();
+void operator delete[](void*, const std::nothrow_t&) throw();
+inline void* operator new(std::size_t, void* __p) throw() { return __p; }
+inline void* operator new[](std::size_t, void* __p) throw() { return __p; }
+inline void operator delete (void*, void*) throw() { }
+inline void operator delete[](void*, void*) throw() { }
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  void
+  __throw_bad_exception(void) __attribute__((__noreturn__));
+  __attribute__((transaction_safe))
+  void
+  __throw_bad_alloc(void) __attribute__((__noreturn__));
+  void
+  __throw_bad_cast(void) __attribute__((__noreturn__));
+  void
+  __throw_bad_typeid(void) __attribute__((__noreturn__));
+  void
+  __throw_logic_error(const char*) __attribute__((__noreturn__));
+  void
+  __throw_domain_error(const char*) __attribute__((__noreturn__));
+  void
+  __throw_invalid_argument(const char*) __attribute__((__noreturn__));
+  void
+  __throw_length_error(const char*) __attribute__((__noreturn__));
+  void
+  __throw_out_of_range(const char*) __attribute__((__noreturn__));
+  void
+  __throw_runtime_error(const char*) __attribute__((__noreturn__));
+  void
+  __throw_range_error(const char*) __attribute__((__noreturn__));
+  void
+  __throw_overflow_error(const char*) __attribute__((__noreturn__));
+  void
+  __throw_underflow_error(const char*) __attribute__((__noreturn__));
+  void
+  __throw_ios_failure(const char*) __attribute__((__noreturn__));
+  void
+  __throw_system_error(int) __attribute__((__noreturn__));
+  void
+  __throw_future_error(int) __attribute__((__noreturn__));
+  void
+  __throw_bad_function_call() __attribute__((__noreturn__));
+}
+       
+       
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  template<typename _Tp>
+    inline void
+    swap(_Tp& __a, _Tp& __b)
+    {
+     
+      _Tp __tmp = (__a);
+      __a = (__b);
+      __b = (__tmp);
+    }
+  template<typename _Tp, size_t _Nm>
+    inline void
+    swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
+    {
+      for (size_t __n = 0; __n < _Nm; ++__n)
+ swap(__a[__n], __b[__n]);
+    }
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) {
+  using std::size_t;
+  using std::ptrdiff_t;
+  template<typename _Tp>
+    class new_allocator
+    {
+    public:
+      typedef size_t size_type;
+      typedef ptrdiff_t difference_type;
+      typedef _Tp* pointer;
+      typedef const _Tp* const_pointer;
+      typedef _Tp& reference;
+      typedef const _Tp& const_reference;
+      typedef _Tp value_type;
+      template<typename _Tp1>
+        struct rebind
+        { typedef new_allocator<_Tp1> other; };
+      new_allocator() throw() { }
+      new_allocator(const new_allocator&) throw() { }
+      template<typename _Tp1>
+        new_allocator(const new_allocator<_Tp1>&) throw() { }
+      ~new_allocator() throw() { }
+      pointer
+      address(reference __x) const { return &__x; }
+      const_pointer
+      address(const_reference __x) const { return &__x; }
+      __attribute__((transaction_safe))
+      pointer
+      allocate(size_type __n, const void* = 0)
+      {
+ if (__n > this->max_size())
+   std::__throw_bad_alloc();
+ return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
+      }
+__attribute__((transaction_safe))
+void
+      deallocate(pointer __p, size_type)
+      { ::operator delete(__p); }
+      size_type
+      max_size() const throw()
+      { return size_t(-1) / sizeof(_Tp); }
+      void
+      construct(pointer __p, const _Tp& __val)
+      { ::new((void *)__p) _Tp(__val); }
+      void
+      destroy(pointer __p) { __p->~_Tp(); }
+    };
+  template<typename _Tp>
+    inline bool
+    operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
+    { return true; }
+  template<typename _Tp>
+    inline bool
+    operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
+    { return false; }
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  template<typename _Tp>
+    class allocator;
+  template<>
+    class allocator<void>
+    {
+    public:
+      typedef size_t size_type;
+      typedef ptrdiff_t difference_type;
+      typedef void* pointer;
+      typedef const void* const_pointer;
+      typedef void value_type;
+      template<typename _Tp1>
+        struct rebind
+        { typedef allocator<_Tp1> other; };
+    };
+  template<typename _Tp>
+    class allocator: public __gnu_cxx::new_allocator<_Tp>
+    {
+   public:
+      typedef size_t size_type;
+      typedef ptrdiff_t difference_type;
+      typedef _Tp* pointer;
+      typedef const _Tp* const_pointer;
+      typedef _Tp& reference;
+      typedef const _Tp& const_reference;
+      typedef _Tp value_type;
+      template<typename _Tp1>
+        struct rebind
+        { typedef allocator<_Tp1> other; };
+      allocator() throw() { }
+      allocator(const allocator& __a) throw()
+      : __gnu_cxx::new_allocator<_Tp>(__a) { }
+      template<typename _Tp1>
+        allocator(const allocator<_Tp1>&) throw() { }
+      ~allocator() throw() { }
+    };
+  template<typename _T1, typename _T2>
+    inline bool
+    operator==(const allocator<_T1>&, const allocator<_T2>&)
+    { return true; }
+  template<typename _Tp>
+    inline bool
+    operator==(const allocator<_Tp>&, const allocator<_Tp>&)
+    { return true; }
+  template<typename _T1, typename _T2>
+    inline bool
+    operator!=(const allocator<_T1>&, const allocator<_T2>&)
+    { return false; }
+  template<typename _Tp>
+    inline bool
+    operator!=(const allocator<_Tp>&, const allocator<_Tp>&)
+    { return false; }
+  //extern template class allocator<char>;
+  //  extern template class allocator<wchar_t>;
+  template<typename _Alloc, bool = __is_empty(_Alloc)>
+    struct __alloc_swap
+    { static void _S_do_it(_Alloc&, _Alloc&) { } };
+  template<typename _Alloc>
+    struct __alloc_swap<_Alloc, false>
+    {
+      static void
+      _S_do_it(_Alloc& __one, _Alloc& __two)
+      {
+ if (__one != __two)
+   swap(__one, __two);
+      }
+    };
+  template<typename _Alloc, bool = __is_empty(_Alloc)>
+    struct __alloc_neq
+    {
+      static bool
+      _S_do_it(const _Alloc&, const _Alloc&)
+      { return false; }
+    };
+  template<typename _Alloc>
+    struct __alloc_neq<_Alloc, false>
+    {
+      static bool
+      _S_do_it(const _Alloc& __one, const _Alloc& __two)
+      { return __one != __two; }
+    };
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  template<typename _Arg, typename _Result>
+    struct unary_function
+    {
+      typedef _Arg argument_type;
+      typedef _Result result_type;
+    };
+  template<typename _Arg1, typename _Arg2, typename _Result>
+    struct binary_function
+    {
+      typedef _Arg1 first_argument_type;
+      typedef _Arg2 second_argument_type;
+      typedef _Result result_type;
+    };
+  template<typename _Tp>
+    struct equal_to : public binary_function<_Tp, _Tp, bool>
+    {
+      bool
+      operator()(const _Tp& __x, const _Tp& __y) const
+      { return __x == __y; }
+    };
+  template<typename _Tp>
+    struct not_equal_to : public binary_function<_Tp, _Tp, bool>
+    {
+      bool
+      operator()(const _Tp& __x, const _Tp& __y) const
+      { return __x != __y; }
+    };
+  template<typename _Tp>
+    struct greater : public binary_function<_Tp, _Tp, bool>
+    {
+      bool
+      operator()(const _Tp& __x, const _Tp& __y) const
+      { return __x > __y; }
+    };
+  template<typename _Tp>
+    struct less : public binary_function<_Tp, _Tp, bool>
+    {
+      bool
+      operator()(const _Tp& __x, const _Tp& __y) const
+      { return __x < __y; }
+    };
+  template<typename _Tp>
+    struct _Identity : public unary_function<_Tp,_Tp>
+    {
+      _Tp&
+      operator()(_Tp& __x) const
+      { return __x; }
+      const _Tp&
+      operator()(const _Tp& __x) const
+      { return __x; }
+    };
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  enum _Rb_tree_color { _S_red = false, _S_black = true };
+  struct _Rb_tree_node_base
+  {
+    typedef _Rb_tree_node_base* _Base_ptr;
+    typedef const _Rb_tree_node_base* _Const_Base_ptr;
+    _Rb_tree_color _M_color;
+    _Base_ptr _M_parent;
+    _Base_ptr _M_left;
+    _Base_ptr _M_right;
+    static _Base_ptr
+    _S_minimum(_Base_ptr __x)
+    {
+      while (__x->_M_left != 0) __x = __x->_M_left;
+      return __x;
+    }
+    static _Const_Base_ptr
+    _S_minimum(_Const_Base_ptr __x)
+    {
+      while (__x->_M_left != 0) __x = __x->_M_left;
+      return __x;
+    }
+    static _Base_ptr
+    _S_maximum(_Base_ptr __x)
+    {
+      while (__x->_M_right != 0) __x = __x->_M_right;
+      return __x;
+    }
+    static _Const_Base_ptr
+    _S_maximum(_Const_Base_ptr __x)
+    {
+      while (__x->_M_right != 0) __x = __x->_M_right;
+      return __x;
+    }
+  };
+  template<typename _Val>
+    struct _Rb_tree_node : public _Rb_tree_node_base
+    {
+      typedef _Rb_tree_node<_Val>* _Link_type;
+      _Val _M_value_field;
+    };
+  __attribute__ ((__pure__)) _Rb_tree_node_base*
+  _Rb_tree_increment(_Rb_tree_node_base* __x) throw ();
+  __attribute__ ((__pure__)) const _Rb_tree_node_base*
+  _Rb_tree_increment(const _Rb_tree_node_base* __x) throw ();
+  __attribute__ ((__pure__)) _Rb_tree_node_base*
+  _Rb_tree_decrement(_Rb_tree_node_base* __x) throw ();
+  __attribute__ ((__pure__)) const _Rb_tree_node_base*
+  _Rb_tree_decrement(const _Rb_tree_node_base* __x) throw ();
+  template<typename _Tp>
+    struct _Rb_tree_iterator
+    {
+      typedef _Tp value_type;
+      typedef _Tp& reference;
+      typedef _Tp* pointer;
+      typedef bidirectional_iterator_tag iterator_category;
+      typedef ptrdiff_t difference_type;
+      typedef _Rb_tree_iterator<_Tp> _Self;
+      typedef _Rb_tree_node_base::_Base_ptr _Base_ptr;
+      typedef _Rb_tree_node<_Tp>* _Link_type;
+      _Rb_tree_iterator()
+      : _M_node() { }
+      explicit
+      _Rb_tree_iterator(_Link_type __x)
+      : _M_node(__x) { }
+      reference
+      operator*() const
+      { return static_cast<_Link_type>(_M_node)->_M_value_field; }
+      pointer
+      operator->() const
+      { return &static_cast<_Link_type>(_M_node)->_M_value_field; }
+      _Self&
+      operator++()
+      {
+ _M_node = _Rb_tree_increment(_M_node);
+ return *this;
+      }
+      _Self
+      operator++(int)
+      {
+ _Self __tmp = *this;
+ _M_node = _Rb_tree_increment(_M_node);
+ return __tmp;
+      }
+      _Self&
+      operator--()
+      {
+ _M_node = _Rb_tree_decrement(_M_node);
+ return *this;
+      }
+      _Self
+      operator--(int)
+      {
+ _Self __tmp = *this;
+ _M_node = _Rb_tree_decrement(_M_node);
+ return __tmp;
+      }
+      bool
+      operator==(const _Self& __x) const
+      { return _M_node == __x._M_node; }
+      bool
+      operator!=(const _Self& __x) const
+      { return _M_node != __x._M_node; }
+      _Base_ptr _M_node;
+  };
+  template<typename _Tp>
+    struct _Rb_tree_const_iterator
+    {
+      typedef _Tp value_type;
+      typedef const _Tp& reference;
+      typedef const _Tp* pointer;
+      typedef _Rb_tree_iterator<_Tp> iterator;
+      typedef bidirectional_iterator_tag iterator_category;
+      typedef ptrdiff_t difference_type;
+      typedef _Rb_tree_const_iterator<_Tp> _Self;
+      typedef _Rb_tree_node_base::_Const_Base_ptr _Base_ptr;
+      typedef const _Rb_tree_node<_Tp>* _Link_type;
+      _Rb_tree_const_iterator()
+      : _M_node() { }
+      explicit
+      _Rb_tree_const_iterator(_Link_type __x)
+      : _M_node(__x) { }
+      _Rb_tree_const_iterator(const iterator& __it)
+      : _M_node(__it._M_node) { }
+      reference
+      operator*() const
+      { return static_cast<_Link_type>(_M_node)->_M_value_field; }
+      pointer
+      operator->() const
+      { return &static_cast<_Link_type>(_M_node)->_M_value_field; }
+      _Self&
+      operator++()
+      {
+ _M_node = _Rb_tree_increment(_M_node);
+ return *this;
+      }
+      _Self
+      operator++(int)
+      {
+ _Self __tmp = *this;
+ _M_node = _Rb_tree_increment(_M_node);
+ return __tmp;
+      }
+      _Self&
+      operator--()
+      {
+ _M_node = _Rb_tree_decrement(_M_node);
+ return *this;
+      }
+      _Self
+      operator--(int)
+      {
+ _Self __tmp = *this;
+ _M_node = _Rb_tree_decrement(_M_node);
+ return __tmp;
+      }
+      bool
+      operator==(const _Self& __x) const
+      { return _M_node == __x._M_node; }
+      bool
+      operator!=(const _Self& __x) const
+      { return _M_node != __x._M_node; }
+      _Base_ptr _M_node;
+    };
+  void
+  _Rb_tree_insert_and_rebalance(const bool __insert_left,
+                                _Rb_tree_node_base* __x,
+                                _Rb_tree_node_base* __p,
+                                _Rb_tree_node_base& __header) throw ();
+  _Rb_tree_node_base*
+  _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z,
+          _Rb_tree_node_base& __header) throw ();
+  template<typename _Key, typename _Val, typename _KeyOfValue,
+           typename _Compare, typename _Alloc = allocator<_Val> >
+    class _Rb_tree
+    {
+      typedef typename _Alloc::template rebind<_Rb_tree_node<_Val> >::other
+              _Node_allocator;
+    protected:
+      typedef _Rb_tree_node_base* _Base_ptr;
+      typedef const _Rb_tree_node_base* _Const_Base_ptr;
+    public:
+      typedef _Key key_type;
+      typedef _Val value_type;
+      typedef value_type* pointer;
+      typedef const value_type* const_pointer;
+      typedef value_type& reference;
+      typedef const value_type& const_reference;
+      typedef _Rb_tree_node<_Val>* _Link_type;
+      typedef const _Rb_tree_node<_Val>* _Const_Link_type;
+      typedef size_t size_type;
+      typedef ptrdiff_t difference_type;
+      typedef _Alloc allocator_type;
+      _Node_allocator&
+      _M_get_Node_allocator()
+      { return *static_cast<_Node_allocator*>(&this->_M_impl); }
+      const _Node_allocator&
+      _M_get_Node_allocator() const
+      { return *static_cast<const _Node_allocator*>(&this->_M_impl); }
+      allocator_type
+      get_allocator() const
+      { return allocator_type(_M_get_Node_allocator()); }
+    protected:
+      _Link_type
+      _M_get_node()
+      { return _M_impl._Node_allocator::allocate(1); }
+      __attribute__((transaction_safe))
+      void
+      _M_put_node(_Link_type __p)
+      { _M_impl._Node_allocator::deallocate(__p, 1); }
+      __attribute__((transaction_safe))
+      _Link_type
+      _M_create_node(const value_type& __x)
+      {
+ _Link_type __tmp = _M_get_node();
+ try
+   { get_allocator().construct(&__tmp->_M_value_field, __x); }
+ catch(...)
+   {
+     _M_put_node(__tmp);
+     throw;
+   }
+ return __tmp;
+      }
+      void
+      _M_destroy_node(_Link_type __p)
+      {
+ get_allocator().destroy(&__p->_M_value_field);
+ _M_put_node(__p);
+      }
+    protected:
+      template<typename _Key_compare,
+        bool _Is_pod_comparator = __is_pod(_Key_compare)>
+        struct _Rb_tree_impl : public _Node_allocator
+        {
+   _Key_compare _M_key_compare;
+   _Rb_tree_node_base _M_header;
+   size_type _M_node_count;
+   _Rb_tree_impl()
+   : _Node_allocator(), _M_key_compare(), _M_header(),
+     _M_node_count(0)
+   { _M_initialize(); }
+   _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a)
+   : _Node_allocator(__a), _M_key_compare(__comp), _M_header(),
+     _M_node_count(0)
+   { _M_initialize(); }
+ private:
+   void
+   _M_initialize()
+   {
+     this->_M_header._M_color = _S_red;
+     this->_M_header._M_parent = 0;
+     this->_M_header._M_left = &this->_M_header;
+     this->_M_header._M_right = &this->_M_header;
+   }
+ };
+      _Rb_tree_impl<_Compare> _M_impl;
+    protected:
+      _Base_ptr&
+      _M_root()
+      { return this->_M_impl._M_header._M_parent; }
+      _Const_Base_ptr
+      _M_root() const
+      { return this->_M_impl._M_header._M_parent; }
+      _Base_ptr&
+      _M_leftmost()
+      { return this->_M_impl._M_header._M_left; }
+      _Const_Base_ptr
+      _M_leftmost() const
+      { return this->_M_impl._M_header._M_left; }
+      _Base_ptr&
+      _M_rightmost()
+      { return this->_M_impl._M_header._M_right; }
+      _Const_Base_ptr
+      _M_rightmost() const
+      { return this->_M_impl._M_header._M_right; }
+      _Link_type
+      _M_begin()
+      { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); }
+      _Const_Link_type
+      _M_begin() const
+      {
+ return static_cast<_Const_Link_type>
+   (this->_M_impl._M_header._M_parent);
+      }
+      _Link_type
+      _M_end()
+      { return static_cast<_Link_type>(&this->_M_impl._M_header); }
+      _Const_Link_type
+      _M_end() const
+      { return static_cast<_Const_Link_type>(&this->_M_impl._M_header); }
+      static const_reference
+      _S_value(_Const_Link_type __x)
+      { return __x->_M_value_field; }
+      static const _Key&
+      _S_key(_Const_Link_type __x)
+      { return _KeyOfValue()(_S_value(__x)); }
+      static _Link_type
+      _S_left(_Base_ptr __x)
+      { return static_cast<_Link_type>(__x->_M_left); }
+      static _Const_Link_type
+      _S_left(_Const_Base_ptr __x)
+      { return static_cast<_Const_Link_type>(__x->_M_left); }
+      static _Link_type
+      _S_right(_Base_ptr __x)
+      { return static_cast<_Link_type>(__x->_M_right); }
+      static _Const_Link_type
+      _S_right(_Const_Base_ptr __x)
+      { return static_cast<_Const_Link_type>(__x->_M_right); }
+      static const_reference
+      _S_value(_Const_Base_ptr __x)
+      { return static_cast<_Const_Link_type>(__x)->_M_value_field; }
+      static const _Key&
+      _S_key(_Const_Base_ptr __x)
+      { return _KeyOfValue()(_S_value(__x)); }
+    public:
+      typedef _Rb_tree_iterator<value_type> iterator;
+      typedef _Rb_tree_const_iterator<value_type> const_iterator;
+      typedef std::reverse_iterator<iterator> reverse_iterator;
+      typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+    private:
+      iterator
+      _M_insert_(_Const_Base_ptr __x, _Const_Base_ptr __y,
+   const value_type& __v);
+    public:
+      _Rb_tree() { }
+      iterator
+      begin()
+      {
+ return iterator(static_cast<_Link_type>
+   (this->_M_impl._M_header._M_left));
+      }
+      const_iterator
+      begin() const
+      {
+ return const_iterator(static_cast<_Const_Link_type>
+         (this->_M_impl._M_header._M_left));
+      }
+      iterator
+      end()
+      { return iterator(static_cast<_Link_type>(&this->_M_impl._M_header)); }
+      const_iterator
+      end() const
+      {
+ return const_iterator(static_cast<_Const_Link_type>
+         (&this->_M_impl._M_header));
+      }
+      pair<iterator, bool>
+      _M_insert_unique(const value_type& __x);
+    };
+  template<typename _Key, typename _Val, typename _KeyOfValue,
+           typename _Compare, typename _Alloc>
+    typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
+    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
+    _M_insert_(_Const_Base_ptr __x, _Const_Base_ptr __p, const _Val& __v)
+    {
+      _Link_type __z = _M_create_node(__v);
+      return iterator(__z);
+    }
+  template<typename _Key, typename _Val, typename _KeyOfValue,
+           typename _Compare, typename _Alloc>
+    pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
+      _Compare, _Alloc>::iterator, bool>
+    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
+    _M_insert_unique(const _Val& __v)
+    {
+      _Link_type __x = _M_begin();
+      _Link_type __y = _M_end();
+      iterator __j = iterator(__y);
+ return pair<iterator, bool>(_M_insert_(__x, __y, __v), true);
+    }
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+  template<typename _Key, typename _Compare = std::less<_Key>,
+    typename _Alloc = std::allocator<_Key> >
+    class set
+    {
+    public:
+      typedef _Key key_type;
+      typedef _Key value_type;
+      typedef _Compare key_compare;
+      typedef _Compare value_compare;
+      typedef _Alloc allocator_type;
+    private:
+      typedef typename _Alloc::template rebind<_Key>::other _Key_alloc_type;
+      typedef _Rb_tree<key_type, value_type, _Identity<value_type>,
+         key_compare, _Key_alloc_type> _Rep_type;
+      _Rep_type _M_t;
+    public:
+      typedef typename _Key_alloc_type::pointer pointer;
+      typedef typename _Key_alloc_type::const_pointer const_pointer;
+      typedef typename _Key_alloc_type::reference reference;
+      typedef typename _Key_alloc_type::const_reference const_reference;
+      typedef typename _Rep_type::const_iterator iterator;
+      typedef typename _Rep_type::const_iterator const_iterator;
+      typedef typename _Rep_type::const_reverse_iterator reverse_iterator;
+      typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
+      typedef typename _Rep_type::size_type size_type;
+      typedef typename _Rep_type::difference_type difference_type;
+      std::pair<iterator, bool>
+      insert(const value_type& __x)
+      {
+   _M_t._M_insert_unique(__x);
+      }
+    };
+}
+__attribute__((transaction_pure))
+void* operator new(size_t);
+__attribute__((transaction_pure))
+void operator delete(void*);
+class Widget
+{
+private:
+};
+class Screen
+{
+protected:
+std::set<Widget *> widgets;
+public:
+void addWidget(Widget* widget);
+};
+void Screen::addWidget(Widget* widget)
+{
+widgets.insert(widget);
+}
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 167791)
+++ cp/class.c	(working copy)
@@ -4169,15 +4169,6 @@  clone_constructors_and_destructors (tree
     clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
 }
 
-/* Subroutine of set_method_tm_attributes.  Apply TM attribute ATTR
-   to the method FNDECL.  */
-
-void
-apply_tm_attr (tree fndecl, tree attr)
-{
-  decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
-}
-
 /* 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.  */
Index: cp/except.c
===================================================================
--- cp/except.c	(revision 167791)
+++ cp/except.c	(working copy)
@@ -891,6 +891,9 @@  build_throw (tree exp)
 	    (fn, build_function_type (void_type_node, void_list_node));
 	}
 
+      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 (fn, NULL_TREE, tf_warning_or_error);
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 167791)
+++ cp/cp-tree.h	(working copy)
@@ -4626,7 +4626,6 @@  extern void fixup_type_variants			(tree)
 extern tree* decl_cloned_function_p		(const_tree, bool);
 extern void clone_function_decl			(tree, int);
 extern void adjust_clone_args			(tree);
-extern void apply_tm_attr			(tree, tree);
 
 /* in cvt.c */
 extern tree convert_to_reference		(tree, tree, int, int, tree);