diff -ur ruby-1.9.3-p125/object.c ruby-1.9.3-p125-mod/object.c
--- ruby-1.9.3-p125/object.c	2012-02-10 05:13:30.000000000 +0900
+++ ruby-1.9.3-p125-mod/object.c	2012-03-24 20:32:05.000000000 +0900
@@ -1683,8 +1683,8 @@
 
 /*
  *  call-seq:
- *     attr_reader(symbol, ...)    -> nil
- *     attr(symbol, ...)             -> nil
+ *     attr_reader(symbol, ...)    -> [method-symbol, ...]
+ *     attr(symbol, ...)             -> [method-symbol, ...]
  *
  *  Creates instance variables and corresponding methods that return the
  *  value of each instance variable. Equivalent to calling
@@ -1695,11 +1695,14 @@
 rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass)
 {
     int i;
+    VALUE result = rb_ary_new();
 
     for (i=0; i<argc; i++) {
 	rb_attr(klass, rb_to_id(argv[i]), TRUE, FALSE, TRUE);
+	rb_ary_push(result, ID2SYM(rb_to_id(argv[i])));
     }
-    return Qnil;
+
+    return result;
 }
 
 VALUE
@@ -1715,31 +1718,36 @@
 
 /*
  *  call-seq:
- *      attr_writer(symbol, ...)    -> nil
+ *      attr_writer(symbol, ...)    -> [method-symbol, ...]
  *
  *  Creates an accessor method to allow assignment to the attribute
  *  <i>aSymbol</i><code>.id2name</code>.
+ *  returns accessor method names like [:x=, :y=, ...]
  */
 
 static VALUE
 rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass)
 {
     int i;
+    VALUE result = rb_ary_new();
 
     for (i=0; i<argc; i++) {
 	rb_attr(klass, rb_to_id(argv[i]), FALSE, TRUE, TRUE);
+	rb_ary_push(result, ID2SYM(rb_id_attrset(rb_to_id(argv[i]))));
     }
-    return Qnil;
+
+    return result;
 }
 
 /*
  *  call-seq:
- *     attr_accessor(symbol, ...)    -> nil
+ *     attr_accessor(symbol, ...)    -> [method-symbol, ...]
  *
  *  Defines a named attribute for this module, where the name is
  *  <i>symbol.</i><code>id2name</code>, creating an instance variable
  *  (<code>@name</code>) and a corresponding access method to read it.
  *  Also creates a method called <code>name=</code> to set the attribute.
+ *  returns both read/write method names like [:x, :x=, :y, :y=, ...]
  *
  *     module Mod
  *       attr_accessor(:one, :two)
@@ -1751,11 +1759,15 @@
 rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass)
 {
     int i;
+    VALUE result = rb_ary_new();
 
     for (i=0; i<argc; i++) {
 	rb_attr(klass, rb_to_id(argv[i]), TRUE, TRUE, TRUE);
+	rb_ary_push(result, ID2SYM(rb_to_id(argv[i])));
+	rb_ary_push(result, ID2SYM(rb_id_attrset(rb_to_id(argv[i]))));
     }
-    return Qnil;
+    
+    return result;
 }
 
 /*
diff -ur ruby-1.9.3-p125/test/ruby/test_module.rb ruby-1.9.3-p125-mod/test/ruby/test_module.rb
--- ruby-1.9.3-p125/test/ruby/test_module.rb	2012-02-13 13:51:21.000000000 +0900
+++ ruby-1.9.3-p125-mod/test/ruby/test_module.rb	2012-03-25 00:52:53.000000000 +0900
@@ -1220,4 +1220,118 @@
     INPUT
     assert_in_out_err([], src, ["NameError"], [])
   end
+
+  def test_attr_return_value
+    c = Class.new
+    c.class_eval do
+      @@r1 = attr_reader :r1
+      @@w1 = attr_writer :w1
+      @@rw1 = attr_accessor :rw1
+
+      @@r2 = attr_reader :r2_1, :r2_2, :r2_3
+      @@w2 = attr_writer :w2_1, :w2_2, :w2_3
+      @@rw2 = attr_accessor :rw2_1, :rw2_2, :rw2_3
+
+      def self.get_r1; @@r1; end
+      def self.get_w1; @@w1; end
+      def self.get_rw1; @@rw1; end
+      def self.get_r2; @@r2; end
+      def self.get_w2; @@w2; end
+      def self.get_rw2; @@rw2; end
+    end
+
+    assert_equal(c.get_r1, [:r1])
+    assert_equal(c.get_w1, [:w1=])
+    assert_equal(c.get_rw1.sort, [:rw1,:rw1=].sort)
+
+    assert_equal(c.get_r2, [:r2_1, :r2_2, :r2_3])
+    assert_equal(c.get_w2, [:w2_1=, :w2_2=, :w2_3=])
+    assert_equal(c.get_rw2.sort, [:rw2_1,:rw2_1=,
+                                  :rw2_2,:rw2_2=,
+                                  :rw2_3,:rw2_3=].sort)
+  end
+
+  def test_visibility_array
+    c = Class.new
+    c.class_eval do
+      def foo; end
+      def pub0; end
+      def pub1; end
+      def pub2; end
+      def pub3; end
+      
+      def pro0; end
+      def pro1; end
+      def pro2; end
+      def pro3; end
+      
+      def pri0; end
+      def pri1; end
+      def pri2; end
+      def pri3; end
+      
+      public :pub0, [:pub1, :pub2], :pub3
+      protected :pro0, [], [:pro1], [:pro2, :pro3]
+      private [:pri0, :pri1, :pri2, :pri3]
+    end
+
+    pub = [true, false, false]
+    pro = [false, true, false]
+    pri = [false, false, true]
+    check = {
+      :pub0 => pub, :pub1 => pub, :pub2 => pub, :pub3 => pub,
+      :pro0 => pro, :pro1 => pro, :pro2 => pro, :pro3 => pro,
+      :pri0 => pri, :pri1 => pri, :pri2 => pri, :pri3 => pri,
+    }
+
+    check.each do |symbol, (ispub, ispro, ispri)|
+      assert_equal(ispub, c.public_method_defined?(symbol))
+      assert_equal(ispro, c.protected_method_defined?(symbol))
+      assert_equal(ispri, c.private_method_defined?(symbol))
+    end
+  end
+
+  def test_attr_visibility
+    c = Class.new
+    c.class_eval do
+      public attr_reader :pub_r1
+      protected attr_reader :pro_r1, :pro_r2
+      private attr_reader :pri_r1
+      
+      public attr_writer :pub_w1, :pub_w2
+      protected attr_writer :pro_w1
+      private attr_writer :pri_w1
+
+      public attr_accessor :pub_a1
+      protected attr_accessor :pro_a1
+      private attr_accessor :pri_a1, :pri_a2
+    end
+
+    pub = [true, false, false]
+    pro = [false, true, false]
+    pri = [false, false, true]
+    none = [false, false, false]
+    check = {
+      :pub_r1 => pub, :pub_r1= => none,
+      :pro_r1 => pro, :pro_r1= => none,
+      :pro_r2 => pro, :pro_r2= => none,
+      :pri_r1 => pri, :pri_r1= => none,
+
+      :pub_w1 => none, :pub_w1= => pub,
+      :pub_w2 => none, :pub_w2= => pub,
+      :pro_w1 => none, :pro_w1= => pro,
+      :pri_w1 => none, :pri_w1= => pri,
+
+      :pub_a1 => pub, :pub_a1= => pub,
+      :pro_a1 => pro, :pro_a1 => pro,
+      :pri_a1 => pri, :pri_a1 => pri,
+      :pri_a2 => pri, :pri_a2 => pri,
+    }
+    
+    check.each do |symbol, (ispub, ispro, ispri)|
+      assert_equal(ispub, c.public_method_defined?(symbol))
+      assert_equal(ispro, c.protected_method_defined?(symbol))
+      assert_equal(ispri, c.private_method_defined?(symbol))
+    end
+  end
 end
diff -ur ruby-1.9.3-p125/vm_method.c ruby-1.9.3-p125-mod/vm_method.c
--- ruby-1.9.3-p125/vm_method.c	2012-02-13 13:51:21.000000000 +0900
+++ ruby-1.9.3-p125-mod/vm_method.c	2012-03-25 01:24:47.000000000 +0900
@@ -958,6 +958,25 @@
     }
 }
 
+static int
+try_set_methods_visibilities(VALUE self, VALUE ary, rb_method_flag_t ex)
+{
+    int i;
+    VALUE tmp = ary;
+
+    if(TYPE(ary) != T_ARRAY) {
+	tmp = rb_check_array_type(tmp);
+	if(NIL_P(tmp)) {
+	    return FALSE;
+	}
+    }
+    for(i=0; i<RARRAY_LEN(ary); ++i) {
+	rb_export_method(self, rb_to_id(RARRAY_PTR(ary)[i]), ex);
+    }
+  
+    return TRUE;
+}
+
 static void
 set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex)
 {
@@ -969,7 +988,9 @@
     }
 
     for (i = 0; i < argc; i++) {
-	rb_export_method(self, rb_to_id(argv[i]), ex);
+	if(!try_set_methods_visibilities(self, argv[i], ex)) {
+  	    rb_export_method(self, rb_to_id(argv[i]), ex);
+	}
     }
     rb_clear_cache_by_class(self);
 }
@@ -978,10 +999,11 @@
  *  call-seq:
  *     public                 -> self
  *     public(symbol, ...)    -> self
+ *     public(array, ...)     -> self
  *
  *  With no arguments, sets the default visibility for subsequently
  *  defined methods to public. With arguments, sets the named methods to
- *  have public visibility.
+ *  have public visibility. Arguments can contain array of symbols.
  */
 
 static VALUE
@@ -1001,10 +1023,11 @@
  *  call-seq:
  *     protected                -> self
  *     protected(symbol, ...)   -> self
+ *     protected(array, ...)    -> self
  *
  *  With no arguments, sets the default visibility for subsequently
  *  defined methods to protected. With arguments, sets the named methods
- *  to have protected visibility.
+ *  to have protected visibility. Arguments can contain array of symbols.
  */
 
 static VALUE
@@ -1024,10 +1047,11 @@
  *  call-seq:
  *     private                 -> self
  *     private(symbol, ...)    -> self
+ *     private(array, ...)     -> self
  *
  *  With no arguments, sets the default visibility for subsequently
  *  defined methods to private. With arguments, sets the named methods
- *  to have private visibility.
+ *  to have private visibility. Arguments can contain array of symbols.
  *
  *     module Mod
  *       def a()  end
