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] Conversion operators, at last


The last piece.  With this, and a local demangler patch that I need to
either obsolete or submit, I no longer have any mangled name testcases that
I can't parse.

This takes advantage of the fact that, as far as I know, there is no way for
an operator name to end up mangled without its argument list.  This means
that while user input like:
  break Foo::operator++
will work and bring up an overload resolution list, to get at
"Foo::operator int (*)(int) ()" you'll have to say:
  break Foo::operator int (*)(int) ()

There are more elegant solutions possible and I'm still thinking about them;
really it ought to be possible, because in:
  Foo::operator int (*)(int)
it's obvious that we don't have a "spare" function argument list to belong
to the operator.  The problem here is with the other gross hack I added
today for function local variables.  Hmm...

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

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

	* cp-names.y (%union): Add abstract_fn.
	(conversion_op): New non-terminal, broken out of operator.
	(conversion_op_name, abstract_declarator_fn): New non-terminals.
	(ptr_operator_seq): Remove.
	(function): Use D_COMP_LOCAL_NAME.  Handle conversion operators.
	(declarator_1): Use D_COMP_LOCAL_NAME.
	(tokentab2, tokentab3): Remove.
	(HANDLE_TOKEN3): Fix typo.
	(yylex): Call HANDLE_TOKEN3 before HANDLE_TOKEN2.

Index: cp-names.y
===================================================================
RCS file: /cvs/src/src/gdb/Attic/cp-names.y,v
retrieving revision 1.1.2.10
diff -u -p -r1.1.2.10 cp-names.y
--- cp-names.y	20 Dec 2003 06:05:40 -0000	1.1.2.10
+++ cp-names.y	20 Dec 2003 06:05:56 -0000
@@ -182,6 +182,9 @@ void yyerror (char *);
     struct {
       struct d_comp *comp, *last;
     } nested1;
+    struct {
+      struct d_comp *comp, **last, *fn;
+    } abstract_fn;
     LONGEST lval;
     struct {
       LONGEST val;
@@ -202,15 +205,17 @@ static int parse_number (char *, int, in
 %type <comp> typespec typespec_2 array_indicator
 %type <comp> colon_ext_only ext_only_name
 
-%type <comp> demangler_special function
+%type <comp> demangler_special function conversion_op
+%type <nested> conversion_op_name
 
 %type <nested> abstract_declarator direct_abstract_declarator
+%type <abstract_fn> abstract_declarator_fn
 %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
+%type <nested> ptr_operator
 
 %type <nested1> nested_name
 
@@ -320,10 +325,23 @@ function
 		   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); }
+			  if ($3) $$ = d_make_comp (di, D_COMP_LOCAL_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); }
+			  if ($3) $$ = d_make_comp (di, D_COMP_LOCAL_NAME, $$, $3); }
+
+		|	conversion_op_name abstract_declarator_fn start_opt
+			{ if ($2.last)
+			    {
+			       /* First complete the abstract_declarator's type using
+				  the typespec from the conversion_op_name.  */
+			      *$2.last = *$1.last;
+			      /* Then complete the conversion_op_name with the type.  */
+			      *$1.last = $2.comp;
+			    }
+			  /* Then finally build the function.  */
+			  $$ = d_make_comp (di, D_COMP_TYPED_NAME, $1.comp, $2.fn);
+			  if ($3) $$ = d_make_comp (di, D_COMP_LOCAL_NAME, $$, $3); }
 
 		;
 
@@ -406,15 +424,35 @@ 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
+conversion_op
+		:	OPERATOR typespec_2
 			{ $$ = d_make_comp (di, D_COMP_CAST, $2, NULL); }
-		|	OPERATOR typespec_2 ptr_operator_seq
-			{ *$3.last = $2;
-			  $$ = d_make_comp (di, D_COMP_CAST, $3.comp, NULL); }
+		;
+
+conversion_op_name
+		:	nested_name conversion_op
+			{ $$.comp = $1.comp;
+			  d_right ($1.last) = $2;
+			  $$.last = &d_left ($2);
+			}
+		|	conversion_op
+			{ $$.comp = $1;
+			  $$.last = &d_left ($1);
+			}
+		|	COLONCOLON nested_name conversion_op
+			{ $$.comp = $2.comp;
+			  d_right ($2.last) = $3;
+			  $$.last = &d_left ($3);
+			}
+		|	COLONCOLON conversion_op
+			{ $$.comp = $2;
+			  $$.last = &d_left ($2);
+			}
 		;
 
 /* D_COMP_NAME */
@@ -657,13 +695,6 @@ ptr_operator	:	'*' qualifiers_opt
 			  $$.comp = d_qualify ($$.comp, $4, 0); }
 		;
 
-ptr_operator_seq:	ptr_operator
-		|	ptr_operator_seq ptr_operator
-			{ $$.comp = $1.comp;
-			  $$.last = $2.last;
-			  *$1.last = $2.comp; }
-		;
-
 array_indicator	:	'[' ']'
 			{ $$ = d_make_empty (di, D_COMP_ARRAY_TYPE);
 			  d_left ($$) = NULL;
@@ -722,6 +753,30 @@ direct_abstract_declarator
 		/* |	function_arglist */
 		;
 
+abstract_declarator_fn
+		:	function_arglist
+			{ $$.fn = $1.comp;
+			  $$.comp = NULL;
+			  $$.last = NULL;
+			}
+		|	ptr_operator abstract_declarator_fn
+			{ $$.fn = $2.fn;
+			  $$.last = $1.last;
+			  if ($2.comp)
+			    {
+			      $$.comp = $2.comp;
+			      *$2.last = $1.comp;
+			    }
+			  else
+			    $$.comp = $1.comp;
+			}
+		|	direct_abstract_declarator function_arglist
+			{ $$.fn = $2.comp;
+			  $$.comp = $1.comp;
+			  $$.last = $1.last;
+			}
+		;
+
 type		:	typespec_2
 		|	typespec_2 abstract_declarator
 			{ $$ = $2.comp;
@@ -781,7 +836,7 @@ declarator_1	:	ptr_operator declarator_1
 		|	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);
+			  $$.comp = d_make_comp (di, D_COMP_LOCAL_NAME, $$.comp, $4);
 			}
 		;
 
@@ -1432,7 +1487,7 @@ struct token
 #define HANDLE_TOKEN3(string, token, op)		\
   if (lexptr[1] == string[1] && lexptr[2] == string[2])	\
     {							\
-      lexptr += 2;					\
+      lexptr += 3;					\
       yylval.opname = string;				\
       return token;					\
     }      
@@ -1647,15 +1702,15 @@ yylex (void)
       lexptr++;
       return c;
     case '<':
+      HANDLE_TOKEN3 ("<<=", ASSIGN_MODIFY, BINOP_LSH);
       HANDLE_TOKEN2 ("<=", LEQ, BINOP_END);
       HANDLE_TOKEN2 ("<<", LSH, BINOP_END);
-      HANDLE_TOKEN3 ("<<=", ASSIGN_MODIFY, BINOP_LSH);
       lexptr++;
       return c;
     case '>':
+      HANDLE_TOKEN3 (">>=", ASSIGN_MODIFY, BINOP_RSH);
       HANDLE_TOKEN2 (">=", GEQ, BINOP_END);
       HANDLE_TOKEN2 (">>", RSH, BINOP_END);
-      HANDLE_TOKEN3 (">>=", ASSIGN_MODIFY, BINOP_RSH);
       lexptr++;
       return c;
     case '=':


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