You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
9.6 KiB
299 lines
9.6 KiB
Index: gdb-7.6.1/gdb/c-exp.y |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/c-exp.y 2013-11-09 17:29:19.336729300 +0100 |
|
+++ gdb-7.6.1/gdb/c-exp.y 2013-11-09 17:29:21.935727454 +0100 |
|
@@ -2890,6 +2890,30 @@ classify_inner_name (const struct block |
|
{ |
|
case LOC_BLOCK: |
|
case LOC_LABEL: |
|
+ { |
|
+ struct field_of_this_result fot; |
|
+ |
|
+ /* We might have erroneously found a constructor where we wanted |
|
+ a type name. The trick is ascertaining what the user wanted. |
|
+ If cp_lookup_nested_symbol found a constructor, but it is for a |
|
+ different type than CONTEXT, then this is really a type, not a |
|
+ constructor. Look for the type and return that. */ |
|
+ memset (&fot, 0, sizeof (fot)); |
|
+ check_field (type, copy, &fot); |
|
+ if (fot.fn_field != NULL |
|
+ && TYPE_FN_FIELD_CONSTRUCTOR (fot.fn_field->fn_fields, 0) |
|
+ && !types_equal (type, fot.type)) |
|
+ { |
|
+ struct symbol *sym; |
|
+ |
|
+ sym = lookup_symbol (copy, block, STRUCT_DOMAIN, NULL); |
|
+ if (sym != NULL) |
|
+ { |
|
+ yylval.tsym.type = SYMBOL_TYPE (sym); |
|
+ return TYPENAME; |
|
+ } |
|
+ } |
|
+ } |
|
return ERROR; |
|
|
|
case LOC_TYPEDEF: |
|
Index: gdb-7.6.1/gdb/symtab.c |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/symtab.c 2013-11-09 17:29:19.338729298 +0100 |
|
+++ gdb-7.6.1/gdb/symtab.c 2013-11-09 17:29:21.936727453 +0100 |
|
@@ -1260,7 +1260,7 @@ lookup_language_this (const struct langu |
|
return 1 if the component named NAME from the ultimate target |
|
structure/union is defined, otherwise, return 0. */ |
|
|
|
-static int |
|
+int |
|
check_field (struct type *type, const char *name, |
|
struct field_of_this_result *is_a_field_of_this) |
|
{ |
|
Index: gdb-7.6.1/gdb/symtab.h |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/symtab.h 2013-11-09 17:29:19.339729298 +0100 |
|
+++ gdb-7.6.1/gdb/symtab.h 2013-11-09 17:27:11.329820268 +0100 |
|
@@ -1318,4 +1318,9 @@ void iterate_over_symbols (const struct |
|
struct cleanup *demangle_for_lookup (const char *name, enum language lang, |
|
const char **result_name); |
|
|
|
+/* See comment in symtab.c. */ |
|
+ |
|
+int check_field (struct type *type, const char *name, |
|
+ struct field_of_this_result *is_a_field_of_this); |
|
+ |
|
#endif /* !defined(SYMTAB_H) */ |
|
Index: gdb-7.6.1/gdb/valops.c |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/valops.c 2013-11-09 17:29:19.340729297 +0100 |
|
+++ gdb-7.6.1/gdb/valops.c 2013-11-09 17:28:02.417784136 +0100 |
|
@@ -3401,10 +3401,35 @@ value_struct_elt_for_reference (struct t |
|
return value_from_longest |
|
(lookup_memberptr_type (TYPE_FIELD_TYPE (t, i), domain), |
|
offset + (TYPE_FIELD_BITPOS (t, i) >> 3)); |
|
- else if (noside == EVAL_AVOID_SIDE_EFFECTS) |
|
+ else if (noside != EVAL_NORMAL) |
|
return allocate_value (TYPE_FIELD_TYPE (t, i)); |
|
else |
|
- error (_("Cannot reference non-static field \"%s\""), name); |
|
+ { |
|
+ /* Try to evaluate NAME as a qualified name with implicit |
|
+ this pointer. In this case, attempt to return the |
|
+ equivalent to `this->*(&TYPE::NAME)'. */ |
|
+ v = value_of_this_silent (current_language); |
|
+ if (v != NULL) |
|
+ { |
|
+ struct value *ptr; |
|
+ long mem_offset; |
|
+ struct type *type, *tmp; |
|
+ |
|
+ ptr = value_aggregate_elt (domain, name, NULL, 1, noside); |
|
+ type = check_typedef (value_type (ptr)); |
|
+ gdb_assert (type != NULL |
|
+ && TYPE_CODE (type) == TYPE_CODE_MEMBERPTR); |
|
+ tmp = lookup_pointer_type (TYPE_DOMAIN_TYPE (type)); |
|
+ v = value_cast_pointers (tmp, v, 1); |
|
+ mem_offset = value_as_long (ptr); |
|
+ tmp = lookup_pointer_type (TYPE_TARGET_TYPE (type)); |
|
+ result = value_from_pointer (tmp, |
|
+ value_as_long (v) + mem_offset); |
|
+ return value_ind (result); |
|
+ } |
|
+ |
|
+ error (_("Cannot reference non-static field \"%s\""), name); |
|
+ } |
|
} |
|
} |
|
|
|
Index: gdb-7.6.1/gdb/testsuite/gdb.cp/impl-this.cc |
|
=================================================================== |
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
|
+++ gdb-7.6.1/gdb/testsuite/gdb.cp/impl-this.cc 2013-11-09 17:29:21.938727452 +0100 |
|
@@ -0,0 +1,96 @@ |
|
+/* This testcase is part of GDB, the GNU debugger. |
|
+ |
|
+ Copyright 2013 Free Software Foundation, Inc. |
|
+ |
|
+ This program is free software; you can redistribute it and/or modify |
|
+ it under the terms of the GNU General Public License as published by |
|
+ the Free Software Foundation; either version 3 of the License, or |
|
+ (at your option) any later version. |
|
+ |
|
+ This program is distributed in the hope that it will be useful, |
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
+ GNU General Public License for more details. |
|
+ |
|
+ You should have received a copy of the GNU General Public License |
|
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
|
+ |
|
+#ifdef DEBUG |
|
+#include <stdio.h> |
|
+#endif |
|
+ |
|
+class A |
|
+{ |
|
+public: |
|
+ int i; |
|
+ int z; |
|
+ A () : i (1), z (10) {} |
|
+}; |
|
+ |
|
+class B : public virtual A |
|
+{ |
|
+public: |
|
+ int i; |
|
+ B () : i (2) {} |
|
+}; |
|
+ |
|
+class C : public virtual A |
|
+{ |
|
+public: |
|
+ int i; |
|
+ int c; |
|
+ C () : i (3), c (30) {} |
|
+}; |
|
+ |
|
+class D : public B, public C |
|
+{ |
|
+public: |
|
+ int i; |
|
+ int x; |
|
+ D () : i (4), x (40) {} |
|
+ |
|
+#ifdef DEBUG |
|
+#define SUM(X) \ |
|
+ do \ |
|
+ { \ |
|
+ sum += (X); \ |
|
+ printf ("" #X " = %d\n", (X)); \ |
|
+ } \ |
|
+ while (0) |
|
+#else |
|
+#define SUM(X) sum += (X) |
|
+#endif |
|
+ |
|
+int |
|
+f (void) |
|
+ { |
|
+ int sum = 0; |
|
+ |
|
+ SUM (i); |
|
+ SUM (D::i); |
|
+ SUM (D::B::i); |
|
+ SUM (B::i); |
|
+ SUM (D::C::i); |
|
+ SUM (C::i); |
|
+ SUM (D::B::A::i); |
|
+ SUM (B::A::i); |
|
+ SUM (A::i); |
|
+ SUM (D::C::A::i); |
|
+ SUM (C::A::i); |
|
+ SUM (D::x); |
|
+ SUM (x); |
|
+ SUM (D::C::c); |
|
+ SUM (C::c); |
|
+ SUM (c); |
|
+ |
|
+ return sum; |
|
+ } |
|
+}; |
|
+ |
|
+int |
|
+main (void) |
|
+{ |
|
+ D d; |
|
+ |
|
+ return d.f (); |
|
+} |
|
Index: gdb-7.6.1/gdb/testsuite/gdb.cp/impl-this.exp |
|
=================================================================== |
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
|
+++ gdb-7.6.1/gdb/testsuite/gdb.cp/impl-this.exp 2013-11-09 17:29:21.939727451 +0100 |
|
@@ -0,0 +1,89 @@ |
|
+# Copyright 2013 Free Software Foundation, Inc. |
|
+ |
|
+# This program is free software; you can redistribute it and/or modify |
|
+# it under the terms of the GNU General Public License as published by |
|
+# the Free Software Foundation; either version 3 of the License, or |
|
+# (at your option) any later version. |
|
+# |
|
+# This program is distributed in the hope that it will be useful, |
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
+# GNU General Public License for more details. |
|
+# |
|
+# You should have received a copy of the GNU General Public License |
|
+# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
+ |
|
+# This file is part of the gdb testsuite |
|
+ |
|
+# Test expressions which assume an implicit "this" with a qualified |
|
+# name. |
|
+ |
|
+if {[skip_cplus_tests]} { continue } |
|
+ |
|
+standard_testfile .cc |
|
+ |
|
+if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} { |
|
+ return -1 |
|
+} |
|
+ |
|
+# First test expressions when there is no context. |
|
+gdb_test "print i" "No symbol \"i\" in current context." |
|
+gdb_test "print D::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print D::B::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print B::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print D::C::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print C::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print D::B::A::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print B::A::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print A::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print D::C::A::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print C::A::i" "Cannot reference non-static field \"i\"" |
|
+gdb_test "print D::x" "Cannot reference non-static field \"x\"" |
|
+gdb_test "print x" "No symbol \"x\" in current context." |
|
+gdb_test "print D::C::c" "Cannot reference non-static field \"c\"" |
|
+gdb_test "print C::c" "Cannot reference non-static field \"c\"" |
|
+gdb_test "print c" "No symbol \"c\" in current context." |
|
+ |
|
+# Run to D::f. |
|
+if {![runto_main]} { |
|
+ perror "couldn't run to main" |
|
+ continue |
|
+} |
|
+ |
|
+gdb_breakpoint "D::f" |
|
+gdb_continue_to_breakpoint "run to D::f" |
|
+ |
|
+# Now test valid expressions in the class hierarchy for D. |
|
+gdb_test "print i" "= 4" |
|
+gdb_test "print D::i" "= 4" |
|
+gdb_test "print D::B::i" "= 2" |
|
+gdb_test "print B::i" "= 2" |
|
+gdb_test "print D::C::i" "= 3" |
|
+gdb_test "print C::i" "= 3" |
|
+gdb_test "print D::B::A::i" "= 1" |
|
+gdb_test "print B::A::i" "= 1" |
|
+gdb_test "print A::i" "= 1" |
|
+gdb_test "print D::C::A::i" "= 1" |
|
+gdb_test "print C::A::i" "= 1" |
|
+gdb_test "print D::x" "= 40" |
|
+gdb_test "print x" "= 40" |
|
+gdb_test "print D::C::c" "= 30" |
|
+gdb_test "print C::c" "= 30" |
|
+gdb_test "print c" "= 30" |
|
+ |
|
+# Test some invalid expressions |
|
+gdb_test "print D::B::c" "There is no field named c" |
|
+gdb_test "print D::B::A::c" "There is no field named c" |
|
+gdb_test "print D::C::A::c" "There is no field named c" |
|
+gdb_test "print B::c" "There is no field named c" |
|
+gdb_test "print B::A::c" "There is no field named c" |
|
+gdb_test "print C::A::c" "There is no field named c" |
|
+gdb_test "print D::B::x" "There is no field named x" |
|
+gdb_test "print D::B::A::x" "There is no field named x" |
|
+gdb_test "print B::x" "There is no field named x" |
|
+gdb_test "print B::A::x" "There is no field named x" |
|
+gdb_test "print D::C::x" "There is no field named x" |
|
+gdb_test "print C::x" "There is no field named x" |
|
+gdb_test "print D::C::A::x" "There is no field named x" |
|
+gdb_test "print C::A::x" "There is no field named x" |
|
+
|
|
|