This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


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

[C++ PATCH]: Fix bugs 508, 510, 512


Hi,
I've installed the attached patch for bugs 508, 510 & 512. operator names
are built up by bison, not by the lexer and there's some icky hackery
in the lexer to deal with qualified ids & templates. This patch makes
that same hackery work for operator names.

built & tested on i686-pc-linux-gnu, approved by Mark.

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2000-09-07  Nathan Sidwell  <nathan@codesourcery.com>

	* cp-tree.h (frob_opname): Declare.
	* parse.y (saved_scopes): New static variable.
	(cp_parse_init): Adjust.
	(do_id): If lastiddecl is NULL, do do_identifier.
	(operator): Save scope information.
	(unoperator): new reduction. Restore scope information.
	(operator_name): Append unoperator. Call frob_opname.
	* spew.c (frob_opname): Define.

Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.526
diff -c -3 -p -r1.526 cp-tree.h
*** cp-tree.h	2000/09/07 06:55:51	1.526
--- cp-tree.h	2000/09/07 15:37:28
*************** extern void init_spew				PARAMS ((void))
*** 4386,4391 ****
--- 4386,4392 ----
  extern int peekyylex				PARAMS ((void));
  extern int yylex				PARAMS ((void));
  extern tree arbitrate_lookup			PARAMS ((tree, tree, tree));
+ extern tree frob_opname                         PARAMS ((tree));
  
  /* in tree.c */
  extern void init_tree			        PARAMS ((void));
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v
retrieving revision 1.194
diff -c -3 -p -r1.194 parse.y
*** parse.y	2000/09/07 00:37:13	1.194
--- parse.y	2000/09/07 15:37:32
*************** static tree prefix_attributes;
*** 78,83 ****
--- 78,87 ----
  /* When defining an enumeration, this is the type of the enumeration.  */
  static tree current_enum_type;
  
+ /* When parsing a conversion operator name, this is the scope of the
+    operator itself.  */
+ static tree saved_scopes;
+ 
  static tree empty_parms PARAMS ((void));
  static tree parse_decl0 PARAMS ((tree, tree, tree, tree, int));
  static tree parse_decl PARAMS ((tree, tree, int));
*************** cp_parse_init ()
*** 208,213 ****
--- 212,218 ----
    ggc_add_tree_root (&current_declspecs, 1);
    ggc_add_tree_root (&prefix_attributes, 1);
    ggc_add_tree_root (&current_enum_type, 1);
+   ggc_add_tree_root (&saved_scopes, 1);
  }
  %}
  
*************** do_id:
*** 1437,1443 ****
  		     means that we're in an expression like S::f<int>, so
  		     don't do_identifier; we only do that for unqualified
  		     identifiers.  */
! 		  if (lastiddecl && TREE_CODE (lastiddecl) != TREE_LIST)
  		    $$ = do_identifier ($<ttype>-1, 1, NULL_TREE);
  		  else
  		    $$ = $<ttype>-1;
--- 1442,1448 ----
  		     means that we're in an expression like S::f<int>, so
  		     don't do_identifier; we only do that for unqualified
  		     identifiers.  */
! 	          if (!lastiddecl || TREE_CODE (lastiddecl) != TREE_LIST)
  		    $$ = do_identifier ($<ttype>-1, 1, NULL_TREE);
  		  else
  		    $$ = $<ttype>-1;
*************** conversion_declarator:
*** 3746,3827 ****
  	;
  
  operator:
! 	  OPERATOR
! 		{ got_scope = NULL_TREE; }
! 	;
  
  operator_name:
