diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/eval.c | 40 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/member-ptr.cc | 15 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/member-ptr.exp | 28 |
5 files changed, 85 insertions, 13 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6957b73..7030b85 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2012-11-27 Daniel Jacobowitz <dan@codesourcery.com> + Yao Qi <yao@codesourcery.com> + + * eval.c (evaluate_subexp_standard): Add handling of + TYPE_CODE_MEMBERPTR when calling functions. Correct the + result of ptype for calling a TYPE_CODE_METHODPTR. + 2012-11-27 Yao Qi <yao@codesourcery.com> * symtab.c (symtab_symbol_info): Fix a -Wformat-extra-args @@ -1364,7 +1364,6 @@ evaluate_subexp_standard (struct type *expect_type, alloca (sizeof (struct value *) * (nargs + 3)); if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) { - nargs++; /* First, evaluate the structure into arg2. */ pc2 = (*pos)++; @@ -1388,22 +1387,37 @@ evaluate_subexp_standard (struct type *expect_type, arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); - if (TYPE_CODE (check_typedef (value_type (arg1))) - != TYPE_CODE_METHODPTR) - error (_("Non-pointer-to-member value used in pointer-to-member " - "construct")); + type = check_typedef (value_type (arg1)); + if (TYPE_CODE (type) == TYPE_CODE_METHODPTR) + { + if (noside == EVAL_AVOID_SIDE_EFFECTS) + arg1 = value_zero (TYPE_TARGET_TYPE (type), not_lval); + else + arg1 = cplus_method_ptr_to_value (&arg2, arg1); - if (noside == EVAL_AVOID_SIDE_EFFECTS) + /* Now, say which argument to start evaluating from. */ + nargs++; + tem = 2; + argvec[1] = arg2; + } + else if (TYPE_CODE (type) == TYPE_CODE_MEMBERPTR) { - struct type *method_type = check_typedef (value_type (arg1)); + struct type *type_ptr + = lookup_pointer_type (TYPE_DOMAIN_TYPE (type)); + + /* Now, convert these values to an address. */ + arg2 = value_cast (type_ptr, arg2); - arg1 = value_zero (method_type, not_lval); + mem_offset = value_as_long (arg1); + + arg1 = value_from_pointer (type_ptr, + value_as_long (arg2) + mem_offset); + arg1 = value_ind (arg1); + tem = 1; } else - arg1 = cplus_method_ptr_to_value (&arg2, arg1); - - /* Now, say which argument to start evaluating from. */ - tem = 2; + error (_("Non-pointer-to-member value used in pointer-to-member " + "construct")); } else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR) { @@ -1654,7 +1668,7 @@ evaluate_subexp_standard (struct type *expect_type, } else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) { - argvec[1] = arg2; + /* Pointer to member. argvec[1] is already set up. */ argvec[0] = arg1; } else if (op == OP_VAR_VALUE || (op == OP_SCOPE && function != NULL)) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index b5b125f..2046e8b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2012-11-27 Daniel Jacobowitz <dan@codesourcery.com> + + * gdb.cp/member-ptr.cc (class Diamond): Add func_ptr. + (func): New function. + (main): Initialize diamond.func_ptr and add diamond_pfunc_ptr. + * gdb.cp/member-ptr.exp: Add new tests for ptype and for + pointers to members with pointer-to-function type. + 2012-11-26 Jan Kratochvil <jan.kratochvil@redhat.com> Tom Tromey <tromey@redhat.com> diff --git a/gdb/testsuite/gdb.cp/member-ptr.cc b/gdb/testsuite/gdb.cp/member-ptr.cc index 17f022c..c501e56 100644 --- a/gdb/testsuite/gdb.cp/member-ptr.cc +++ b/gdb/testsuite/gdb.cp/member-ptr.cc @@ -137,6 +137,7 @@ class Diamond : public Padding, public Left, public Right { public: virtual int vget_base (); + int (*func_ptr) (int); }; int Diamond::vget_base () @@ -144,6 +145,12 @@ int Diamond::vget_base () return this->Left::x + 2000; } +int +func (int x) +{ + return 19 + x; +} + int main () { A a; @@ -161,6 +168,7 @@ int main () int (Diamond::*right_vpmf) (); int (Base::*base_vpmf) (); int Diamond::*diamond_pmi; + int (* Diamond::*diamond_pfunc_ptr) (int); PMI null_pmi; PMF null_pmf; @@ -178,6 +186,7 @@ int main () diamond.Left::x = 77; diamond.Right::x = 88; + diamond.func_ptr = func; /* Some valid pointer to members from a base class. */ left_pmf = (int (Diamond::*) ()) (int (Left::*) ()) (&Base::get_x); @@ -192,11 +201,17 @@ int main () /* A pointer to data member from a base class. */ diamond_pmi = (int Diamond::*) (int Left::*) &Base::x; + /* A pointer to data member, where the member is itself a pointer to + a function. */ + diamond_pfunc_ptr = (int (* Diamond::*) (int)) &Diamond::func_ptr; + null_pmi = NULL; null_pmf = NULL; pmi = NULL; /* Breakpoint 1 here. */ + (diamond.*diamond_pfunc_ptr) (20); + k = (a.*pmf)(3); pmi = &A::jj; diff --git a/gdb/testsuite/gdb.cp/member-ptr.exp b/gdb/testsuite/gdb.cp/member-ptr.exp index f569ca9..ae2b8b4 100644 --- a/gdb/testsuite/gdb.cp/member-ptr.exp +++ b/gdb/testsuite/gdb.cp/member-ptr.exp @@ -376,6 +376,33 @@ gdb_test_multiple "print ((int) pmi) == ((char *) &a.j - (char *) & a)" $name { } } +# Check pointers to data members, which are themselves pointers to +# functions. These behave like data members, not like pointers to +# member functions. + +gdb_test "ptype diamond_pfunc_ptr" \ + "type = int \\(\\*Diamond::\\*\\)\\(int\\)" + +gdb_test "ptype diamond.*diamond_pfunc_ptr" \ + "type = int \\(\\*\\)\\(int\\)" + +# This one is invalid; () binds more tightly than .*, so it tries to +# call the member pointer as a normal pointer-to-function. + +gdb_test "print diamond.*diamond_pfunc_ptr (20)" \ + "Invalid data type for function to be called." + +# With parentheses, it is valid. + +gdb_test "print (diamond.*diamond_pfunc_ptr) (20)" \ + "$vhn = 39" + +# Make sure that we do not interpret this as either a member pointer +# call or a member function call. + +gdb_test "print diamond.func_ptr (20)" \ + "$vhn = 39" + # ========================== # pointer to member function # ========================== @@ -595,6 +622,7 @@ gdb_test_multiple "print (a.*pmf)(3)" $name { } gdb_test "ptype a.*pmf" "type = int \\(A \\*( const)?, int\\)" +gdb_test "ptype (a.*pmf)(3)" "type = int" # Print out a pointer to data member which requires looking into # a base class. |