[cplus] Handle functions without a return type

Daniel Jacobowitz drow@mvista.com
Fri Dec 19 04:21:00 GMT 2003


This proved to be quite tricky.  I think I didn't butcher anything in my
declarator handling fixing it.

I've also added a mode in which it behaves like c++filt, for testing with
Michael Chastain's unspeakably awesome demangler tester.  It caught the
BOOL/CHAR typo below.  I still have a ways to go:
   5258    5258  501828 b-different.list
  15040   15040 1149943 b-identical.list
   3365    3365 1853207 b-similar.list

But I know what most of the remaining problems are now, so I'm checking in
this much of the work.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

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

	* cp-names.y (ext_name): Remove.
	(colon_ext_only, ext_only_name): New non-terminals.
	(colon_ext_name): Use colon_ext_only.
	(declarator_1, direct_declarator_1): New non-terminals.
	('('): Remove %right precedence.
	(result): New non-terminal.
	(start): Assign to $$.  Use declarator_1.  Handle functions
	without return types.
	(template_arg): Use start instead of colon_ext_name.
	(yylex): Fix typo in "char" case.
	(yyerror): Add newline.
	(main): Behave like c++filt when started with no arguments.

Index: cp-names.y
===================================================================
RCS file: /cvs/src/src/gdb/Attic/cp-names.y,v
retrieving revision 1.1.2.5
diff -u -p -r1.1.2.5 cp-names.y
--- cp-names.y	18 Dec 2003 16:32:12 -0000	1.1.2.5
+++ cp-names.y	19 Dec 2003 04:15:06 -0000
@@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place - Suit
    with include files (<malloc.h> and <stdlib.h> for example) just became
    too messy, particularly when such includes can be inserted at random
    times by the parser generator.  */
-   
+
 %{
 
 #include <stdio.h>
@@ -196,14 +196,17 @@ static int parse_number (char *, int, in
 %}
 
 %type <comp> exp exp1 type start operator colon_name
-%type <comp> unqualified_name scope_id ext_name colon_ext_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 <nested> abstract_declarator direct_abstract_declarator
 %type <nested> declarator direct_declarator function_arglist
 
+%type <nested> declarator_1 direct_declarator_1
+
 %type <nested> template_params function_args
 %type <nested> ptr_operator ptr_operator_seq
 
@@ -261,18 +264,35 @@ static int parse_number (char *, int, in
 %left '+' '-'
 %left '*' '/' '%'
 %right UNARY INCREMENT DECREMENT
-%right ARROW '.' '[' '('
+
+/* We don't need a precedence for '(' in this reduced grammar, and it
+   can mask some unpleasant bugs, so disable it for now.  */
+
+%right ARROW '.' '[' /* '(' */
 %left COLONCOLON
 
 
 %%
 
-start		:	type
+result		:	start
 			{ result = $1; }
-		|	typespec_2 declarator
-			{ result = $2.comp;
+
+start		:	type
+			{ $$ = $1; }
+
+		/* Function with a return type.  declarator_1 is used to prevent
+		   ambiguity with the next rule.  */
+		|	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); }
 		;
 
 operator	:	OPERATOR NEW
@@ -371,13 +391,16 @@ name		:	nested_name scope_id %prec NAME
 		|	scope_id %prec NAME
 		;
 
-colon_ext_name	:	ext_name
-		|	COLONCOLON ext_name
+colon_ext_name	:	colon_name
+		|	colon_ext_only
+		;
+
+colon_ext_only	:	ext_only_name
+		|	COLONCOLON ext_only_name
 			{ $$ = $2; }
 		;
 
-ext_name	:	name
-		|	nested_name unqualified_name
+ext_only_name	:	nested_name unqualified_name
 			{ $$ = $1.comp; d_right ($1.last) = $2; }
 		|	unqualified_name
 		;
@@ -414,9 +437,9 @@ template_params	:	template_arg
 /* Also an integral constant-expression of integral type, and a
    pointer to member (?) */
 template_arg	:	type
-		|	'&' colon_ext_name
+		|	'&' start
 			{ $$ = d_make_comp (di, D_COMP_REFERENCE, $2, NULL); }
-		|	'&' '(' colon_ext_name ')'
+		|	'&' '(' start ')'
 			{ $$ = d_make_comp (di, D_COMP_REFERENCE, $3, NULL); }
 		|	exp
 		;
@@ -675,6 +698,49 @@ direct_declarator
 			}
 		;
 