! 	  operator '*'
! 		{ $$ = ansi_opname (MULT_EXPR); }
! 	| operator '/'
! 		{ $$ = ansi_opname (TRUNC_DIV_EXPR); }
! 	| operator '%'
! 		{ $$ = ansi_opname (TRUNC_MOD_EXPR); }
! 	| operator '+'
! 		{ $$ = ansi_opname (PLUS_EXPR); }
! 	| operator '-'
! 		{ $$ = ansi_opname (MINUS_EXPR); }
! 	| operator '&'
! 		{ $$ = ansi_opname (BIT_AND_EXPR); }
! 	| operator '|'
! 		{ $$ = ansi_opname (BIT_IOR_EXPR); }
! 	| operator '^'
! 		{ $$ = ansi_opname (BIT_XOR_EXPR); }
! 	| operator '~'
! 		{ $$ = ansi_opname (BIT_NOT_EXPR); }
! 	| operator ','
! 		{ $$ = ansi_opname (COMPOUND_EXPR); }
! 	| operator ARITHCOMPARE
! 		{ $$ = ansi_opname ($2); }
! 	| operator '<'
! 		{ $$ = ansi_opname (LT_EXPR); }
! 	| operator '>'
! 		{ $$ = ansi_opname (GT_EXPR); }
! 	| operator EQCOMPARE
! 		{ $$ = ansi_opname ($2); }
! 	| operator ASSIGN
! 		{ $$ = ansi_assopname ($2); }
! 	| operator '='
! 		{ $$ = ansi_assopname (NOP_EXPR); }
! 	| operator LSHIFT
! 		{ $$ = ansi_opname ($2); }
! 	| operator RSHIFT
! 		{ $$ = ansi_opname ($2); }
! 	| operator PLUSPLUS
! 		{ $$ = ansi_opname (POSTINCREMENT_EXPR); }
! 	| operator MINUSMINUS
! 		{ $$ = ansi_opname (PREDECREMENT_EXPR); }
! 	| operator ANDAND
! 		{ $$ = ansi_opname (TRUTH_ANDIF_EXPR); }
! 	| operator OROR
! 		{ $$ = ansi_opname (TRUTH_ORIF_EXPR); }
! 	| operator '!'
! 		{ $$ = ansi_opname (TRUTH_NOT_EXPR); }
! 	| operator '?' ':'
! 		{ $$ = ansi_opname (COND_EXPR); }
! 	| operator MIN_MAX
! 		{ $$ = ansi_opname ($2); }
! 	| operator POINTSAT  %prec EMPTY
! 		{ $$ = ansi_opname (COMPONENT_REF); }
! 	| operator POINTSAT_STAR  %prec EMPTY
! 		{ $$ = ansi_opname (MEMBER_REF); }
! 	| operator LEFT_RIGHT
! 		{ $$ = ansi_opname (CALL_EXPR); }
! 	| operator '[' ']'
! 		{ $$ = ansi_opname (ARRAY_REF); }
! 	| operator NEW  %prec EMPTY
! 		{ $$ = ansi_opname (NEW_EXPR); }
! 	| operator DELETE  %prec EMPTY
! 		{ $$ = ansi_opname (DELETE_EXPR); }
! 	| operator NEW '[' ']'
! 		{ $$ = ansi_opname (VEC_NEW_EXPR); }
! 	| operator DELETE '[' ']'
! 		{ $$ = ansi_opname (VEC_DELETE_EXPR); }
  	/* Names here should be looked up in class scope ALSO.  */
! 	| operator type_specifier_seq conversion_declarator
! 		{ $$ = grokoptypename ($2.t, $3); }
! 	| operator error
! 		{ $$ = ansi_opname (ERROR_MARK); }
  	;
  
  %%
--- 3751,3838 ----
  	;
  
  operator:
!         OPERATOR
!         { saved_scopes = tree_cons (got_scope, got_object, saved_scopes); 
!           got_scope = NULL_TREE; got_object = NULL_TREE; }
!         ;
! unoperator:
!         { got_scope = TREE_PURPOSE (saved_scopes);
!           got_object = TREE_VALUE (saved_scopes);
!           saved_scopes = TREE_CHAIN (saved_scopes); }
!         ;
  
  operator_name:
