This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[cplus] Support for function-local names


With this patch I can now parse every demangled name in Michael's testsuite
except for:
  CryptoPP::NullRNG()::NullRNG::AlgorithmName const()
  boost::optional<url>::operator void (boost::optional<url>::*)() const()
  and similar.

The first is a demangler bug; the const should be after the parentheses. 
This is GCC PR c++/13447.

The second is the same bug and also a problem with the mangling of operator
names.  I'm not decided on whether the conflict is resolvable.  There's
discussion of demangling this as:
  blah::operator __typeof__(void (boost::optional<url>::*)()) () const
instead.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2003-12-19  Daniel Jacobowitz  <drow@mvista.com>

	* cp-names.y (symbol_end): New function.
	(trim_chars): Use it.
	(start_opt, function): New non-terminals used to support
	function-local names.
	(GLOBAL): New terminal.
	(start): Use start_opt.
	(demangler_special): Handle GLOBAL.
	(array_indicator): Swap arguments to D_COMP_ARRAY_TYPE.
	(direct_abstract_declarator, direct_declarator)
	(direct_declarator_1): Likewise.
	(declarator_1): Use declarator_1 instead of declarator after
	a ptr_operator.  Support function-local names.
	(yylex): Handle GLOBAL specially.

Index: cp-names.y
===================================================================
RCS file: /cvs/src/src/gdb/Attic/cp-names.y,v
retrieving revision 1.1.2.7
diff -u -p -r1.1.2.7 cp-names.y
--- cp-names.y	19 Dec 2003 06:23:13 -0000	1.1.2.7
+++ cp-names.y	19 Dec 2003 16:42:03 -0000
@@ -49,6 +49,7 @@ typedef long double DOUBLEST;
 
 #include "safe-ctype.h"
 
+/* #define CP_DEMANGLE_DEBUG */
 #include "../libiberty/cp-demangle.c"
 
 static char *lexptr, *prev_lexptr;
@@ -62,6 +63,8 @@ static struct d_comp *d_op_from_string (
 static struct d_comp *d_unary (const char *opname, struct d_comp *);
 static struct d_comp *d_binary (const char *opname, struct d_comp *, struct d_comp *);
 
+static char *symbol_end (char *lexptr);
+
 /* Global state, ew.  */
 struct d_info *di;
 static struct d_comp *result;
@@ -195,14 +198,14 @@ void yyerror (char *);
 static int parse_number (char *, int, int, YYSTYPE *);
 %}
 
-%type <comp> exp exp1 type start operator colon_name
+%type <comp> exp exp1 type start start_opt operator colon_name
 %type <comp> unqualified_name scope_id colon_ext_name
 %type <comp> template template_arg
 %type <comp> builtin_type
 %type <comp> typespec typespec_2 array_indicator
 %type <comp> colon_ext_only ext_only_name
 
-%type <comp> demangler_special
+%type <comp> demangler_special function
 
 %type <nested> abstract_declarator direct_abstract_declarator
 %type <nested> declarator direct_declarator function_arglist
@@ -244,6 +247,7 @@ static int parse_number (char *, int, in
 /* Non-C++ things we get from the demangler.  */
 %token <lval> DEMANGLER_SPECIAL CONSTRUCTION_VTABLE
 %token CONSTRUCTION_IN
+%token <typed_val_int> GLOBAL
 
 %{
 enum {
@@ -293,21 +297,37 @@ result		:	start
 start		:	type
 			{ $$ = $1; }
 
+		|	demangler_special
+
+		|	function
+
+		;
+
+start_opt	:	/* */
+			{ $$ = NULL; }
+		|	COLONCOLON start
+			{ $$ = $2; }
+		;
+
+function
 		/* Function with a return type.  declarator_1 is used to prevent
 		   ambiguity with the next rule.  */
-		|	typespec_2 declarator_1
+		:	typespec_2 declarator_1
 			{ $$ = $2.comp;
 			  *$2.last = $1;
 			}
 
 		/* Function without a return type.  We need to use typespec_2
-		   to prevent conflicts from qualifiers_opt.  Harmless.  */
-		|	typespec_2 function_arglist
-			{ $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2.comp); }
-		|	colon_ext_only function_arglist
-			{ $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2.comp); }
+		   to prevent conflicts from qualifiers_opt - harmless.  The
+		   start_opt is used to handle "function-local" variables and
+		   types.  */
+		|	typespec_2 function_arglist start_opt
+			{ $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2.comp);
+			  if ($3) $$ = d_make_comp (di, D_COMP_QUAL_NAME, $$, $3); }
+		|	colon_ext_only function_arglist start_opt
+			{ $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2.comp);
+			  if ($3) $$ = d_make_comp (di, D_COMP_QUAL_NAME, $$, $3); }
 
-		| demangler_special
 		;
 
 demangler_special
@@ -317,6 +337,10 @@ demangler_special
 			  d_right ($$) = NULL; }
 		|	CONSTRUCTION_VTABLE start CONSTRUCTION_IN start
 			{ $$ = d_make_comp (di, $1, $2, $4); }
+		|	GLOBAL
+			{ $$ = d_make_empty (di, $1.val);
+			  d_left ($$) = $1.type;
+			  d_right ($$) = NULL; }
 		;
 
 operator	:	OPERATOR NEW
@@ -385,6 +409,10 @@ operator	:	OPERATOR NEW
 			{ $$ = d_op_from_string ("()"); }
 		|	OPERATOR '[' ']'
 			{ $$ = d_op_from_string ("[]"); }
