* Re: [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions. [not found] ` <a3993cdc-dbb0-e377-3e46-a84d8cf971a0@redhat.com> @ 2017-03-13 20:35 ` Mark Wielaard 2017-03-14 1:26 ` Pedro Alves 0 siblings, 1 reply; 6+ messages in thread From: Mark Wielaard @ 2017-03-13 20:35 UTC (permalink / raw) To: Pedro Alves Cc: Markus Trippelsdorf, gdb-patches, Nathan Sidwell, Ian Lance Taylor, Nick Clifton [-- Attachment #1: Type: text/plain, Size: 1645 bytes --] Hi, Switching mailinglist from gcc to gdb. On Mon, 2017-03-13 at 18:54 +0000, Pedro Alves wrote: > On 03/13/2017 06:29 PM, Mark Wielaard wrote: > > > O, sorry. I should have let Nick known about the gdb regressions I found. > > Besides this patch gdb needs the following one-liner fix: > > > > diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y > > index fd1e949..5278c05 100644 > > --- a/gdb/cp-name-parser.y > > +++ b/gdb/cp-name-parser.y > > @@ -201,6 +201,7 @@ make_empty (enum demangle_component_type d_type) > > { > > struct demangle_component *ret = d_grab (); > > ret->type = d_type; > > + ret->d_printing = 0; > > return ret; > > } > > Should gdb be memsetting instead to avoid having to know about > libiberty's "internals"? Maybe. But I went with the version I tested. Basically none of this would be needed if gdb only used the cplus_demangle_fill_* functions to initialize the data structures (although that is where there was a bug, but that is now fixed). cp-name-parser.y however sometimes uses the cplus_demangle_fill functions, but other times fills in the data structures by hand (using its own partial fill function make_empty). I know too little of this code to know why. Maybe the set of cplus_demangle_fill functions isn't complete enough or maybe the way the parser works not all information needed is there yet to call cplus_demangle_fill or maybe doing it by hand just felt more efficient? > Either version is pre-approved for GDB. Thanks. I checked in the attached to merge libiberty again and fix cp-name-parser.y make_empty. Cheers, Mark [-- Attachment #2: 0001-Merge-libiberty-Initialize-d_printing-in-all-cplus_d.patch --] [-- Type: text/x-patch, Size: 3713 bytes --] From b9da89d161e3903faa335f444af2bf05e40f926e Mon Sep 17 00:00:00 2001 From: mark <mark@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Mon, 13 Mar 2017 18:26:47 +0000 Subject: [PATCH] Merge libiberty: Initialize d_printing in all cplus_demangle_fill_* functions. While integrating the d_printing recursion guard change into gdb I noticed we forgot to initialize the demangle_component d_printing field in cplus_demangle_fill_{name,extended_operator,ctor,dtor}. As is done in cplus_demangle_fill_{component,builtin_type,operator}. It happened to work because in gcc all demangle_components were allocated through d_make_empty. But gdb has its own allocation mechanism (as might other users). libiberty/ChangeLog: * cp-demangle.c (cplus_demangle_fill_name): Initialize demangle_component d_printing. (cplus_demangle_fill_extended_operator): Likewise. (cplus_demangle_fill_ctor): Likewise. (cplus_demangle_fill_dtor): Likewise. gdb/ChangeLog: * cp-name-parser.y (make_empty): Initialize d_printing to zero. --- gdb/ChangeLog | 4 ++++ gdb/cp-name-parser.y | 1 + libiberty/ChangeLog | 8 ++++++++ libiberty/cp-demangle.c | 4 ++++ 4 files changed, 17 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e4c4432..7de2498 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,7 @@ +2017-03-13 Mark Wielaard <mark@klomp.org> + + * cp-name-parser.y (make_empty): Initialize d_printing to zero. + 2017-03-10 Keith Seitz <keiths@redhat.com> PR c++/8218 diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y index fd1e949..5278c05 100644 --- a/gdb/cp-name-parser.y +++ b/gdb/cp-name-parser.y @@ -201,6 +201,7 @@ make_empty (enum demangle_component_type d_type) { struct demangle_component *ret = d_grab (); ret->type = d_type; + ret->d_printing = 0; return ret; } diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index e93e327..b513fce 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,11 @@ +2017-03-12 Mark Wielaard <mark@klomp.org> + + * cp-demangle.c (cplus_demangle_fill_name): Initialize + demangle_component d_printing. + (cplus_demangle_fill_extended_operator): Likewise. + (cplus_demangle_fill_ctor): Likewise. + (cplus_demangle_fill_dtor): Likewise. + 2017-03-08 Mark Wielaard <mark@klomp.org> PR demangler/70909 diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 341a418..04832ff 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -854,6 +854,7 @@ cplus_demangle_fill_name (struct demangle_component *p, const char *s, int len) { if (p == NULL || s == NULL || len == 0) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_NAME; p->u.s_name.s = s; p->u.s_name.len = len; @@ -869,6 +870,7 @@ cplus_demangle_fill_extended_operator (struct demangle_component *p, int args, { if (p == NULL || args < 0 || name == NULL) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR; p->u.s_extended_operator.args = args; p->u.s_extended_operator.name = name; @@ -888,6 +890,7 @@ cplus_demangle_fill_ctor (struct demangle_component *p, || (int) kind < gnu_v3_complete_object_ctor || (int) kind > gnu_v3_object_ctor_group) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_CTOR; p->u.s_ctor.kind = kind; p->u.s_ctor.name = name; @@ -907,6 +910,7 @@ cplus_demangle_fill_dtor (struct demangle_component *p, || (int) kind < gnu_v3_deleting_dtor || (int) kind > gnu_v3_object_dtor_group) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_DTOR; p->u.s_dtor.kind = kind; p->u.s_dtor.name = name; -- 1.8.3.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions. 2017-03-13 20:35 ` [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions Mark Wielaard @ 2017-03-14 1:26 ` Pedro Alves 2017-03-14 9:05 ` Mark Wielaard 2017-03-27 14:36 ` [pushed] gdb/cp-name-parser.y: Eliminate make_empty, use cplus_demangle_fill_component " Pedro Alves 0 siblings, 2 replies; 6+ messages in thread From: Pedro Alves @ 2017-03-14 1:26 UTC (permalink / raw) To: Mark Wielaard Cc: Markus Trippelsdorf, gdb-patches, Nathan Sidwell, Ian Lance Taylor, Nick Clifton On 03/13/2017 08:35 PM, Mark Wielaard wrote: > Switching mailinglist from gcc to gdb. > > On Mon, 2017-03-13 at 18:54 +0000, Pedro Alves wrote: >> On 03/13/2017 06:29 PM, Mark Wielaard wrote: >> >> Should gdb be memsetting instead to avoid having to know about >> libiberty's "internals"? > > Maybe. But I went with the version I tested. Thanks, this restores master to a working state quickly. > Basically none of this would be needed if gdb only used the > cplus_demangle_fill_* functions to initialize the data structures > (although that is where there was a bug, but that is now fixed). > > cp-name-parser.y however sometimes uses the cplus_demangle_fill > functions, but other times fills in the data structures by hand (using > its own partial fill function make_empty). I know too little of this > code to know why. Maybe the set of cplus_demangle_fill functions isn't > complete enough or maybe the way the parser works not all information > needed is there yet to call cplus_demangle_fill or maybe doing it by > hand just felt more efficient? I don't know either. I have never had to look much deeply into this file. Git blame points at the commit that added the parser in the first place (git fb4c6eba): https://sourceware.org/ml/gdb-patches/2005-03/msg00182.html But that doesn't include any comment about this either. Seems like all uses of GDB's make_empty are followed by referring to the "s_binary" union member via these two macros: #define d_left(dc) (dc)->u.s_binary.left #define d_right(dc) (dc)->u.s_binary.right "s_binary" is documented as being "for other types": struct demangle_component { ... /* For other types. */ struct { /* Left (or only) subtree. */ struct demangle_component *left; /* Right subtree. */ struct demangle_component *right; } s_binary; And there's a cplus_demangle_fill_component function to fill these in. It's already used by cp-name-parser.y in other cases, via the fill_comp wrapper function. Using that seems to work, testing the patch below on x86_64 Fedora 23 shows no regressions. From e55453c67bbe772ce001ea15b152f8dc44b8945e Mon Sep 17 00:00:00 2001 From: Pedro Alves <palves@redhat.com> Date: Mon, 13 Mar 2017 22:54:09 +0000 Subject: [PATCH] gdb/cp-name-parser.y: Eliminate make_empty, use cplus_demangle_fill_component The demangler exports the cplus_demangle_fill_component function that clients should use to initialize demangle_component components that use the "s_binary" union member. cp-name-parser.y uses it in some places, via the fill_comp wrapper, but not all. Several places instead use a GDB-specific "make_empty" function. Because this function does not call any of the demangler "fill" functions, we had to patch it recently to clear the allocated demangle_component's "d_printing" field, which is supposedly a "private" demangler field. To avoid such problems in the future, this commit switches those places to use "fill_comp" instead, and eliminates the "make_empty" function. gdb/ChangeLog: 2017-03-13 Pedro Alves <palves@redhat.com> * cp-name-parser.y (make_empty): Delete. (demangler_special, nested_name, ptr_operator, array_indicator) (direct_declarator, declarator_1): Use fill_comp instead of make_empty. --- gdb/cp-name-parser.y | 57 ++++++++++++---------------------------------------- 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y index 70790fc..5a9e51c 100644 --- a/gdb/cp-name-parser.y +++ b/gdb/cp-name-parser.y @@ -197,15 +197,6 @@ fill_comp (enum demangle_component_type d_type, struct demangle_component *lhs, } static struct demangle_component * -make_empty (enum demangle_component_type d_type) -{ - struct demangle_component *ret = d_grab (); - ret->type = d_type; - ret->d_printing = 0; - return ret; -} - -static struct demangle_component * make_operator (const char *name, int args) { struct demangle_component *ret = d_grab (); @@ -433,9 +424,7 @@ function demangler_special : DEMANGLER_SPECIAL start - { $$ = make_empty ((enum demangle_component_type) $1); - d_left ($$) = $2; - d_right ($$) = NULL; } + { $$ = fill_comp ((enum demangle_component_type) $1, $2, NULL); } | CONSTRUCTION_VTABLE start CONSTRUCTION_IN start { $$ = fill_comp (DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, $2, $4); } ; @@ -600,30 +589,22 @@ ext_only_name : nested_name unqualified_name ; nested_name : NAME COLONCOLON - { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); - d_left ($$.comp) = $1; - d_right ($$.comp) = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL); $$.last = $$.comp; } | nested_name NAME COLONCOLON { $$.comp = $1.comp; - d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); + d_right ($1.last) = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL); $$.last = d_right ($1.last); - d_left ($$.last) = $2; - d_right ($$.last) = NULL; } | templ COLONCOLON - { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); - d_left ($$.comp) = $1; - d_right ($$.comp) = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL); $$.last = $$.comp; } | nested_name templ COLONCOLON { $$.comp = $1.comp; - d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); + d_right ($1.last) = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL); $$.last = d_right ($1.last); - d_left ($$.last) = $2; - d_right ($$.last) = NULL; } ; @@ -761,41 +742,31 @@ builtin_type : int_seq ; ptr_operator : '*' qualifiers_opt - { $$.comp = make_empty (DEMANGLE_COMPONENT_POINTER); - $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_POINTER, NULL, NULL); $$.last = &d_left ($$.comp); $$.comp = d_qualify ($$.comp, $2, 0); } /* g++ seems to allow qualifiers after the reference? */ | '&' - { $$.comp = make_empty (DEMANGLE_COMPONENT_REFERENCE); - $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_REFERENCE, NULL, NULL); $$.last = &d_left ($$.comp); } | nested_name '*' qualifiers_opt - { $$.comp = make_empty (DEMANGLE_COMPONENT_PTRMEM_TYPE); - $$.comp->u.s_binary.left = $1.comp; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $1.comp, NULL); /* Convert the innermost DEMANGLE_COMPONENT_QUAL_NAME to a DEMANGLE_COMPONENT_NAME. */ *$1.last = *d_left ($1.last); - $$.comp->u.s_binary.right = NULL; $$.last = &d_right ($$.comp); $$.comp = d_qualify ($$.comp, $3, 0); } | COLONCOLON nested_name '*' qualifiers_opt - { $$.comp = make_empty (DEMANGLE_COMPONENT_PTRMEM_TYPE); - $$.comp->u.s_binary.left = $2.comp; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $2.comp, NULL); /* Convert the innermost DEMANGLE_COMPONENT_QUAL_NAME to a DEMANGLE_COMPONENT_NAME. */ *$2.last = *d_left ($2.last); - $$.comp->u.s_binary.right = NULL; $$.last = &d_right ($$.comp); $$.comp = d_qualify ($$.comp, $4, 0); } ; array_indicator : '[' ']' - { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE); - d_left ($$) = NULL; - } + { $$ = fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, NULL, NULL); } | '[' INT ']' - { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE); - d_left ($$) = $2; - } + { $$ = fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, $2, NULL); } ; /* Details of this approach inspired by the G++ < 3.4 parser. */ @@ -948,8 +919,7 @@ direct_declarator $$.last = &d_right ($2); } | colon_ext_name - { $$.comp = make_empty (DEMANGLE_COMPONENT_TYPED_NAME); - d_left ($$.comp) = $1; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL); $$.last = &d_right ($$.comp); } ; @@ -965,8 +935,7 @@ declarator_1 : ptr_operator declarator_1 $$.last = $1.last; *$2.last = $1.comp; } | colon_ext_name - { $$.comp = make_empty (DEMANGLE_COMPONENT_TYPED_NAME); - d_left ($$.comp) = $1; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL); $$.last = &d_right ($$.comp); } | direct_declarator_1 -- 2.5.5 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions. 2017-03-14 1:26 ` Pedro Alves @ 2017-03-14 9:05 ` Mark Wielaard 2017-03-14 10:50 ` Pedro Alves 2017-03-27 14:36 ` [pushed] gdb/cp-name-parser.y: Eliminate make_empty, use cplus_demangle_fill_component " Pedro Alves 1 sibling, 1 reply; 6+ messages in thread From: Mark Wielaard @ 2017-03-14 9:05 UTC (permalink / raw) To: Pedro Alves Cc: Markus Trippelsdorf, gdb-patches, Nathan Sidwell, Ian Lance Taylor, Nick Clifton On Tue, 2017-03-14 at 01:26 +0000, Pedro Alves wrote: > And there's a cplus_demangle_fill_component function to fill > these in. It's already used by cp-name-parser.y in other > cases, via the fill_comp wrapper function. > > Using that seems to work, testing the patch below on x86_64 Fedora 23 > shows no regressions. > > From e55453c67bbe772ce001ea15b152f8dc44b8945e Mon Sep 17 00:00:00 2001 > From: Pedro Alves <palves@redhat.com> > Date: Mon, 13 Mar 2017 22:54:09 +0000 > Subject: [PATCH] gdb/cp-name-parser.y: Eliminate make_empty, use > cplus_demangle_fill_component > > The demangler exports the cplus_demangle_fill_component function that > clients should use to initialize demangle_component components that > use the "s_binary" union member. cp-name-parser.y uses it in some > places, via the fill_comp wrapper, but not all. Several places > instead use a GDB-specific "make_empty" function. Because this > function does not call any of the demangler "fill" functions, we had > to patch it recently to clear the allocated demangle_component's > "d_printing" field, which is supposedly a "private" demangler field. > To avoid such problems in the future, this commit switches those > places to use "fill_comp" instead, and eliminates the "make_empty" > function. That looks good. But note that there is one behavioral change. cplus_demangle_fill_component is defined as: /* Fill in most component types with a left subtree and a right subtree. Returns non-zero on success, zero on failure, such as an unrecognized or inappropriate component type. */ And gdb/cp-name-parser.y fill_comp does: i = cplus_demangle_fill_component (ret, d_type, lhs, rhs); gdb_assert (i); So you have an extra sanity check. Where before you might have silently created a bogus demangle_component. Which I assume is what you want. But it might depend on what gdb_assert precisely does and if the parser input is normally "sane" or not. Cheers, Mark ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions. 2017-03-14 9:05 ` Mark Wielaard @ 2017-03-14 10:50 ` Pedro Alves 2017-03-27 14:28 ` [pushed/ob] cplus_demangle_fill_component: Handle DEMANGLE_COMPONENT_RVALUE_REFERENCE (Re: [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions.) Pedro Alves 0 siblings, 1 reply; 6+ messages in thread From: Pedro Alves @ 2017-03-14 10:50 UTC (permalink / raw) To: Mark Wielaard Cc: Markus Trippelsdorf, gdb-patches, Nathan Sidwell, Ian Lance Taylor, Nick Clifton On 03/14/2017 09:04 AM, Mark Wielaard wrote: > That looks good. But note that there is one behavioral change. > cplus_demangle_fill_component is defined as: > > /* Fill in most component types with a left subtree and a right > subtree. Returns non-zero on success, zero on failure, such as an > unrecognized or inappropriate component type. */ > > And gdb/cp-name-parser.y fill_comp does: > > i = cplus_demangle_fill_component (ret, d_type, lhs, rhs); > gdb_assert (i); > > So you have an extra sanity check. Where before you might have silently > created a bogus demangle_component. Which I assume is what you want. Indeed, and I think it is. > But it might depend on what gdb_assert precisely does gdb_assert triggers the infamous: A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) > and if the parser input is normally "sane" or not. The only thing that is validated is that we don't create a component with a left/right subtree when that doesn't make sense for the component type. I think trying to create such a component would be a parser/grammar/production bug, even with invalid input. I had run into that assert in fill_comp yesterday actually, with a slightly different/larger patch. At first I saw the cplus_demangle_fill_component declaration in demangle.h, but didn't see the implementation in cp-demangle.c, and thought that was just some oversight/left over. So I though I'd add one. I factored out a cplus_demangle_fill_component out of cp-demangle.c:d_make_comp, following the same pattern used by the other cplus_demangle_fill* / d_make* function pairs. Only after did I notice that actually, there's an implementation of cplus_demangle_fill_component in cplus-demint.c... AFAICS, that's only used by GDB. No other tool in the binutils-gdb repo, nor GCC's repo uses it, AFAICS. So I figured that I'd remove the cplus-demint.c implementation, in favor of the new implementation in cp-demangle.c based on d_make_comp. And _that_ ran into the assertion, because the implementations are exactly the same. GDB fills in some types with NULL left components and fills them in later. For example, for DEMANGLE_COMPONENT_POINTER: ptr_operator : '*' qualifiers_opt - { $$.comp = make_empty (DEMANGLE_COMPONENT_POINTER); - $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_POINTER, NULL, NULL); $$.last = &d_left ($$.comp); $$.comp = d_qualify ($$.comp, $2, 0); } Note how cp-demangle.c:d_make_comp's validations are stricter than cp-demint.c:cplus_demangle_fill_component's. The former only allows lazy-filling for a few cases: [...] /* These are allowed to have no parameters--in some cases they will be filled in later. */ case DEMANGLE_COMPONENT_FUNCTION_TYPE: [...] While cp-demint.c:cplus_demangle_fill_component, the version that GDB uses, allows that in all cases. IOW, passing in a NULL left/right subtree to cplus_demangle_fill_component when the component type expects one is OK, assuming that the caller will fill them in afterwards. I crossed checked the types in the new fill_comp calls with the checks inside cplus_demangle_fill_component now, and I believe they're all OK. Maybe it'd be possible to avoid this lazy filling in, but I didn't bother trying. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 6+ messages in thread
* [pushed/ob] cplus_demangle_fill_component: Handle DEMANGLE_COMPONENT_RVALUE_REFERENCE (Re: [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions.) 2017-03-14 10:50 ` Pedro Alves @ 2017-03-27 14:28 ` Pedro Alves 0 siblings, 0 replies; 6+ messages in thread From: Pedro Alves @ 2017-03-27 14:28 UTC (permalink / raw) To: Mark Wielaard Cc: Markus Trippelsdorf, gdb-patches, Nathan Sidwell, Ian Lance Taylor, Nick Clifton, gcc-patches [added back gcc-patches, obvious libiberty patch below] On 03/14/2017 10:50 AM, Pedro Alves wrote: > On 03/14/2017 09:04 AM, Mark Wielaard wrote: > >> That looks good. But note that there is one behavioral change. >> cplus_demangle_fill_component is defined as: >> >> /* Fill in most component types with a left subtree and a right >> subtree. Returns non-zero on success, zero on failure, such as an >> unrecognized or inappropriate component type. */ >> >> And gdb/cp-name-parser.y fill_comp does: >> >> i = cplus_demangle_fill_component (ret, d_type, lhs, rhs); >> gdb_assert (i); >> >> So you have an extra sanity check. Where before you might have silently >> created a bogus demangle_component. Which I assume is what you want. > > Indeed, and I think it is. > >> But it might depend on what gdb_assert precisely does > > gdb_assert triggers the infamous: > > A problem internal to GDB has been detected, > further debugging may prove unreliable. > Quit this debugging session? (y or n) > >> and if the parser input is normally "sane" or not. > > The only thing that is validated is that we don't create > a component with a left/right subtree when that doesn't make sense > for the component type. I think trying to create such a component > would be a parser/grammar/production bug, even with invalid input. > > I had run into that assert in fill_comp yesterday actually, with a slightly > different/larger patch. At first I saw the cplus_demangle_fill_component > declaration in demangle.h, but didn't see the implementation in cp-demangle.c, and > thought that was just some oversight/left over. So I though I'd add one. I factored > out a cplus_demangle_fill_component out of cp-demangle.c:d_make_comp, following the > same pattern used by the other cplus_demangle_fill* / d_make* function pairs. > Only after did I notice that actually, there's an implementation of > cplus_demangle_fill_component in cplus-demint.c... AFAICS, that's only > used by GDB. No other tool in the binutils-gdb repo, nor GCC's repo uses it, AFAICS. > So I figured that I'd remove the cplus-demint.c implementation, in favor of > the new implementation in cp-demangle.c based on d_make_comp. And _that_ ran into the > assertion, because the implementations are exactly the same. GDB fills in some types with > NULL left components and fills them in later. For example, for DEMANGLE_COMPONENT_POINTER: > > ptr_operator : '*' qualifiers_opt > - { $$.comp = make_empty (DEMANGLE_COMPONENT_POINTER); > - $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL; > + { $$.comp = fill_comp (DEMANGLE_COMPONENT_POINTER, NULL, NULL); > $$.last = &d_left ($$.comp); > $$.comp = d_qualify ($$.comp, $2, 0); } > > Note how cp-demangle.c:d_make_comp's validations are stricter than > cp-demint.c:cplus_demangle_fill_component's. The former only allows > lazy-filling for a few cases: > > [...] > /* These are allowed to have no parameters--in some cases they > will be filled in later. */ > case DEMANGLE_COMPONENT_FUNCTION_TYPE: > [...] > > While cp-demint.c:cplus_demangle_fill_component, the version that > GDB uses, allows that in all cases. IOW, passing in a NULL left/right subtree > to cplus_demangle_fill_component when the component type expects one is OK, assuming > that the caller will fill them in afterwards. I crossed checked the types in > the new fill_comp calls with the checks inside cplus_demangle_fill_component now, > and I believe they're all OK. > > Maybe it'd be possible to avoid this lazy filling in, but I didn't > bother trying. Funny enough, I was going to apply the gdb patch today, but gdb meanwhile gained a new make_empty call for DEMANGLE_COMPONENT_RVALUE_REFERENCE, and making that new code use fill_comp/cplus_demangle_fill_component too triggered the sanity check discussed above... This is just a latent bug being exposed now. I've pushed the obvious patch below to both gcc trunk and binutils-gdb master. From b1a42fdfa31937d7e05df34afee970ac0ad239e1 Mon Sep 17 00:00:00 2001 From: Pedro Alves <palves@redhat.com> Date: Mon, 27 Mar 2017 13:56:49 +0100 Subject: [PATCH] cplus_demangle_fill_component: Handle DEMANGLE_COMPONENT_RVALUE_REFERENCE This patch almost a decade ago: ... 2007-08-31 Douglas Gregor <doug.gregor@gmail.com> * cp-demangle.c (d_dump): Handle DEMANGLE_COMPONENT_RVALUE_REFERENCE. (d_make_comp): Ditto. ... ... missed doing the same change to cplus_demangle_fill_component that was done to d_make_comp. I.e., teach it to only validate that we're not passing in a "right" subtree. GDB has recently (finally) learned about rvalue references, and a change to make it use cplus_demangle_fill_component more ran into an assertion because of this. (GDB is the only user of cplus_demangle_fill_component in both the gcc and binutils-gdb trees.) libiberty/ChangeLog: 2017-03-27 Pedro Alves <palves@redhat.com> * cp-demint.c (cplus_demangle_fill_component): Handle DEMANGLE_COMPONENT_RVALUE_REFERENCE. --- libiberty/ChangeLog | 5 +++++ libiberty/cp-demint.c | 1 + 2 files changed, 6 insertions(+) diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index b513fce..f6318e2 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,8 @@ +2017-03-27 Pedro Alves <palves@redhat.com> + + * cp-demint.c (cplus_demangle_fill_component): Handle + DEMANGLE_COMPONENT_RVALUE_REFERENCE. + 2017-03-12 Mark Wielaard <mark@klomp.org> * cp-demangle.c (cplus_demangle_fill_name): Initialize diff --git a/libiberty/cp-demint.c b/libiberty/cp-demint.c index 13a71d9..158b90a 100644 --- a/libiberty/cp-demint.c +++ b/libiberty/cp-demint.c @@ -106,6 +106,7 @@ cplus_demangle_fill_component (struct demangle_component *p, case DEMANGLE_COMPONENT_CONST_THIS: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_REFERENCE: + case DEMANGLE_COMPONENT_RVALUE_REFERENCE: case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: case DEMANGLE_COMPONENT_VENDOR_TYPE: -- 2.5.5 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [pushed] gdb/cp-name-parser.y: Eliminate make_empty, use cplus_demangle_fill_component (Re: [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions.) 2017-03-14 1:26 ` Pedro Alves 2017-03-14 9:05 ` Mark Wielaard @ 2017-03-27 14:36 ` Pedro Alves 1 sibling, 0 replies; 6+ messages in thread From: Pedro Alves @ 2017-03-27 14:36 UTC (permalink / raw) To: Mark Wielaard Cc: Markus Trippelsdorf, gdb-patches, Nathan Sidwell, Ian Lance Taylor, Nick Clifton On 03/14/2017 01:26 AM, Pedro Alves wrote: > From e55453c67bbe772ce001ea15b152f8dc44b8945e Mon Sep 17 00:00:00 2001 > From: Pedro Alves <palves@redhat.com> > Date: Mon, 13 Mar 2017 22:54:09 +0000 > Subject: [PATCH] gdb/cp-name-parser.y: Eliminate make_empty, use > cplus_demangle_fill_component > > The demangler exports the cplus_demangle_fill_component function that > clients should use to initialize demangle_component components that > use the "s_binary" union member. cp-name-parser.y uses it in some > places, via the fill_comp wrapper, but not all. Several places > instead use a GDB-specific "make_empty" function. Because this > function does not call any of the demangler "fill" functions, we had > to patch it recently to clear the allocated demangle_component's > "d_printing" field, which is supposedly a "private" demangler field. > To avoid such problems in the future, this commit switches those > places to use "fill_comp" instead, and eliminates the "make_empty" > function. > > gdb/ChangeLog: > 2017-03-13 Pedro Alves <palves@redhat.com> > > * cp-name-parser.y (make_empty): Delete. > (demangler_special, nested_name, ptr_operator, array_indicator) > (direct_declarator, declarator_1): Use fill_comp instead of > make_empty. Now pushed, as below. Same patch, but rebased on current master, which had gained a new call to make_empty, for DEMANGLE_COMPONENT_RVALUE_REFERENCE. That's what exposed the need for: https://gcc.gnu.org/ml/gcc-patches/2017-03/msg01392.html From a7e80b9e21eb907ac5c90de7452588c059db0cec Mon Sep 17 00:00:00 2001 From: Pedro Alves <palves@redhat.com> Date: Mon, 27 Mar 2017 13:56:49 +0100 Subject: [PATCH] gdb/cp-name-parser.y: Eliminate make_empty, use cplus_demangle_fill_component The demangler exports the cplus_demangle_fill_component function that clients should use to initialize demangle_component components that use the "s_binary" union member. cp-name-parser.y uses it in some places, via the fill_comp wrapper, but not all. Several places instead use a GDB-specific "make_empty" function. Because this function does not call any of the demangler "fill" functions, we had to patch it recently to clear the allocated demangle_component's "d_printing" field, which is supposedly a "private" demangler field. To avoid such problems in the future, this commit switches those places to use "fill_comp" instead, and eliminates the "make_empty" function. gdb/ChangeLog: 2017-03-27 Pedro Alves <palves@redhat.com> * cp-name-parser.y (make_empty): Delete. (demangler_special, nested_name, ptr_operator, array_indicator) (direct_declarator, declarator_1): Use fill_comp instead of make_empty. --- gdb/ChangeLog | 7 ++++++ gdb/cp-name-parser.y | 60 ++++++++++++---------------------------------------- 2 files changed, 21 insertions(+), 46 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b4d995a..517aa3d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,12 @@ 2017-03-27 Pedro Alves <palves@redhat.com> + * cp-name-parser.y (make_empty): Delete. + (demangler_special, nested_name, ptr_operator, array_indicator) + (direct_declarator, declarator_1): Use fill_comp instead of + make_empty. + +2017-03-27 Pedro Alves <palves@redhat.com> + * xml-support.h (gdb_xml_debug): Pass a "first-to-check" argument to ATTRIBUTE_PRINTF. * solib-target.c (library_list_start_list): Print "string" not diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y index b51c5e2..73a4d90 100644 --- a/gdb/cp-name-parser.y +++ b/gdb/cp-name-parser.y @@ -197,15 +197,6 @@ fill_comp (enum demangle_component_type d_type, struct demangle_component *lhs, } static struct demangle_component * -make_empty (enum demangle_component_type d_type) -{ - struct demangle_component *ret = d_grab (); - ret->type = d_type; - ret->d_printing = 0; - return ret; -} - -static struct demangle_component * make_operator (const char *name, int args) { struct demangle_component *ret = d_grab (); @@ -433,9 +424,7 @@ function demangler_special : DEMANGLER_SPECIAL start - { $$ = make_empty ((enum demangle_component_type) $1); - d_left ($$) = $2; - d_right ($$) = NULL; } + { $$ = fill_comp ((enum demangle_component_type) $1, $2, NULL); } | CONSTRUCTION_VTABLE start CONSTRUCTION_IN start { $$ = fill_comp (DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, $2, $4); } ; @@ -600,30 +589,22 @@ ext_only_name : nested_name unqualified_name ; nested_name : NAME COLONCOLON - { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); - d_left ($$.comp) = $1; - d_right ($$.comp) = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL); $$.last = $$.comp; } | nested_name NAME COLONCOLON { $$.comp = $1.comp; - d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); + d_right ($1.last) = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL); $$.last = d_right ($1.last); - d_left ($$.last) = $2; - d_right ($$.last) = NULL; } | templ COLONCOLON - { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); - d_left ($$.comp) = $1; - d_right ($$.comp) = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL); $$.last = $$.comp; } | nested_name templ COLONCOLON { $$.comp = $1.comp; - d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME); + d_right ($1.last) = fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL); $$.last = d_right ($1.last); - d_left ($$.last) = $2; - d_right ($$.last) = NULL; } ; @@ -761,45 +742,34 @@ builtin_type : int_seq ; ptr_operator : '*' qualifiers_opt - { $$.comp = make_empty (DEMANGLE_COMPONENT_POINTER); - $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_POINTER, NULL, NULL); $$.last = &d_left ($$.comp); $$.comp = d_qualify ($$.comp, $2, 0); } /* g++ seems to allow qualifiers after the reference? */ | '&' - { $$.comp = make_empty (DEMANGLE_COMPONENT_REFERENCE); - $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_REFERENCE, NULL, NULL); $$.last = &d_left ($$.comp); } | ANDAND - { $$.comp = make_empty (DEMANGLE_COMPONENT_RVALUE_REFERENCE); - $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_RVALUE_REFERENCE, NULL, NULL); $$.last = &d_left ($$.comp); } | nested_name '*' qualifiers_opt - { $$.comp = make_empty (DEMANGLE_COMPONENT_PTRMEM_TYPE); - $$.comp->u.s_binary.left = $1.comp; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $1.comp, NULL); /* Convert the innermost DEMANGLE_COMPONENT_QUAL_NAME to a DEMANGLE_COMPONENT_NAME. */ *$1.last = *d_left ($1.last); - $$.comp->u.s_binary.right = NULL; $$.last = &d_right ($$.comp); $$.comp = d_qualify ($$.comp, $3, 0); } | COLONCOLON nested_name '*' qualifiers_opt - { $$.comp = make_empty (DEMANGLE_COMPONENT_PTRMEM_TYPE); - $$.comp->u.s_binary.left = $2.comp; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $2.comp, NULL); /* Convert the innermost DEMANGLE_COMPONENT_QUAL_NAME to a DEMANGLE_COMPONENT_NAME. */ *$2.last = *d_left ($2.last); - $$.comp->u.s_binary.right = NULL; $$.last = &d_right ($$.comp); $$.comp = d_qualify ($$.comp, $4, 0); } ; array_indicator : '[' ']' - { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE); - d_left ($$) = NULL; - } + { $$ = fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, NULL, NULL); } | '[' INT ']' - { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE); - d_left ($$) = $2; - } + { $$ = fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, $2, NULL); } ; /* Details of this approach inspired by the G++ < 3.4 parser. */ @@ -952,8 +922,7 @@ direct_declarator $$.last = &d_right ($2); } | colon_ext_name - { $$.comp = make_empty (DEMANGLE_COMPONENT_TYPED_NAME); - d_left ($$.comp) = $1; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL); $$.last = &d_right ($$.comp); } ; @@ -969,8 +938,7 @@ declarator_1 : ptr_operator declarator_1 $$.last = $1.last; *$2.last = $1.comp; } | colon_ext_name - { $$.comp = make_empty (DEMANGLE_COMPONENT_TYPED_NAME); - d_left ($$.comp) = $1; + { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL); $$.last = &d_right ($$.comp); } | direct_declarator_1 -- 2.5.5 ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2017-03-27 14:36 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <1489356354-27648-1-git-send-email-mark@klomp.org>
[not found] ` <20170313181150.GA287@x4>
[not found] ` <20170313182959.GC2167@stream>
[not found] ` <a3993cdc-dbb0-e377-3e46-a84d8cf971a0@redhat.com>
2017-03-13 20:35 ` [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions Mark Wielaard
2017-03-14 1:26 ` Pedro Alves
2017-03-14 9:05 ` Mark Wielaard
2017-03-14 10:50 ` Pedro Alves
2017-03-27 14:28 ` [pushed/ob] cplus_demangle_fill_component: Handle DEMANGLE_COMPONENT_RVALUE_REFERENCE (Re: [PATCH] libiberty: Initialize d_printing in all cplus_demangle_* functions.) Pedro Alves
2017-03-27 14:36 ` [pushed] gdb/cp-name-parser.y: Eliminate make_empty, use cplus_demangle_fill_component " Pedro Alves
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox