public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* 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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).