+
+		/* Conversion operators.  We don't try to handle some of
+		   the wackier demangler output for function pointers,
+		   since it's not clear that it's parseable.  */
 		|	OPERATOR typespec_2
 			{ $$ = d_make_comp (di, D_COMP_CAST, $2, NULL); }
 		|	OPERATOR typespec_2 ptr_operator_seq
@@ -641,7 +669,7 @@ ptr_operator_seq:	ptr_operator
 
 array_indicator	:	'[' ']'
 			{ $$ = d_make_empty (di, D_COMP_ARRAY_TYPE);
-			  d_right ($$) = NULL;
+			  d_left ($$) = NULL;
 			}
 		|	'[' INT ']'
 			{ struct d_comp *i;
@@ -651,7 +679,7 @@ array_indicator	:	'[' ']'
 			  i = d_make_name (di, buf, strlen (buf));
 			  i = d_make_comp (di, D_COMP_LITERAL, $2.type, i);
 			  $$ = d_make_empty (di, D_COMP_ARRAY_TYPE);
-			  d_right ($$) = i;
+			  d_left ($$) = i;
 			}
 
 /* Details of this approach inspired by the G++ < 3.4 parser.  */
@@ -686,11 +714,11 @@ direct_abstract_declarator
 		|	direct_abstract_declarator array_indicator
 			{ $$.comp = $1.comp;
 			  *$1.last = $2;
-			  $$.last = &d_left ($2);
+			  $$.last = &d_right ($2);
 			}
 		|	array_indicator
 			{ $$.comp = $1;
-			  $$.last = &d_left ($1);
+			  $$.last = &d_right ($1);
 			}
 		/* G++ has the following except for () and (type).  Then
 		   (type) is handled in regcast_or_absdcl and () is handled
@@ -728,7 +756,7 @@ direct_declarator
 		|	direct_declarator array_indicator
 			{ $$.comp = $1.comp;
 			  *$1.last = $2;
-			  $$.last = &d_left ($2);
+			  $$.last = &d_right ($2);
 			}
 		|	colon_ext_name
 			{ $$.comp = d_make_empty (di, D_COMP_TYPED_NAME);
@@ -743,7 +771,7 @@ direct_declarator
    parentheses around the colon_ext_name; any colon_ext_name in parentheses
    must be followed by an argument list or an array indicator, or preceded
    by a pointer.  */
-declarator_1	:	ptr_operator declarator
+declarator_1	:	ptr_operator declarator_1
 			{ $$.comp = $2.comp;
 			  $$.last = $1.last;
 			  *$2.last = $1.comp; }
@@ -753,6 +781,17 @@ declarator_1	:	ptr_operator declarator
 			  $$.last = &d_right ($$.comp);
 			}
 		|	direct_declarator_1
+
+			/* Function local variable or type.  The typespec to
+			   our left is the type of the containing function. 
+			   This should be OK, because function local types
+			   can not be templates, so the return types of their
+			   members will not be mangled.  */
+		|	colon_ext_name function_arglist COLONCOLON start
+			{ $$.comp = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2.comp);
+			  $$.last = $2.last;
+			  $$.comp = d_make_comp (di, D_COMP_QUAL_NAME, $$.comp, $4);
+			}
 		;
 
 direct_declarator_1
@@ -768,7 +807,7 @@ direct_declarator_1
 		|	direct_declarator_1 array_indicator
 			{ $$.comp = $1.comp;
 			  *$1.last = $2;
-			  $$.last = &d_left ($2);
+			  $$.last = &d_right ($2);
 			}
 		|	colon_ext_name function_arglist
 			{ $$.comp = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2.comp);
@@ -776,7 +815,7 @@ direct_declarator_1
 			}
 		|	colon_ext_name array_indicator
 			{ $$.comp = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2);
-			  $$.last = &d_left ($2);
+			  $$.last = &d_right ($2);
 			}
 		;
 
@@ -1862,6 +1901,16 @@ yylex ()
 	yylval.lval = tokentab_big[i].opcode;
 	if (yylval.lval == D_COMP_CONSTRUCTION_VTABLE)
 	  return CONSTRUCTION_VTABLE;
+	else if (yylval.lval == GLOBAL_CONSTRUCTORS
+		 || yylval.lval == GLOBAL_DESTRUCTORS)
+	  {
+	    /* Skip the trailing space, find the end of the symbol.  */
+	    char *p = symbol_end (lexptr + 1);
+	    yylval.typed_val_int.val = yylval.lval;
+	    yylval.typed_val_int.type = d_make_name (di, lexptr + 1, p - (lexptr + 1));
+	    lexptr = p;
+	    return GLOBAL;
+	  }
 	return DEMANGLER_SPECIAL;
       }  
 
@@ -2004,14 +2053,22 @@ cp_print (struct d_comp *result)
   return str3;
 }
 
-static char
-trim_chars (char *lexptr, char **extra_chars)
+static char *
+symbol_end (char *lexptr)
 {
   char *p = lexptr;
-  char c = 0;
 
   while (*p && (ISALNUM (*p) || *p == '_' || *p == '$' || *p == '.'))
     p++;
+
+  return p;
+}
+
+static char
+trim_chars (char *lexptr, char **extra_chars)
+{
+  char *p = symbol_end (lexptr);
+  char c = 0;
 
   if (*p)
     {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]