This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH]: Fix bugs 508, 510, 512
- To: gcc-patches at gcc dot gnu dot org
- Subject: [C++ PATCH]: Fix bugs 508, 510, 512
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Mon, 11 Sep 2000 15:30:31 +0100
- Organization: Codesourcery LLC
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 (¤t_declspecs, 1);
ggc_add_tree_root (&prefix_attributes, 1);
ggc_add_tree_root (¤t_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> > ();