+/* These are similar to declarator and direct_declarator except that they
+   do not permit ( colon_ext_name ), which is ambiguous with a function
+   argument list.  They also don't permit a few other forms with redundant
+   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
+			{ $$.comp = $2.comp;
+			  $$.last = $1.last;
+			  *$2.last = $1.comp; }
+		|	colon_ext_name
+			{ $$.comp = d_make_empty (di, D_COMP_TYPED_NAME);
+			  d_left ($$.comp) = $1;
+			  $$.last = &d_right ($$.comp);
+			}
+		|	direct_declarator_1
+		;
+
+direct_declarator_1
+		:	'(' ptr_operator declarator ')'
+			{ $$.comp = $3.comp;
+			  $$.last = $2.last;
+			  *$3.last = $2.comp; }
+		|	direct_declarator_1 function_arglist
+			{ $$.comp = $1.comp;
+			  *$1.last = $2.comp;
+			  $$.last = $2.last;
+			}
+		|	direct_declarator_1 array_indicator
+			{ $$.comp = $1.comp;
+			  *$1.last = $2;
+			  $$.last = &d_left ($2);
+			}
+		|	colon_ext_name function_arglist
+			{ $$.comp = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2.comp);
+			  $$.last = $2.last;
+			}
+		|	colon_ext_name array_indicator
+			{ $$.comp = d_make_comp (di, D_COMP_TYPED_NAME, $1, $2);
+			  $$.last = &d_left ($2);
+			}
+		;
+
 exp	:	'(' exp1 ')'
 		{ $$ = $2; }
 	;
@@ -1761,7 +1827,7 @@ yylex ()
       if (strncmp (tokstart, "bool", 4) == 0)
 	return BOOL;
       if (strncmp (tokstart, "char", 4) == 0)
-	return BOOL;
+	return CHAR;
       if (strncmp (tokstart, "enum", 4) == 0)
 	return ENUM;
       if (strncmp (tokstart, "long", 4) == 0)
@@ -1790,23 +1856,51 @@ yyerror (msg)
   if (prev_lexptr)
     lexptr = prev_lexptr;
 
-  error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+  error ("A %s in expression, near `%s'.\n", (msg ? msg : "error"), lexptr);
 }
 
 #ifdef TEST_CPNAMES
 
-int main(int argc, char **argv)
+int
+main (int argc, char **argv)
 {
   struct d_info myinfo;
   int err = 0;
-  char *str;
-
-  lexptr = argv[1];
-  d_init_info (NULL, DMGL_PARAMS | DMGL_ANSI, 2 * strlen (lexptr), &myinfo);
-  di = &myinfo;
-  yyparse ();
-  str = d_print (DMGL_PARAMS | DMGL_ANSI, result, &err);
-  printf ("Result is %s\n", str);
+  char *str, *str2;
+  char buf[65536];
+  
+  if (argv[1] == NULL)
+    while (fgets (buf, 65536, stdin) != NULL)
+      {
+	result = NULL;
+	buf[strlen (buf) - 1] = 0;
+	str2 = cplus_demangle (buf, DMGL_PARAMS | DMGL_ANSI);
+	lexptr = str2;
+	if (lexptr == NULL)
+	  {
+	    printf ("Demangling error\n");
+	    continue;
+	  }
+	d_init_info (NULL, DMGL_PARAMS | DMGL_ANSI, 2 * strlen (lexptr), &myinfo);
+	di = &myinfo;
+	if (yyparse () || result == NULL)
+	  continue;
+	str = d_print (DMGL_PARAMS | DMGL_ANSI, result, &err);
+	free (str2);
+	printf ("%s\n", str);
+	free (str);
+      }
+  else
+    {
+      lexptr = argv[1];
+      d_init_info (NULL, DMGL_PARAMS | DMGL_ANSI, 2 * strlen (lexptr), &myinfo);
+      di = &myinfo;
+      if (yyparse () || result == NULL)
+	return 0;
+      str = d_print (DMGL_PARAMS | DMGL_ANSI, result, &err);
+      printf ("%s\n", str);
+      free (str);
+    }
   return 0;
 }
 



More information about the Gdb-patches mailing list