! 	  operator '*' unoperator
! 		{ $$ = frob_opname (ansi_opname (MULT_EXPR)); }
! 	| operator '/' unoperator
! 		{ $$ = frob_opname (ansi_opname (TRUNC_DIV_EXPR)); }
! 	| operator '%' unoperator
! 		{ $$ = frob_opname (ansi_opname (TRUNC_MOD_EXPR)); }
! 	| operator '+' unoperator
! 		{ $$ = frob_opname (ansi_opname (PLUS_EXPR)); }
! 	| operator '-' unoperator
! 		{ $$ = frob_opname (ansi_opname (MINUS_EXPR)); }
! 	| operator '&' unoperator
! 		{ $$ = frob_opname (ansi_opname (BIT_AND_EXPR)); }
! 	| operator '|' unoperator
! 		{ $$ = frob_opname (ansi_opname (BIT_IOR_EXPR)); }
! 	| operator '^' unoperator
! 		{ $$ = frob_opname (ansi_opname (BIT_XOR_EXPR)); }
! 	| operator '~' unoperator
! 		{ $$ = frob_opname (ansi_opname (BIT_NOT_EXPR)); }
! 	| operator ',' unoperator
! 		{ $$ = frob_opname (ansi_opname (COMPOUND_EXPR)); }
! 	| operator ARITHCOMPARE unoperator
! 		{ $$ = frob_opname (ansi_opname ($2)); }
! 	| operator '<' unoperator
! 		{ $$ = frob_opname (ansi_opname (LT_EXPR)); }
! 	| operator '>' unoperator
! 		{ $$ = frob_opname (ansi_opname (GT_EXPR)); }
! 	| operator EQCOMPARE unoperator
! 		{ $$ = frob_opname (ansi_opname ($2)); }
! 	| operator ASSIGN unoperator
! 		{ $$ = frob_opname (ansi_assopname ($2)); }
! 	| operator '=' unoperator
! 		{ $$ = frob_opname (ansi_assopname (NOP_EXPR)); }
! 	| operator LSHIFT unoperator
! 		{ $$ = frob_opname (ansi_opname ($2)); }
! 	| operator RSHIFT unoperator
! 		{ $$ = frob_opname (ansi_opname ($2)); }
! 	| operator PLUSPLUS unoperator
! 		{ $$ = frob_opname (ansi_opname (POSTINCREMENT_EXPR)); }
! 	| operator MINUSMINUS unoperator
! 		{ $$ = frob_opname (ansi_opname (PREDECREMENT_EXPR)); }
! 	| operator ANDAND unoperator
! 		{ $$ = frob_opname (ansi_opname (TRUTH_ANDIF_EXPR)); }
! 	| operator OROR unoperator
! 		{ $$ = frob_opname (ansi_opname (TRUTH_ORIF_EXPR)); }
! 	| operator '!' unoperator
! 		{ $$ = frob_opname (ansi_opname (TRUTH_NOT_EXPR)); }
! 	| operator '?' ':' unoperator
! 		{ $$ = frob_opname (ansi_opname (COND_EXPR)); }
! 	| operator MIN_MAX unoperator
! 		{ $$ = frob_opname (ansi_opname ($2)); }
! 	| operator POINTSAT  unoperator %prec EMPTY
! 		{ $$ = frob_opname (ansi_opname (COMPONENT_REF)); }
! 	| operator POINTSAT_STAR  unoperator %prec EMPTY
! 		{ $$ = frob_opname (ansi_opname (MEMBER_REF)); }
! 	| operator LEFT_RIGHT unoperator
! 		{ $$ = frob_opname (ansi_opname (CALL_EXPR)); }
! 	| operator '[' ']' unoperator
! 		{ $$ = frob_opname (ansi_opname (ARRAY_REF)); }
! 	| operator NEW  unoperator %prec EMPTY
! 		{ $$ = frob_opname (ansi_opname (NEW_EXPR)); }
! 	| operator DELETE  unoperator %prec EMPTY
! 		{ $$ = frob_opname (ansi_opname (DELETE_EXPR)); }
! 	| operator NEW '[' ']' unoperator
! 		{ $$ = frob_opname (ansi_opname (VEC_NEW_EXPR)); }
! 	| operator DELETE '[' ']' unoperator
! 		{ $$ = frob_opname (ansi_opname (VEC_DELETE_EXPR)); }
  	/* Names here should be looked up in class scope ALSO.  */
! 	| operator type_specifier_seq conversion_declarator unoperator
! 		{ $$ = frob_opname (grokoptypename ($2.t, $3)); }
! 	| operator error unoperator
! 		{ $$ = frob_opname (ansi_opname (ERROR_MARK)); }
  	;
  
  %%
Index: cp/spew.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/spew.c,v
retrieving revision 1.30
diff -c -3 -p -r1.30 spew.c
*** spew.c	2000/09/07 00:37:13	1.30
--- spew.c	2000/09/07 15:37:32
*************** yyungetc (ch, rescan)
*** 938,943 ****
--- 938,979 ----
      }
  }
  
+ /* ID is an operator name. Duplicate the hackery in yylex to determine what
+    it really is.  */
+ 
+ tree frob_opname (id)
+      tree id;
+ {
+   tree trrr;
+   
+   if (yychar == '<')
+     looking_for_template = 1;
+   trrr = lookup_name (id, -2);
+   if (trrr)
+     {
+       switch (identifier_type (trrr))
+         {
+           case TYPENAME:
+           case SELFNAME:
+           case NSNAME:
+           case PTYPENAME:
+             if (got_scope || got_object)
+               id = trrr;
+           case PFUNCNAME:
+           case IDENTIFIER:
+             lastiddecl = trrr;
+             break;
+           default:
+             my_friendly_abort (20000907);
+         }
+     }
+   else
+     lastiddecl = NULL_TREE;
+   got_scope = NULL_TREE;
+   got_object = NULL_TREE;
+   looking_for_template = 0;
+   return id;
+ }
  
  /* Set up the state required to correctly handle the definition of the
     inline function whose preparsed state has been saved in PI.  */
// Build don't link:
// Copyright (C) 2000 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 7 Sep 2000 <nathan@codesourcery.com>

// Bug 508. We failed to set/clear lastiddecl appropriately for
// operator names.

struct A {};

template <typename N> void foo (A, int);
template <typename N> void operator<< (A, int);

int main()
{ 
        A a;
        operator<< <bool>(a, 0); 
        foo <bool>(a, 0); 
}
// Build don't link:
// Copyright (C) 2000 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 7 Sep 2000 <nathan@codesourcery.com>

// Bug 512. Conversion operator functions in template_id's were always
// being looked up in global scope.

class C
{
public:

  template <typename T>
  void f () {}

  template<typename T>
  operator int ()
  { return 0;
  }
};

template void C::f <int>();

template C::operator int<float> ();

template C::operator int<double> ();

typedef int (C::* ptrmem_t) ();

template<ptrmem_t U, ptrmem_t V>
void foo ()
{
}

template void 
foo<&C::operator int<float>, &C::operator int<double> > ();

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