From 2d6d1b2f5827322fad8e6b06e4c107a9653bb7b1 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sat, 9 Nov 2013 19:27:47 +0100 Subject: [PATCH] Fix explicit Class:: inside class scope (BZ 874817, Keith Seitz). --- gdb-implicit-this.patch | 299 ++++++++++++++++++++++++++++++++++++++++ gdb.spec | 9 +- 2 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 gdb-implicit-this.patch diff --git a/gdb-implicit-this.patch b/gdb-implicit-this.patch new file mode 100644 index 0000000..0ce72dd --- /dev/null +++ b/gdb-implicit-this.patch @@ -0,0 +1,299 @@ +Index: gdb-7.6.50.20130731-cvs/gdb/c-exp.y +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/c-exp.y 2013-11-09 18:41:48.706718127 +0100 ++++ gdb-7.6.50.20130731-cvs/gdb/c-exp.y 2013-11-09 18:42:19.291697661 +0100 +@@ -2944,6 +2944,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.50.20130731-cvs/gdb/symtab.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/symtab.c 2013-11-09 18:41:48.708718125 +0100 ++++ gdb-7.6.50.20130731-cvs/gdb/symtab.c 2013-11-09 18:42:19.293697660 +0100 +@@ -1293,7 +1293,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.50.20130731-cvs/gdb/symtab.h +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/symtab.h 2013-11-09 18:42:19.293697660 +0100 ++++ gdb-7.6.50.20130731-cvs/gdb/symtab.h 2013-11-09 18:42:34.023687872 +0100 +@@ -1377,4 +1377,9 @@ void initialize_symbol (struct symbol *) + + struct template_symbol *allocate_template_symbol (struct objfile *); + ++/* 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.50.20130731-cvs/gdb/valops.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/valops.c 2013-11-09 18:41:48.712718123 +0100 ++++ gdb-7.6.50.20130731-cvs/gdb/valops.c 2013-11-09 18:42:19.294697659 +0100 +@@ -3226,10 +3226,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.50.20130731-cvs/gdb/testsuite/gdb.cp/impl-this.cc +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.cp/impl-this.cc 2013-11-09 18:42:19.294697659 +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 . */ ++ ++#ifdef DEBUG ++#include ++#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.50.20130731-cvs/gdb/testsuite/gdb.cp/impl-this.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.cp/impl-this.exp 2013-11-09 18:42:19.295697659 +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 . ++ ++# 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" ++ diff --git a/gdb.spec b/gdb.spec index adbeb7c..be5a304 100644 --- a/gdb.spec +++ b/gdb.spec @@ -38,7 +38,7 @@ Version: 7.6.50.%{snap} # The release always contains a leading reserved number, start it at 1. # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing. -Release: 15%{?dist} +Release: 16%{?dist} License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and BSD and Public Domain Group: Development/Debuggers @@ -529,6 +529,9 @@ Patch843: gdb-enable-count-crash.patch # RH BZ 1013453). Patch844: gdb-rhbz1013453-value-struct-elt-memory-leak.patch +# Fix explicit Class:: inside class scope (BZ 874817, Keith Seitz). +Patch845: gdb-implicit-this.patch + %if 0%{!?rhel:1} || 0%{?rhel} > 6 # RL_STATE_FEDORA_GDB would not be found for: # Patch642: gdb-readline62-ask-more-rh.patch @@ -822,6 +825,7 @@ find -name "*.info*"|xargs rm -f %patch832 -p1 %patch843 -p1 %patch844 -p1 +%patch845 -p1 %patch393 -p1 %if 0%{!?el5:1} || 0%{?scl:1} @@ -1340,6 +1344,9 @@ fi %endif # 0%{!?el5:1} || "%{_target_cpu}" == "noarch" %changelog +* Sat Nov 9 2013 Jan Kratochvil - 7.6.50.20130731-16.fc20 +- Fix explicit Class:: inside class scope (BZ 874817, Keith Seitz). + * Tue Nov 5 2013 Jan Kratochvil - 7.6.50.20130731-15.fc20 - [aarch64] Backport two fixes (BZ 1026484).