]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cp-tree.h (ansi_opname): Make it a macro.
authorAlex Samuel <samuel@codesourcery.com>
Sun, 28 May 2000 02:58:19 +0000 (02:58 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 28 May 2000 02:58:19 +0000 (02:58 +0000)
2000-05-27  Alex Samuel    <samuel@codesourcery.com>
    Mark Mitchell  <mark@codesourcery.com>

* cp-tree.h (ansi_opname): Make it a macro.
(ansi_assopname): Likewise.
(struct lang_decl_flags): Add assignment_operator_p.
(struct lang_decl): Add operator_code.
(DECL_VTT_PARM): Adjust.
(DECL_OVERLOADED_OPERATOR_P): Return the operator_code for an
overloaded operator.
(SET_OVERLOADED_OPERATOR_CODE): New macro.
(DECL_ASSIGNMENT_OPERATOR_P): New macro.
(DECL_ARRAY_DELETE_OPERATOR_P): Adjust.
(opname_tab): Remove.
(assignop_tab): Likewise.
(operator_name_info_t): New type.
(operator_name_info): New variable.
(assignment_operator_name_info): Likewise.
(build_cp_library_fn): Remove declaration.
(push_cp_library_fn): Likewise.
(operator_name_string): Likewise.
(build_decl_overload): Likewise.
* call.c (print_z_candidates): Simplify.
(build_object_call): Adjust usage of ansi_opname.  Use
DECL_OVERLOADED_OPERATOR_P.
(op_error): Adjust operator name lookup.
(build_conditional_expr): Adjust usage of ansi_opname.
(build_new_op): Likewise.
(build_op_delete_call): Likewise.
(build_over_call): Likewise.
(joust): Use DECL_OVERLOADED_OPERATOR_P.
* decl.c (duplicate_decls): Copy operator_code.
(init_decl_processing): Adjust parameters to push_cp_library_fn.
(builtin_function): Adjust parameters to build_library_fn_1.
(build_library_fn_1): Accept an overloaded operator code.
(build_library_fn): Pass ERROR_MARK.
(build_cp_library_fn): Accept an overloaded operator code.
(push_cp_library_fn): Likewise.
(grokfndecl): Tweak.
(grokdeclarator): Simplify code to compute names of overloaded
operators.  Adjust use of ansi_opname.
(ambi_op_p): Work on tree_codes, not identifiers.
(unary_op_p): Likewise.
(grok_op_properties): Likewise.
(start_function): Use DECL_OVERLOADED_OPERATOR_P.
(lang_mark_tree): Don't try to mark the operator_code.
* decl2.c (grok_function_init): Use DECL_OVERLOADED_OPERATOR_P.
* error.c (dump_decl): Remove special handling for operator
names.
(dump_function_name): Likewise.
(dump_expr): Adjust name lookup of operators.
(op_to_string): Simplify.
(assop_to_string): Likewise.
* init.c (build_new_1): Adjust use of ansi_opname.
* lex.c (opname_tab): Remove.
(assignop_tab): Likewise.
(ansi_opname): Likewise.
(ansi_assopname): Likewise.
(operator_name_string): Likewise.
(reinit_lang_specific): Likewise.
(operator_name_info): New variable.
(assignment_operator_name_info): Likewise.
(init_operators): New function.
(init_parse): Use it.
(do_identifier): Adjust use of ansi_opname.
* method.c (mangle_expression): Don't use ansi_opname for
mangling.
(build_decl_overload_real): Use DECL_OVERLOADED_OPERATOR_P.
(build_decl_overload): Remove.
(build_typename_overload): Use OPERATOR_TYPENAME_FORMAT directly.
(do_build_assign_ref): Adjust use of ansi_opname.
(synthesize_method): Likewise.
(implicitly_declare_fn): Likewise.
* operators.def: New file.
* parse.y (operator): Adjust use of ansi_opname.
* pt.c (tsubst_decl): Use IDENTIFIER_OPNAME_P.
(set_mangled_name_for_template_decl): Don't play games with
current_namespace.
(special_function_p): Adjust use of ansi_opname.
* typeck.c (check_return_expr): Likewise.
* Make-lang.in (cc1plus): Depend on operators.def.
* Makefile.in (lex.o): Likewise.
(decl.o): Likewise.

Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r34223

18 files changed:
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/Makefile.in
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/operators.def [new file with mode: 0644]
gcc/cp/parse.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.other/op1.C [new file with mode: 0644]

index d843b3e77d151f5a4cf16dcf8091aff498dafc2f..08a9bcea04ed8158445480a63809b3b2a525ea24 100644 (file)
@@ -1,3 +1,87 @@
+2000-05-27  Alex Samuel    <samuel@codesourcery.com>
+           Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (ansi_opname): Make it a macro.
+       (ansi_assopname): Likewise.
+       (struct lang_decl_flags): Add assignment_operator_p.
+       (struct lang_decl): Add operator_code.
+       (DECL_VTT_PARM): Adjust.
+       (DECL_OVERLOADED_OPERATOR_P): Return the operator_code for an
+       overloaded operator.
+       (SET_OVERLOADED_OPERATOR_CODE): New macro.
+       (DECL_ASSIGNMENT_OPERATOR_P): New macro.
+       (DECL_ARRAY_DELETE_OPERATOR_P): Adjust.
+       (opname_tab): Remove.
+       (assignop_tab): Likewise.
+       (operator_name_info_t): New type.
+       (operator_name_info): New variable.
+       (assignment_operator_name_info): Likewise.
+       (build_cp_library_fn): Remove declaration.
+       (push_cp_library_fn): Likewise.
+       (operator_name_string): Likewise.
+       (build_decl_overload): Likewise.
+       * call.c (print_z_candidates): Simplify.
+       (build_object_call): Adjust usage of ansi_opname.  Use
+       DECL_OVERLOADED_OPERATOR_P.
+       (op_error): Adjust operator name lookup.
+       (build_conditional_expr): Adjust usage of ansi_opname.
+       (build_new_op): Likewise.
+       (build_op_delete_call): Likewise.
+       (build_over_call): Likewise.
+       (joust): Use DECL_OVERLOADED_OPERATOR_P.
+       * decl.c (duplicate_decls): Copy operator_code.
+       (init_decl_processing): Adjust parameters to push_cp_library_fn.
+       (builtin_function): Adjust parameters to build_library_fn_1.
+       (build_library_fn_1): Accept an overloaded operator code.
+       (build_library_fn): Pass ERROR_MARK.
+       (build_cp_library_fn): Accept an overloaded operator code.
+       (push_cp_library_fn): Likewise.
+       (grokfndecl): Tweak.
+       (grokdeclarator): Simplify code to compute names of overloaded
+       operators.  Adjust use of ansi_opname.
+       (ambi_op_p): Work on tree_codes, not identifiers.
+       (unary_op_p): Likewise.
+       (grok_op_properties): Likewise.
+       (start_function): Use DECL_OVERLOADED_OPERATOR_P.
+       (lang_mark_tree): Don't try to mark the operator_code.
+       * decl2.c (grok_function_init): Use DECL_OVERLOADED_OPERATOR_P.
+       * error.c (dump_decl): Remove special handling for operator
+       names.
+       (dump_function_name): Likewise.
+       (dump_expr): Adjust name lookup of operators.
+       (op_to_string): Simplify.
+       (assop_to_string): Likewise.
+       * init.c (build_new_1): Adjust use of ansi_opname.
+       * lex.c (opname_tab): Remove.
+       (assignop_tab): Likewise.
+       (ansi_opname): Likewise.
+       (ansi_assopname): Likewise.
+       (operator_name_string): Likewise.
+       (reinit_lang_specific): Likewise.
+       (operator_name_info): New variable.
+       (assignment_operator_name_info): Likewise.
+       (init_operators): New function.
+       (init_parse): Use it.
+       (do_identifier): Adjust use of ansi_opname.
+       * method.c (mangle_expression): Don't use ansi_opname for
+       mangling.
+       (build_decl_overload_real): Use DECL_OVERLOADED_OPERATOR_P.
+       (build_decl_overload): Remove.
+       (build_typename_overload): Use OPERATOR_TYPENAME_FORMAT directly.
+       (do_build_assign_ref): Adjust use of ansi_opname.
+       (synthesize_method): Likewise.
+       (implicitly_declare_fn): Likewise.
+       * operators.def: New file.
+       * parse.y (operator): Adjust use of ansi_opname.
+       * pt.c (tsubst_decl): Use IDENTIFIER_OPNAME_P.
+       (set_mangled_name_for_template_decl): Don't play games with
+       current_namespace.
+       (special_function_p): Adjust use of ansi_opname.
+       * typeck.c (check_return_expr): Likewise.
+       * Make-lang.in (cc1plus): Depend on operators.def.
+       * Makefile.in (lex.o): Likewise.
+       (decl.o): Likewise.
+
 2000-05-27  Zack Weinberg  <zack@wolery.cumb.org>
 
        * Make-lang.in (cplib2.ready): Eradicate.
index e36dc5e263796ef0a3c915dcee541b0aa8bd0965..0d6fae85ceafcefb530ef226168783abc5a089de 100644 (file)
@@ -123,7 +123,8 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/class.c $(srcdir)/cp/cp-tree.def \
 
 cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o \
         c-pragma.o $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def \
-       $(srcdir)/cp/gxx.gperf $(srcdir)/cp/cfns.gperf hash.o
+       $(srcdir)/cp/gxx.gperf $(srcdir)/cp/cfns.gperf hash.o \
+       $(srcdir)/cp/operators.def
        cd cp; $(MAKE) $(LANG_FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus$(exeext)
 #\f
 # Build hooks:
index e8a43fa10d03cff114f518e63d100ca53b3ee868..5284e7d71000e6f174bc1278c3668be7ba8ae4c2 100644 (file)
@@ -254,11 +254,11 @@ lex.o : lex.c $(CXX_TREE_H) \
   $(PARSE_H) input.c $(srcdir)/../flags.h hash.h lex.h \
   $(srcdir)/../c-pragma.h $(srcdir)/../toplev.h \
   $(srcdir)/../output.h $(srcdir)/../mbchar.h $(GGC_H) \
-  $(srcdir)/../input.h
+  $(srcdir)/../input.h operators.def
 decl.o : decl.c $(CXX_TREE_H) $(srcdir)/../flags.h \
   lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h  \
   $(srcdir)/../except.h $(srcdir)/../toplev.h \
-  $(srcdir)/../hash.h $(GGC_H) $(RTL_H)
+  $(srcdir)/../hash.h $(GGC_H) $(RTL_H) operators.def
 decl2.o : decl2.c $(CXX_TREE_H) $(srcdir)/../flags.h \
   lex.h decl.h $(EXPR_H) $(srcdir)/../output.h $(srcdir)/../except.h \
   $(srcdir)/../toplev.h $(srcdir)/../dwarf2out.h $(srcdir)/../dwarfout.h \
index a034f5292a64031ae0ced5416dff40463f68e17f..2bd5c81843a9e43e5585843bdbcbe197766720e6 100644 (file)
@@ -2257,7 +2257,7 @@ print_z_candidates (candidates)
     {
       if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
        {
-         if (candidates->fn == ansi_opname [COND_EXPR])
+         if (TREE_VEC_LENGTH (candidates->convs) == 3)
            cp_error ("%s %D(%T, %T, %T) <builtin>", str, candidates->fn,
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
@@ -2609,7 +2609,7 @@ build_object_call (obj, args)
       return error_mark_node;
     }
 
-  fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 1);
+  fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname (CALL_EXPR), 1);
   if (fns == error_mark_node)
     return error_mark_node;
 
@@ -2689,7 +2689,7 @@ build_object_call (obj, args)
      function, we must be careful not to unconditionally look at
      DECL_NAME here.  */
   if (TREE_CODE (cand->fn) == FUNCTION_DECL
-      && DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
+      && DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
     return build_over_call (cand, mem_args, LOOKUP_NORMAL);
 
   obj = convert_like_with_context
@@ -2705,8 +2705,12 @@ op_error (code, code2, arg1, arg2, arg3, problem)
      tree arg1, arg2, arg3;
      const char *problem;
 {
-  const char * opname
-    = (code == MODIFY_EXPR ? assignop_tab [code2] : opname_tab [code]);
+  const char * opname;
+
+  if (code == MODIFY_EXPR)
+    opname = assignment_operator_name_info[code2].name;
+  else
+    opname = operator_name_info[code].name;
 
   switch (code)
     {
@@ -2987,7 +2991,7 @@ build_conditional_expr (arg1, arg2, arg3)
       candidates = add_builtin_candidates (candidates, 
                                           COND_EXPR, 
                                           NOP_EXPR,
-                                          ansi_opname[COND_EXPR],
+                                          ansi_opname (COND_EXPR),
                                           args,
                                           LOOKUP_NORMAL);
 
@@ -3166,10 +3170,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
     {
       code2 = TREE_CODE (arg3);
       arg3 = NULL_TREE;
-      fnname = ansi_assopname[code2];
+      fnname = ansi_assopname (code2);
     }
   else
-    fnname = ansi_opname[code];
+    fnname = ansi_opname (code);
 
   switch (code)
     {
@@ -3314,7 +3318,8 @@ build_new_op (code, flags, arg1, arg2, arg3)
             one, then we fall back to the old way of doing things.  */
          if (flags & LOOKUP_COMPLAIN)
            cp_pedwarn ("no `%D (int)' declared for postfix `%s', trying prefix operator instead",
-                       fnname, opname_tab [code]);
+                       fnname, 
+                       operator_name_info[code].name);
          if (code == POSTINCREMENT_EXPR)
            code = PREINCREMENT_EXPR;
          else
@@ -3354,7 +3359,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
     {
       extern int warn_synth;
       if (warn_synth
-         && fnname == ansi_opname[MODIFY_EXPR]
+         && fnname == ansi_assopname (NOP_EXPR)
          && DECL_ARTIFICIAL (cand->fn)
          && candidates->next
          && ! candidates->next->next)
@@ -3516,7 +3521,7 @@ build_op_delete_call (code, addr, size, flags, placement)
     return error_mark_node;
 
   type = TREE_TYPE (TREE_TYPE (addr));
-  fnname = ansi_opname[code];
+  fnname = ansi_opname (code);
 
   if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL))
     /* In [class.free]
@@ -4137,7 +4142,7 @@ build_over_call (cand, args, flags)
          return address;
        }
     }
-  else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR]
+  else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
           && copy_args_p (fn)
           && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
     {
@@ -5123,7 +5128,7 @@ joust (cand1, cand2, warn)
       /* Kludge around broken overloading rules whereby
         Integer a, b; test ? a : b; is ambiguous, since there's a builtin
         that takes references and another that takes values.  */
-      if (cand1->fn == ansi_opname[COND_EXPR])
+      if (DECL_OVERLOADED_OPERATOR_P (cand1->fn) == COND_EXPR)
        {
          tree c1 = TREE_VEC_ELT (cand1->convs, 1);
          tree c2 = TREE_VEC_ELT (cand2->convs, 1);
index 810d17469017ac2716b1acce8a9a9b38efc00e6d..347cde81e50ea40a8ae0c107caa003f18970f5f8 100644 (file)
@@ -1012,8 +1012,11 @@ extern tree current_function_return_value;
 extern tree global_namespace;
 
 extern tree ridpointers[];
-extern tree ansi_opname[];
-extern tree ansi_assopname[];
+
+#define ansi_opname(CODE) \
+  (operator_name_info[(int) (CODE)].identifier)
+#define ansi_assopname(CODE) \
+  (assignment_operator_name_info[(int) (CODE)].identifier)
 
 /* Nonzero means `$' can be in an identifier.  */
 
@@ -1864,7 +1867,8 @@ struct lang_decl_flags
   unsigned global_ctor_p : 1;
   unsigned global_dtor_p : 1;
   unsigned tinfo_fn_p : 1;
-  unsigned dummy : 4;
+  unsigned assignment_operator_p : 1;
+  unsigned dummy : 3;
 
   tree context;
 
@@ -1903,15 +1907,21 @@ struct lang_decl
   /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION.  */
   tree cloned_function;
 
-  /* In a FUNCTION_DECL, this is VTT_PARM.  */
-  tree vtt_parm;
-
   union
   {
     tree sorted_fields;
     struct pending_inline *pending_inline_info;
     struct language_function *saved_language_function;
   } u;
+
+  union {
+    /* In an overloaded operator, this is the value of
+       DECL_OVERLOADED_OPERATOR_P.  */
+    enum tree_code operator_code;
+    /* In a maybe-in-charge constructor or destructor, this is
+       DECL_VTT_PARM.  */
+    tree vtt_parm;
+  } u2;
 };
 
 /* Non-zero if NODE is a _DECL with TREE_READONLY set.  */
@@ -1997,7 +2007,7 @@ struct lang_decl
 /* In a maybe-in-charge constructor or destructor, this is the VTT
    parameter.  It's not actually on the DECL_ARGUMENTS list.  */
 #define DECL_VTT_PARM(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->vtt_parm)
+  (DECL_LANG_SPECIFIC (NODE)->u2.vtt_parm)
 
 /* If there's a DECL_VTT_PARM, this is a magic variable that indicates
    whether or not the VTT parm should be used.  In a subobject
@@ -2017,9 +2027,24 @@ struct lang_decl
 #define DECL_CONV_FN_P(NODE) \
   (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)))
 
-/* Non-zero if NODE is an overloaded operator.  */
-#define DECL_OVERLOADED_OPERATOR_P(NODE)       \
-  (IDENTIFIER_OPNAME_P (DECL_NAME ((NODE))))
+/* Set the overloaded operator code for NODE to CODE.  */
+#define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
+  (DECL_LANG_SPECIFIC (NODE)->u2.operator_code = (CODE))
+
+/* If NODE is an overloaded operator, then this returns the TREE_CODE
+   associcated with the overloaded operator.
+   DECL_ASSIGNMENT_OPERATOR_P must also be checked to determine
+   whether or not NODE is an assignment operator.  If NODE is not an
+   overloaded operator, ERROR_MARK is returned.  Since the numerical
+   value of ERROR_MARK is zero, this macro can be used as a predicate
+   to test whether or not NODE is an overloaded operator.  */
+#define DECL_OVERLOADED_OPERATOR_P(NODE)                       \
+  (IDENTIFIER_OPNAME_P (DECL_NAME ((NODE)))            \
+   ? DECL_LANG_SPECIFIC (NODE)->u2.operator_code : ERROR_MARK)
+
+/* Non-zero if NODE is an assignment operator.  */
+#define DECL_ASSIGNMENT_OPERATOR_P(NODE) \
+  (DECL_LANG_SPECIFIC (NODE)->decl_flags.assignment_operator_p)
 
 /* For FUNCTION_DECLs: nonzero means that this function is a
    constructor or a destructor with an extra in-charge parameter to
@@ -2040,7 +2065,7 @@ struct lang_decl
 
 /* Nonzero if NODE is an overloaded `operator delete[]' function.  */
 #define DECL_ARRAY_DELETE_OPERATOR_P(NODE) \
-  (DECL_NAME (NODE) == ansi_opname[(int) VEC_DELETE_EXPR])
+  (DECL_OVERLOADED_OPERATOR_P (NODE) == VEC_DELETE_EXPR)
 
 /* Nonzero for _DECL means that this decl appears in (or will appear
    in) as a member in a RECORD_TYPE or UNION_TYPE node.  It is also for
@@ -3794,10 +3819,22 @@ enum tree_string_flags
 };
 
 /* in lex.c  */
-/* Indexed by TREE_CODE, these tables give C-looking names to
-   operators represented by TREE_CODES.  For example,
-   opname_tab[(int) MINUS_EXPR] == "-".  */
-extern const char **opname_tab, **assignop_tab;
+
+typedef struct operator_name_info_t
+{
+  /* The IDENTIFIER_NODE for the operator.  */
+  tree identifier;
+  /* The name of the operator.  */
+  const char *name;
+  /* The mangled name of the operator.  */
+  const char *mangled_name;
+} operator_name_info_t;
+
+/* A mapping from tree codes to operator name information.  */
+extern operator_name_info_t operator_name_info[];
+/* Similar, but for assignment operators.  */
+extern operator_name_info_t assignment_operator_name_info[];
+
 \f
 /* in call.c */
 extern int check_dtor_name                     PARAMS ((tree, tree));
@@ -3959,11 +3996,9 @@ extern tree unqualified_namespace_lookup PARAMS ((tree, int, tree *));
 extern int  lookup_using_namespace              PARAMS ((tree, tree, tree, tree, int, tree *));
 extern int  qualified_lookup_using_namespace    PARAMS ((tree, tree, tree, int));
 extern tree build_library_fn                   PARAMS ((tree, tree));
-extern tree build_cp_library_fn                        PARAMS ((tree, tree));
 extern tree build_library_fn_ptr               PARAMS ((const char *, tree));
 extern tree build_cp_library_fn_ptr            PARAMS ((const char *, tree));
 extern tree push_library_fn                    PARAMS ((tree, tree));
-extern tree push_cp_library_fn                 PARAMS ((tree, tree));
 extern tree push_void_library_fn               PARAMS ((tree, tree));
 extern tree push_throw_library_fn              PARAMS ((tree, tree));
 extern void init_decl_processing               PARAMS ((void));
@@ -4184,7 +4219,6 @@ extern tree make_pointer_declarator               PARAMS ((tree, tree));
 extern tree make_reference_declarator          PARAMS ((tree, tree));
 extern tree make_call_declarator               PARAMS ((tree, tree, tree, tree));
 extern void set_quals_and_spec                 PARAMS ((tree, tree, tree));
-extern const char *operator_name_string                PARAMS ((tree));
 extern void lang_init                          PARAMS ((void));
 extern void lang_finish                                PARAMS ((void));
 #if 0
@@ -4234,7 +4268,6 @@ extern int cp_type_qual_from_rid                PARAMS ((tree));
 extern void init_method                                PARAMS ((void));
 extern char *build_overload_name               PARAMS ((tree, int, int));
 extern tree build_static_name                  PARAMS ((tree, tree));
-extern tree build_decl_overload                        PARAMS ((tree, tree, int));
 extern tree build_decl_overload_real            PARAMS ((tree, tree, tree, tree,
                                                       tree, int)); 
 extern void set_mangled_name_for_decl           PARAMS ((tree));
index eecf36da082b49759e884ebe3484c6e31ec05c80..25270d465241e609fce4181cfa748b00f87e0c6f 100644 (file)
@@ -108,8 +108,8 @@ static void signal_catch PARAMS ((int)) ATTRIBUTE_NORETURN;
 static int decl_jump_unsafe PARAMS ((tree));
 static void storedecls PARAMS ((tree));
 static void require_complete_types_for_parms PARAMS ((tree));
-static int ambi_op_p PARAMS ((tree));
-static int unary_op_p PARAMS ((tree));
+static int ambi_op_p PARAMS ((enum tree_code));
+static int unary_op_p PARAMS ((enum tree_code));
 static tree store_bindings PARAMS ((tree, tree));
 static tree lookup_tag_reverse PARAMS ((tree, tree));
 static tree obscure_complex_init PARAMS ((tree, tree));
@@ -126,7 +126,7 @@ static void set_identifier_type_value_with_scope
        PARAMS ((tree, tree, struct binding_level *));
 static void record_builtin_type PARAMS ((enum rid, const char *, tree));
 static void record_unknown_type PARAMS ((tree, const char *));
-static tree build_library_fn_1                 PARAMS ((tree, tree));
+static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree));
 static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
 static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
                                  int));
@@ -186,6 +186,8 @@ static tree cp_make_fname_decl PARAMS ((tree, const char *, int));
 static void initialize_predefined_identifiers PARAMS ((void));
 static tree check_special_function_return_type 
   PARAMS ((special_function_kind, tree, tree, tree));
+static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
+static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PARAMS ((void));
@@ -3425,7 +3427,7 @@ duplicate_decls (newdecl, olddecl)
       DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
       DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
       DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
-      DECL_VTT_PARM (newdecl) = DECL_VTT_PARM (olddecl);
+      DECL_LANG_SPECIFIC (newdecl)->u2 = DECL_LANG_SPECIFIC (olddecl)->u2;
       new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
 
       /* Optionally warn about more than one declaration for the same
@@ -6596,11 +6598,10 @@ init_decl_processing ()
     newtype = build_exception_variant
       (ptr_ftype_sizetype, add_exception_specifier (NULL_TREE, bad_alloc_type_node, -1));
     deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
-    push_cp_library_fn (ansi_opname[(int) NEW_EXPR], newtype);
-    push_cp_library_fn (ansi_opname[(int) VEC_NEW_EXPR], newtype);
-    global_delete_fndecl = push_cp_library_fn (ansi_opname[(int) DELETE_EXPR],
-                                              deltype);
-    push_cp_library_fn (ansi_opname[(int) VEC_DELETE_EXPR], deltype);
+    push_cp_library_fn (NEW_EXPR, newtype);
+    push_cp_library_fn (VEC_NEW_EXPR, newtype);
+    global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
+    push_cp_library_fn (VEC_DELETE_EXPR, deltype);
   }
 
   abort_fndecl
@@ -6756,7 +6757,7 @@ builtin_function (name, type, code, class, libname)
      enum built_in_class class;
      const char *libname;
 {
-  tree decl = build_library_fn_1 (get_identifier (name), type);
+  tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
   DECL_BUILT_IN_CLASS (decl) = class;
   DECL_FUNCTION_CODE (decl) = code;
 
@@ -6776,8 +6777,9 @@ builtin_function (name, type, code, class, libname)
    function.  Not called directly.  */
 
 static tree
-build_library_fn_1 (name, type)
+build_library_fn_1 (name, operator_code, type)
      tree name;
+     enum tree_code operator_code;
      tree type;
 {
   tree fn = build_lang_decl (FUNCTION_DECL, name, type);
@@ -6785,6 +6787,7 @@ build_library_fn_1 (name, type)
   TREE_PUBLIC (fn) = 1;
   DECL_ARTIFICIAL (fn) = 1;
   TREE_NOTHROW (fn) = 1;
+  SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
   return fn;
 }
 
@@ -6797,19 +6800,20 @@ build_library_fn (name, type)
      tree name;
      tree type;
 {
-  tree fn = build_library_fn_1 (name, type);
+  tree fn = build_library_fn_1 (name, ERROR_MARK, type);
   make_function_rtl (fn);
   return fn;
 }
 
 /* Returns the _DECL for a library function with C++ linkage.  */
 
-tree
-build_cp_library_fn (name, type)
+static tree
+build_cp_library_fn (name, operator_code, type)
      tree name;
+     enum tree_code operator_code;
      tree type;
 {
-  tree fn = build_library_fn_1 (name, type);
+  tree fn = build_library_fn_1 (name, operator_code, type);
   TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
   set_mangled_name_for_decl (fn);
   make_function_rtl (fn);
@@ -6835,7 +6839,7 @@ build_cp_library_fn_ptr (name, type)
      const char *name;
      tree type;
 {
-  return build_cp_library_fn (get_identifier (name), type);
+  return build_cp_library_fn (get_identifier (name), ERROR_MARK, type);
 }
 
 /* Like build_library_fn, but also pushes the function so that we will
@@ -6853,12 +6857,14 @@ push_library_fn (name, type)
 /* Like build_cp_library_fn, but also pushes the function so that it
    will be found by normal lookup.  */
 
-tree
-push_cp_library_fn (name, type)
-     tree name;
+static tree
+push_cp_library_fn (operator_code, type)
+     enum tree_code operator_code;
      tree type;
 {
-  tree fn = build_cp_library_fn (name, type);
+  tree fn = build_cp_library_fn (ansi_opname (operator_code), 
+                                operator_code,
+                                type);
   pushdecl (fn);
   return fn;
 }
@@ -8892,7 +8898,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
       quals = NULL_TREE;
     }
 
-  if (DECL_OVERLOADED_OPERATOR_P (decl))
+  if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
     grok_op_properties (decl, virtualp, check < 0);
 
   if (ctype && decl_function_context (decl))
@@ -9794,18 +9800,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                          dname);
                name = IDENTIFIER_POINTER (dname);
              }
-           else if (!IDENTIFIER_OPNAME_P (dname))
+           else if (!IDENTIFIER_TYPENAME_P (dname))
              name = IDENTIFIER_POINTER (dname);
            else
              {
-               if (IDENTIFIER_TYPENAME_P (dname))
-                 {
-                   my_friendly_assert (flags == NO_SPECIAL, 154);
-                   flags = TYPENAME_FLAG;
-                   ctor_return_type = TREE_TYPE (dname);
-                   sfk = sfk_conversion;
-                 }
-               name = operator_name_string (dname);
+               my_friendly_assert (flags == NO_SPECIAL, 154);
+               flags = TYPENAME_FLAG;
+               ctor_return_type = TREE_TYPE (dname);
+               sfk = sfk_conversion;
+               if (IDENTIFIER_GLOBAL_VALUE (dname)
+                   && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (dname)) 
+                       == TYPE_DECL))
+                 name = IDENTIFIER_POINTER (dname);
+               else
+                 name = "<invalid operator>";
              }
            break;
 
@@ -10369,10 +10377,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  else
                    tmp = TREE_OPERAND (declarator, 0);
                  op = IDENTIFIER_OPNAME_P (tmp);
+                 if (IDENTIFIER_TYPENAME_P (tmp))
+                   {
+                     if (IDENTIFIER_GLOBAL_VALUE (tmp)
+                         && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (tmp)) 
+                             == TYPE_DECL))
+                       name = IDENTIFIER_POINTER (tmp);
+                     else
+                       name = "<invalid operator>";
+                   }
                }
              error ("storage class specified for %s `%s'",
                     op ? "member operator" : "field",
-                    op ? operator_name_string (tmp) : name);
+                    name);
            }
          else
            {
@@ -11356,10 +11373,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                    return void_type_node;
                  }
 
-               if (declarator == ansi_opname[(int) NEW_EXPR]
-                   || declarator == ansi_opname[(int) VEC_NEW_EXPR]
-                   || declarator == ansi_opname[(int) DELETE_EXPR]
-                   || declarator == ansi_opname[(int) VEC_DELETE_EXPR])
+               if (declarator == ansi_opname (NEW_EXPR)
+                   || declarator == ansi_opname (VEC_NEW_EXPR)
+                   || declarator == ansi_opname (DELETE_EXPR)
+                   || declarator == ansi_opname (VEC_DELETE_EXPR))
                  {
                    if (virtualp)
                      {
@@ -12225,30 +12242,30 @@ grok_ctor_properties (ctype, decl)
   return 1;
 }
 
-/* An operator with this name can be either unary or binary.  */
+/* An operator with this code is unary, but can also be binary.  */
 
 static int
-ambi_op_p (name)
-     tree name;
+ambi_op_p (code)
+     enum tree_code code;
 {
-  return (name == ansi_opname [(int) INDIRECT_REF]
-         || name == ansi_opname [(int) ADDR_EXPR]
-         || name == ansi_opname [(int) NEGATE_EXPR]
-         || name == ansi_opname[(int) POSTINCREMENT_EXPR]
-         || name == ansi_opname[(int) POSTDECREMENT_EXPR]
-         || name == ansi_opname [(int) CONVERT_EXPR]);
+  return (code == INDIRECT_REF
+         || code == ADDR_EXPR
+         || code == CONVERT_EXPR
+         || code == NEGATE_EXPR
+         || code == PREINCREMENT_EXPR
+         || code == PREDECREMENT_EXPR);
 }
 
 /* An operator with this name can only be unary.  */
 
 static int
-unary_op_p (name)
-     tree name;
+unary_op_p (code)
+     enum tree_code code;
 {
-  return (name == ansi_opname [(int) TRUTH_NOT_EXPR]
-         || name == ansi_opname [(int) BIT_NOT_EXPR]
-         || name == ansi_opname [(int) COMPONENT_REF]
-         || IDENTIFIER_TYPENAME_P (name));
+  return (code == TRUTH_NOT_EXPR
+         || code == BIT_NOT_EXPR
+         || code == COMPONENT_REF
+         || code == TYPE_EXPR);
 }
 
 /* Do a little sanity-checking on how they declared their operator.  */
@@ -12259,43 +12276,87 @@ grok_op_properties (decl, virtualp, friendp)
      int virtualp, friendp;
 {
   tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+  tree argtype;
   int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
   tree name = DECL_NAME (decl);
+  enum tree_code operator_code;
+  int arity;
+
+  /* Count the number of arguments.  */
+  for (argtype = argtypes, arity = 0;
+       argtype && argtype != void_list_node;
+       argtype = TREE_CHAIN (argtype))
+    ++arity;
 
   if (current_class_type == NULL_TREE)
     friendp = 1;
 
+  if (DECL_CONV_FN_P (decl))
+    operator_code = TYPE_EXPR;
+  else
+    do
+      {
+#define DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGING, ARITY, ASSN_P)  \
+       if (ansi_opname (CODE) == name)                                     \
+         {                                                                 \
+           operator_code = CODE;                                           \
+           break;                                                          \
+         }                                                                 \
+       else if (ansi_assopname (CODE) == name)                             \
+         {                                                                 \
+           operator_code = CODE;                                           \
+           DECL_ASSIGNMENT_OPERATOR_P (decl) = 1;                          \
+           break;                                                          \
+         }
+
+#include "operators.def"
+#undef DEF_OPERATOR
+
+       my_friendly_abort (20000527);
+      }
+    while (0);
+  my_friendly_assert (operator_code != LAST_CPLUS_TREE_CODE, 20000526);
+  SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
+
   if (! friendp)
     {
-      /* [class.copy]
+      switch (operator_code)
+       {
+       case CALL_EXPR:
+         TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
+         break;
+         
+       case ARRAY_REF:
+         TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
+         break;
 
-        A user-declared copy assignment operator X::operator= is a
-        non-static non-template member function of class X with
-        exactly one parameter of type X, X&, const X&, volatile X& or
-        const volatile X&.  */
-      if (name == ansi_opname[(int) MODIFY_EXPR]
-         && !(DECL_TEMPLATE_INSTANTIATION (decl)
-              && is_member_template (DECL_TI_TEMPLATE (decl))))
-       ;
-      else if (name == ansi_opname[(int) CALL_EXPR])
-       TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
-      else if (name == ansi_opname[(int) ARRAY_REF])
-       TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
-      else if (name == ansi_opname[(int) COMPONENT_REF]
-              || name == ansi_opname[(int) MEMBER_REF])
-       TYPE_OVERLOADS_ARROW (current_class_type) = 1;
-      else if (name == ansi_opname[(int) NEW_EXPR])
-       TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
-      else if (name == ansi_opname[(int) DELETE_EXPR])
-       TYPE_GETS_DELETE (current_class_type) |= 1;
-      else if (name == ansi_opname[(int) VEC_NEW_EXPR])
-       TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
-      else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
-       TYPE_GETS_DELETE (current_class_type) |= 2;
-    }
-
-  if (name == ansi_opname[(int) NEW_EXPR]
-      || name == ansi_opname[(int) VEC_NEW_EXPR])
+       case COMPONENT_REF:
+       case MEMBER_REF:
+         TYPE_OVERLOADS_ARROW (current_class_type) = 1;
+         break;
+         
+       case NEW_EXPR:
+         TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
+         break;
+         
+       case DELETE_EXPR:
+         TYPE_GETS_DELETE (current_class_type) |= 1;
+         break;
+         
+       case VEC_NEW_EXPR:
+         TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
+         break;
+         
+       case VEC_DELETE_EXPR:
+         TYPE_GETS_DELETE (current_class_type) |= 2;
+         break;
+
+       default:
+         break;
+       }
+    }
+
+  if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
     {
       /* When the compiler encounters the definition of A::operator new, it
         doesn't look at the class declaration to find out if it's static.  */
@@ -12311,8 +12372,7 @@ grok_op_properties (decl, virtualp, friendp)
       else
        TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
     }
-  else if (name == ansi_opname[(int) DELETE_EXPR]
-          || name == ansi_opname[(int) VEC_DELETE_EXPR])
+  else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
     {
       if (methodp)
        revert_static_member_fn (decl);
@@ -12332,11 +12392,11 @@ grok_op_properties (decl, virtualp, friendp)
         an enumeration, or a reference to an enumeration.  13.4.0.6 */
       if (! methodp || DECL_STATIC_FUNCTION_P (decl))
        {
-         if (DECL_CONV_FN_P (decl)
-             || name == ansi_opname[(int) CALL_EXPR]
-             || name == ansi_opname[(int) MODIFY_EXPR]
-             || name == ansi_opname[(int) COMPONENT_REF]
-             || name == ansi_opname[(int) ARRAY_REF])
+         if (operator_code == TYPE_EXPR
+             || operator_code == CALL_EXPR
+             || operator_code == COMPONENT_REF
+             || operator_code == ARRAY_REF
+             || operator_code == NOP_EXPR)
            cp_error ("`%D' must be a nonstatic member function", decl);
          else
            {
@@ -12367,7 +12427,7 @@ grok_op_properties (decl, virtualp, friendp)
            }
        }
 
-      if (name == ansi_opname[(int) CALL_EXPR])
+      if (operator_code == CALL_EXPR)
        return;                 /* No restrictions on args. */
 
       if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
@@ -12397,18 +12457,27 @@ grok_op_properties (decl, virtualp, friendp)
            }
        }
 
-      if (name == ansi_opname[(int) MODIFY_EXPR])
+      if (DECL_ASSIGNMENT_OPERATOR_P (decl) 
+         && operator_code == NOP_EXPR)
        {
          tree parmtype;
 
-         if (list_length (argtypes) != 3 && methodp)
+         if (arity != 2 && methodp)
            {
              cp_error ("`%D' must take exactly one argument", decl);
              return;
            }
          parmtype = TREE_VALUE (TREE_CHAIN (argtypes));
 
+         /* [class.copy]
+
+            A user-declared copy assignment operator X::operator= is
+            a non-static non-template member function of class X with
+            exactly one parameter of type X, X&, const X&, volatile
+            X& or const volatile X&.  */
          if (copy_assignment_arg_p (parmtype, virtualp)
+             && !(DECL_TEMPLATE_INSTANTIATION (decl)
+                  && is_member_template (DECL_TI_TEMPLATE (decl)))
              && ! friendp)
            {
              TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
@@ -12417,19 +12486,55 @@ grok_op_properties (decl, virtualp, friendp)
                TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
            }
        }
-      else if (name == ansi_opname[(int) COND_EXPR])
+      else if (operator_code == COND_EXPR)
        {
          /* 13.4.0.3 */
          cp_error ("ISO C++ prohibits overloading operator ?:");
        }
-      else if (ambi_op_p (name))
+      else if (ambi_op_p (operator_code))
        {
-         if (list_length (argtypes) == 2)
-           /* prefix */;
-         else if (list_length (argtypes) == 3)
+         if (arity == 1)
+           /* We pick the one-argument operator codes by default, so
+              we don't have to change anything.  */
+           ;
+         else if (arity == 2)
            {
-             if ((name == ansi_opname[(int) POSTINCREMENT_EXPR]
-                  || name == ansi_opname[(int) POSTDECREMENT_EXPR])
+             /* If we thought this was a unary operator, we now know
+                it to be a binary operator.  */
+             switch (operator_code)
+               {
+               case INDIRECT_REF:
+                 operator_code = MULT_EXPR;
+                 break;
+
+               case ADDR_EXPR:
+                 operator_code = BIT_AND_EXPR;
+                 break;
+
+               case CONVERT_EXPR:
+                 operator_code = PLUS_EXPR;
+                 break;
+
+               case NEGATE_EXPR:
+                 operator_code = MINUS_EXPR;
+                 break;
+
+               case PREINCREMENT_EXPR:
+                 operator_code = POSTINCREMENT_EXPR;
+                 break;
+
+               case PREDECREMENT_EXPR:
+                 operator_code = PREDECREMENT_EXPR;
+                 break;
+
+               default:
+                 my_friendly_abort (20000527);
+               }
+
+             SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
+
+             if ((operator_code == POSTINCREMENT_EXPR
+                  || operator_code == POSTDECREMENT_EXPR)
                  && ! processing_template_decl
                  && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
                {
@@ -12452,15 +12557,18 @@ grok_op_properties (decl, virtualp, friendp)
 
          /* More Effective C++ rule 6.  */
          if (warn_ecpp
-             && (name == ansi_opname[(int) POSTINCREMENT_EXPR]
-                 || name == ansi_opname[(int) POSTDECREMENT_EXPR]))
+             && (operator_code == POSTINCREMENT_EXPR
+                 || operator_code == POSTDECREMENT_EXPR
+                 || operator_code == PREINCREMENT_EXPR
+                 || operator_code == PREDECREMENT_EXPR))
            {
              tree arg = TREE_VALUE (argtypes);
              tree ret = TREE_TYPE (TREE_TYPE (decl));
              if (methodp || TREE_CODE (arg) == REFERENCE_TYPE)
                arg = TREE_TYPE (arg);
              arg = TYPE_MAIN_VARIANT (arg);
-             if (list_length (argtypes) == 2)
+             if (operator_code == PREINCREMENT_EXPR
+                 || operator_code == PREDECREMENT_EXPR)
                {
                  if (TREE_CODE (ret) != REFERENCE_TYPE
                      || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
@@ -12475,9 +12583,9 @@ grok_op_properties (decl, virtualp, friendp)
                }
            }
        }
-      else if (unary_op_p (name))
+      else if (unary_op_p (operator_code))
        {
-         if (list_length (argtypes) != 2)
+         if (arity != 1)
            {
              if (methodp)
                cp_error ("`%D' must take `void'", decl);
@@ -12485,9 +12593,9 @@ grok_op_properties (decl, virtualp, friendp)
                cp_error ("`%D' must take exactly one argument", decl);
            }
        }
-      else /* if (binary_op_p (name)) */
+      else /* if (binary_op_p (operator_code)) */
        {
-         if (list_length (argtypes) != 3)
+         if (arity != 2)
            {
              if (methodp)
                cp_error ("`%D' must take exactly one argument", decl);
@@ -12497,20 +12605,20 @@ grok_op_properties (decl, virtualp, friendp)
 
          /* More Effective C++ rule 7.  */
          if (warn_ecpp
-             && (name == ansi_opname [TRUTH_ANDIF_EXPR]
-                 || name == ansi_opname [TRUTH_ORIF_EXPR]
-                 || name == ansi_opname [COMPOUND_EXPR]))
+             && (operator_code == TRUTH_ANDIF_EXPR
+                 || operator_code == TRUTH_ORIF_EXPR
+                 || operator_code == COMPOUND_EXPR))
            cp_warning ("user-defined `%D' always evaluates both arguments",
                        decl);
        }
 
       /* Effective C++ rule 23.  */
       if (warn_ecpp
-         && list_length (argtypes) == 3
-         && (name == ansi_opname [PLUS_EXPR]
-             || name == ansi_opname [MINUS_EXPR]
-             || name == ansi_opname [TRUNC_DIV_EXPR]
-             || name == ansi_opname [MULT_EXPR])
+         && arity == 2
+         && (operator_code == PLUS_EXPR
+             || operator_code == MINUS_EXPR
+             || operator_code == TRUNC_DIV_EXPR
+             || operator_code == MULT_EXPR)
          && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
        cp_warning ("`%D' should return by value", decl);
 
@@ -12520,8 +12628,8 @@ grok_op_properties (decl, virtualp, friendp)
         if (TREE_PURPOSE (argtypes))
           {
             TREE_PURPOSE (argtypes) = NULL_TREE;
-            if (name == ansi_opname[(int) POSTINCREMENT_EXPR] 
-                || name == ansi_opname[(int) POSTDECREMENT_EXPR])   
+            if (operator_code == POSTINCREMENT_EXPR
+               || operator_code == POSTDECREMENT_EXPR)
               {
                 if (pedantic)
                   cp_pedwarn ("`%D' cannot have default arguments", decl);
@@ -13464,7 +13572,7 @@ start_function (declspecs, declarator, attrs, flags)
 
   /* Effective C++ rule 15.  See also c_expand_return.  */
   if (warn_ecpp
-      && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
+      && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
       && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
     cp_warning ("`operator=' should return a reference to `*this'");
 
@@ -14896,7 +15004,8 @@ lang_mark_tree (t)
              ggc_mark_tree (ld->befriending_classes);
              ggc_mark_tree (ld->saved_tree);
              ggc_mark_tree (ld->cloned_function);
-             ggc_mark_tree (ld->vtt_parm);
+             if (!DECL_OVERLOADED_OPERATOR_P (t))
+               ggc_mark_tree (ld->u2.vtt_parm);
              if (TREE_CODE (t) == TYPE_DECL)
                ggc_mark_tree (ld->u.sorted_fields);
              else if (TREE_CODE (t) == FUNCTION_DECL
index 11250e7a02f245c2210ac2a4c2d4f81ba5bbdd9d..6a90a0a0dbb97b17cd287f2f20edd5a6555a3e27 100644 (file)
@@ -1960,7 +1960,7 @@ grok_function_init (decl, init)
        }
 #endif
       DECL_PURE_VIRTUAL_P (decl) = 1;
-      if (DECL_NAME (decl) == ansi_opname [(int) MODIFY_EXPR])
+      if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
        {
          tree parmtype
            = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))));
index bfd921f5aadc82f51efca6348fd6ecbef0f7537c..f4c116be161fa740183f78cdfca487164084870c 100644 (file)
@@ -945,14 +945,6 @@ dump_decl (t, flags)
            dump_type (TREE_TYPE (t), flags);
            break;
          }
-       else if (IDENTIFIER_OPNAME_P (t))
-         {
-           const char *name_string = operator_name_string (t);
-           OB_PUTS ("operator");
-           if (ISALPHA (name_string[0]))
-             OB_PUTC (' ');
-           OB_PUTCP (name_string);
-         }
        else
          OB_PUTID (t);
       }
@@ -1278,13 +1270,7 @@ dump_function_name (t, flags)
       dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
     }
   else if (IDENTIFIER_OPNAME_P (name))
-    {
-      const char *name_string = operator_name_string (name);
-      OB_PUTS ("operator");
-      if (ISALPHA (name_string[0]))
-       OB_PUTC (' ');
-      OB_PUTCP (name_string);
-    }
+    OB_PUTID (name);
   else
     dump_decl (name, flags);
 
@@ -1694,7 +1680,7 @@ dump_expr (t, flags)
     case EQ_EXPR:
     case NE_EXPR:
     case EXACT_DIV_EXPR:
-      dump_binary_op (opname_tab[(int) TREE_CODE (t)], t, flags);
+      dump_binary_op (operator_name_info[(int) TREE_CODE (t)].name, t, flags);
       break;
 
     case CEIL_DIV_EXPR:
@@ -1782,14 +1768,14 @@ dump_expr (t, flags)
     case TRUTH_NOT_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
-      dump_unary_op (opname_tab [(int)TREE_CODE (t)], t, flags);
+      dump_unary_op (operator_name_info [(int)TREE_CODE (t)].name, t, flags);
       break;
 
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
       OB_PUTC ('(');
       dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
-      OB_PUTCP (opname_tab[(int)TREE_CODE (t)]);
+      OB_PUTCP (operator_name_info[(int)TREE_CODE (t)].name);
       OB_PUTC (')');
       break;
 
@@ -2307,13 +2293,10 @@ op_to_string (p, v)
      enum tree_code p;
      int v ATTRIBUTE_UNUSED;
 {
-  static char buf[] = "operator                ";
+  tree id;
 
-  if (p == 0)
-    return "{unknown}";
-  
-  strcpy (buf + 8, opname_tab [p]);
-  return buf;
+  id = operator_name_info[(int) p].identifier;
+  return id ? IDENTIFIER_POINTER (id) : "{unknown}";
 }
 
 static const char *
@@ -2342,13 +2325,10 @@ assop_to_string (p, v)
      enum tree_code p;
      int v ATTRIBUTE_UNUSED;
 {
-  static char buf[] = "operator                ";
+  tree id;
 
-  if (p == 0)
-    return "{unknown}";
-  
-  strcpy (buf + 9, assignop_tab [p]);
-  return buf;
+  id = assignment_operator_name_info[(int) p].identifier;
+  return id ? IDENTIFIER_POINTER (id) : "{unknown}";
 }
 
 static const char *
index cc5be91c79efe887db4d33898e7112d955127bb5..073aa68ec4dd82636abf3dfd593aa74cdf9c944f 100644 (file)
@@ -2331,7 +2331,7 @@ build_new_1 (exp)
       tree args;
 
       args = tree_cons (NULL_TREE, size, placement);
-      fnname = ansi_opname[code];
+      fnname = ansi_opname (code);
 
       if (use_global_new)
        rval = (build_new_function_call 
index 279b42d44e43cd9bd06d514e0a9be8ae165cc0fe..e9cd519e6f91b8c0b10582cf6406eb0a5f895709 100644 (file)
@@ -94,6 +94,7 @@ static void mark_impl_file_chain PARAMS ((void *));
 static int read_ucs PARAMS ((int));
 static int is_extended_char PARAMS ((int));
 static int is_extended_char_1 PARAMS ((int));
+static void init_operators PARAMS ((void));
 
 /* Given a file name X, return the nondirectory portion.
    Keep in mind that X can be computed more than once.  */
@@ -144,10 +145,6 @@ extern struct obstack token_obstack;
 /* ??? Don't really know where this goes yet.  */
 #include "input.c"
 
-/* Holds translations from TREE_CODEs to operator name strings,
-   i.e., opname_tab[PLUS_EXPR] == "+".  */
-const char **opname_tab;
-const char **assignop_tab;
 \f
 extern int yychar;             /*  the lookahead symbol                */
 extern YYSTYPE yylval;         /*  the semantic value of the           */
@@ -297,52 +294,6 @@ set_quals_and_spec (call_declarator, cv_qualifiers, exception_specification)
   CALL_DECLARATOR_EXCEPTION_SPEC (call_declarator) = exception_specification;
 }
 \f
-/* Build names and nodes for overloaded operators.  */
-
-tree ansi_opname[LAST_CPLUS_TREE_CODE];
-tree ansi_assopname[LAST_CPLUS_TREE_CODE];
-
-const char *
-operator_name_string (name)
-     tree name;
-{
-  char *opname = IDENTIFIER_POINTER (name) + 2;
-  tree *opname_table;
-  int i, assign;
-
-  /* Works for builtin and user defined types.  */
-  if (IDENTIFIER_GLOBAL_VALUE (name)
-      && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TYPE_DECL)
-    return IDENTIFIER_POINTER (name);
-
-  if (opname[0] == 'a' && opname[2] != '\0' && opname[2] != '_')
-    {
-      opname += 1;
-      assign = 1;
-      opname_table = ansi_assopname;
-    }
-  else
-    {
-      assign = 0;
-      opname_table = ansi_opname;
-    }
-
-  for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
-    {
-      if (opname[0] == IDENTIFIER_POINTER (opname_table[i])[2+assign]
-         && opname[1] == IDENTIFIER_POINTER (opname_table[i])[3+assign])
-       break;
-    }
-
-  if (i == LAST_CPLUS_TREE_CODE)
-    return "<invalid operator>";
-
-  if (assign)
-    return assignop_tab[i];
-  else
-    return opname_tab[i];
-}
-\f
 int interface_only;            /* whether or not current file is only for
                                   interface definitions.  */
 int interface_unknown;         /* whether or not we know this class
@@ -487,19 +438,6 @@ init_filename_times ()
     }
 }
 
-/* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
-   Stuck this hack in to get the files open correctly; this is called
-   in place of init_parse if we are an unexec'd binary.    */
-
-#if 0
-void
-reinit_lang_specific ()
-{
-  init_filename_times ();
-  reinit_search_statistics ();
-}
-#endif
-
 static int *
 init_cpp_parse ()
 {
@@ -514,6 +452,81 @@ init_cpp_parse ()
   return token_count;
 }
 
+/* A mapping from tree codes to operator name information.  */
+operator_name_info_t operator_name_info[(int) LAST_CPLUS_TREE_CODE];
+/* Similar, but for assignment operators.  */
+operator_name_info_t assignment_operator_name_info[(int) LAST_CPLUS_TREE_CODE];
+  
+/* Initialize data structures that keep track of operator names.  */
+
+static void
+init_operators ()
+{
+  tree identifier;
+  char buffer[256];
+  struct operator_name_info_t *oni;
+  
+#define DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY, ASSN_P) \
+  my_friendly_assert ((strlen ("operator ") + strlen (NAME) + 1                    \
+                      <= 256),                                             \
+                     20000526);                                            \
+  sprintf (buffer, "operator %s", NAME);                                   \
+  identifier = get_identifier (buffer);                                            \
+  IDENTIFIER_OPNAME_P (identifier) = 1;                                            \
+                                                                           \
+  oni = (ASSN_P                                                                    \
+        ? &assignment_operator_name_info[(int) CODE]                       \
+        : &operator_name_info[(int) CODE]);                                \
+  oni->identifier = identifier;                                                    \
+  oni->name = NAME;                                                        \
+  oni->mangled_name = flag_new_abi ? NEW_MANGLING : OLD_MANGLING;
+
+#include "operators.def"
+#undef DEF_OPERATOR
+
+  operator_name_info[(int) ERROR_MARK].identifier 
+    = get_identifier ("<invalid operator>");
+
+  /* Handle some special cases.  These operators are not defined in
+     the language, but can be produced internally.  We may need them
+     for error-reporting.  (Eventually, we should ensure that this
+     does not happen.  Error messages involving these operators will
+     be confusing to users.)  */
+  
+  operator_name_info [(int) INIT_EXPR].name 
+    = operator_name_info [(int) MODIFY_EXPR].name;
+  operator_name_info [(int) EXACT_DIV_EXPR].name = "(ceiling /)";
+  operator_name_info [(int) CEIL_DIV_EXPR].name = "(ceiling /)";
+  operator_name_info [(int) FLOOR_DIV_EXPR].name = "(floor /)";
+  operator_name_info [(int) ROUND_DIV_EXPR].name = "(round /)";
+  operator_name_info [(int) CEIL_MOD_EXPR].name = "(ceiling %)";
+  operator_name_info [(int) FLOOR_MOD_EXPR].name = "(floor %)";
+  operator_name_info [(int) ROUND_MOD_EXPR].name = "(round %)";
+  operator_name_info [(int) ABS_EXPR].name = "abs";
+  operator_name_info [(int) FFS_EXPR].name = "ffs";
+  operator_name_info [(int) BIT_ANDTC_EXPR].name = "&~";
+  operator_name_info [(int) TRUTH_AND_EXPR].name = "strict &&";
+  operator_name_info [(int) TRUTH_OR_EXPR].name = "strict ||";
+  operator_name_info [(int) IN_EXPR].name = "in";
+  operator_name_info [(int) RANGE_EXPR].name = "...";
+  operator_name_info [(int) CONVERT_EXPR].name = "+";
+
+  assignment_operator_name_info [(int) EXACT_DIV_EXPR].name 
+    = "(exact /=)";
+  assignment_operator_name_info [(int) CEIL_DIV_EXPR].name 
+    = "(ceiling /=)";
+  assignment_operator_name_info [(int) FLOOR_DIV_EXPR].name 
+    = "(floor /=)";
+  assignment_operator_name_info [(int) ROUND_DIV_EXPR].name 
+    = "(round /=)";
+  assignment_operator_name_info [(int) CEIL_MOD_EXPR].name 
+    = "(ceiling %=)";
+  assignment_operator_name_info [(int) FLOOR_MOD_EXPR].name 
+    = "(floor %=)";
+  assignment_operator_name_info [(int) ROUND_MOD_EXPR].name 
+    = "(round %=)";
+}
+
 const char *
 init_parse (filename)
      const char *filename;
@@ -521,8 +534,6 @@ init_parse (filename)
   extern int flag_no_gnu_keywords;
   extern int flag_operator_names;
 
-  int i;
-
 #ifdef MULTIBYTE_CHARS
   /* Change to the native locale for multibyte conversions.  */
   setlocale (LC_CTYPE, "");
@@ -580,138 +591,7 @@ init_parse (filename)
          cplus_tree_code_name,
          (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
 
-  opname_tab = (const char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
-  memset (opname_tab, 0, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
-  assignop_tab = (const char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
-  memset (assignop_tab, 0, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
-
-  ansi_opname[0] = get_identifier ("<invalid operator>");
-  for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
-    {
-      ansi_opname[i] = ansi_opname[0];
-      ansi_assopname[i] = ansi_opname[0];
-    }
-
-  ansi_opname[(int) MULT_EXPR] = get_identifier ("__ml");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) MULT_EXPR]) = 1;
-  ansi_opname[(int) INDIRECT_REF] = ansi_opname[(int) MULT_EXPR];
-  ansi_assopname[(int) MULT_EXPR] = get_identifier ("__aml");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) MULT_EXPR]) = 1;
-  ansi_assopname[(int) INDIRECT_REF] = ansi_assopname[(int) MULT_EXPR];
-  ansi_opname[(int) TRUNC_MOD_EXPR] = get_identifier ("__md");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUNC_MOD_EXPR]) = 1;
-  ansi_assopname[(int) TRUNC_MOD_EXPR] = get_identifier ("__amd");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) TRUNC_MOD_EXPR]) = 1;
-  ansi_opname[(int) CEIL_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
-  ansi_opname[(int) FLOOR_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
-  ansi_opname[(int) ROUND_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
-  ansi_opname[(int) MINUS_EXPR] = get_identifier ("__mi");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) MINUS_EXPR]) = 1;
-  ansi_opname[(int) NEGATE_EXPR] = ansi_opname[(int) MINUS_EXPR];
-  ansi_assopname[(int) MINUS_EXPR] = get_identifier ("__ami");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) MINUS_EXPR]) = 1;
-  ansi_assopname[(int) NEGATE_EXPR] = ansi_assopname[(int) MINUS_EXPR];
-  ansi_opname[(int) RSHIFT_EXPR] = get_identifier ("__rs");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) RSHIFT_EXPR]) = 1;
-  ansi_assopname[(int) RSHIFT_EXPR] = get_identifier ("__ars");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) RSHIFT_EXPR]) = 1;
-  ansi_opname[(int) NE_EXPR] = get_identifier ("__ne");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) NE_EXPR]) = 1;
-  ansi_opname[(int) GT_EXPR] = get_identifier ("__gt");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) GT_EXPR]) = 1;
-  ansi_opname[(int) GE_EXPR] = get_identifier ("__ge");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) GE_EXPR]) = 1;
-  ansi_opname[(int) BIT_IOR_EXPR] = get_identifier ("__or");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_IOR_EXPR]) = 1;
-  ansi_assopname[(int) BIT_IOR_EXPR] = get_identifier ("__aor");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_IOR_EXPR]) = 1;
-  ansi_opname[(int) TRUTH_ANDIF_EXPR] = get_identifier ("__aa");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ANDIF_EXPR]) = 1;
-  ansi_opname[(int) TRUTH_NOT_EXPR] = get_identifier ("__nt");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_NOT_EXPR]) = 1;
-  ansi_opname[(int) PREINCREMENT_EXPR] = get_identifier ("__pp");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) PREINCREMENT_EXPR]) = 1;
-  ansi_opname[(int) POSTINCREMENT_EXPR] = ansi_opname[(int) PREINCREMENT_EXPR];
-  ansi_opname[(int) MODIFY_EXPR] = get_identifier ("__as");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) MODIFY_EXPR]) = 1;
-  ansi_assopname[(int) NOP_EXPR] = ansi_opname[(int) MODIFY_EXPR];
-  ansi_opname[(int) COMPOUND_EXPR] = get_identifier ("__cm");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPOUND_EXPR]) = 1;
-  ansi_opname[(int) EXACT_DIV_EXPR] = get_identifier ("__dv");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) EXACT_DIV_EXPR]) = 1;
-  ansi_assopname[(int) EXACT_DIV_EXPR] = get_identifier ("__adv");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) EXACT_DIV_EXPR]) = 1;
-  ansi_opname[(int) TRUNC_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
-  ansi_opname[(int) CEIL_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
-  ansi_opname[(int) FLOOR_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
-  ansi_opname[(int) ROUND_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
-  ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl");
-  ansi_assopname[(int) TRUNC_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
-  ansi_assopname[(int) CEIL_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
-  ansi_assopname[(int) FLOOR_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
-  ansi_assopname[(int) ROUND_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) PLUS_EXPR]) = 1;
-  ansi_assopname[(int) PLUS_EXPR] = get_identifier ("__apl");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) PLUS_EXPR]) = 1;
-  ansi_opname[(int) CONVERT_EXPR] = ansi_opname[(int) PLUS_EXPR];
-  ansi_assopname[(int) CONVERT_EXPR] = ansi_assopname[(int) PLUS_EXPR];
-  ansi_opname[(int) LSHIFT_EXPR] = get_identifier ("__ls");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) LSHIFT_EXPR]) = 1;
-  ansi_assopname[(int) LSHIFT_EXPR] = get_identifier ("__als");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) LSHIFT_EXPR]) = 1;
-  ansi_opname[(int) EQ_EXPR] = get_identifier ("__eq");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) EQ_EXPR]) = 1;
-  ansi_opname[(int) LT_EXPR] = get_identifier ("__lt");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) LT_EXPR]) = 1;
-  ansi_opname[(int) LE_EXPR] = get_identifier ("__le");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) LE_EXPR]) = 1;
-  ansi_opname[(int) BIT_AND_EXPR] = get_identifier ("__ad");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_AND_EXPR]) = 1;
-  ansi_assopname[(int) BIT_AND_EXPR] = get_identifier ("__aad");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_AND_EXPR]) = 1;
-  ansi_opname[(int) ADDR_EXPR] = ansi_opname[(int) BIT_AND_EXPR];
-  ansi_assopname[(int) ADDR_EXPR] = ansi_assopname[(int) BIT_AND_EXPR];
-  ansi_opname[(int) BIT_XOR_EXPR] = get_identifier ("__er");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_XOR_EXPR]) = 1;
-  ansi_assopname[(int) BIT_XOR_EXPR] = get_identifier ("__aer");
-  IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_XOR_EXPR]) = 1;
-  ansi_opname[(int) TRUTH_ORIF_EXPR] = get_identifier ("__oo");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ORIF_EXPR]) = 1;
-  ansi_opname[(int) BIT_NOT_EXPR] = get_identifier ("__co");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_NOT_EXPR]) = 1;
-  ansi_opname[(int) PREDECREMENT_EXPR] = get_identifier ("__mm");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) PREDECREMENT_EXPR]) = 1;
-  ansi_opname[(int) POSTDECREMENT_EXPR] = ansi_opname[(int) PREDECREMENT_EXPR];
-  ansi_opname[(int) COMPONENT_REF] = get_identifier ("__rf");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPONENT_REF]) = 1;
-  ansi_opname[(int) MEMBER_REF] = get_identifier ("__rm");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) MEMBER_REF]) = 1;
-  ansi_opname[(int) CALL_EXPR] = get_identifier ("__cl");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) CALL_EXPR]) = 1;
-  ansi_opname[(int) ARRAY_REF] = get_identifier ("__vc");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) ARRAY_REF]) = 1;
-  ansi_opname[(int) NEW_EXPR] = get_identifier ("__nw");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1;
-  ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) DELETE_EXPR]) = 1;
-  ansi_opname[(int) VEC_NEW_EXPR] = get_identifier ("__vn");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_NEW_EXPR]) = 1;
-  ansi_opname[(int) VEC_DELETE_EXPR] = get_identifier ("__vd");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_DELETE_EXPR]) = 1;
-  ansi_opname[(int) TYPE_EXPR] = get_identifier (OPERATOR_TYPENAME_FORMAT);
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1;
-
-  /* This is not true: these operators are not defined in ANSI,
-     but we need them anyway.  */
-  ansi_opname[(int) MIN_EXPR] = get_identifier ("__mn");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) MIN_EXPR]) = 1;
-  ansi_opname[(int) MAX_EXPR] = get_identifier ("__mx");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1;
-  ansi_opname[(int) COND_EXPR] = get_identifier ("__cn");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1;
-  ansi_opname[(int) SIZEOF_EXPR] = get_identifier ("__sz");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) SIZEOF_EXPR]) = 1;
-
+  init_operators ();
   init_method ();
   init_error ();
   gcc_obstack_init (&inline_text_obstack);
@@ -787,88 +667,6 @@ init_parse (filename)
   null_node = build_int_2 (0, 0);
   ridpointers[RID_NULL] = null_node;
 
-  opname_tab[(int) COMPONENT_REF] = "->";
-  opname_tab[(int) MEMBER_REF] = "->*";
-  opname_tab[(int) INDIRECT_REF] = "*";
-  opname_tab[(int) ARRAY_REF] = "[]";
-  opname_tab[(int) MODIFY_EXPR] = "=";
-  opname_tab[(int) INIT_EXPR] = "=";
-  opname_tab[(int) NEW_EXPR] = "new";
-  opname_tab[(int) DELETE_EXPR] = "delete";
-  opname_tab[(int) VEC_NEW_EXPR] = "new []";
-  opname_tab[(int) VEC_DELETE_EXPR] = "delete []";
-  opname_tab[(int) COND_EXPR] = "?:";
-  opname_tab[(int) CALL_EXPR] = "()";
-  opname_tab[(int) PLUS_EXPR] = "+";
-  opname_tab[(int) MINUS_EXPR] = "-";
-  opname_tab[(int) MULT_EXPR] = "*";
-  opname_tab[(int) TRUNC_DIV_EXPR] = "/";
-  opname_tab[(int) CEIL_DIV_EXPR] = "(ceiling /)";
-  opname_tab[(int) FLOOR_DIV_EXPR] = "(floor /)";
-  opname_tab[(int) ROUND_DIV_EXPR] = "(round /)";
-  opname_tab[(int) TRUNC_MOD_EXPR] = "%";
-  opname_tab[(int) CEIL_MOD_EXPR] = "(ceiling %)";
-  opname_tab[(int) FLOOR_MOD_EXPR] = "(floor %)";
-  opname_tab[(int) ROUND_MOD_EXPR] = "(round %)";
-  opname_tab[(int) EXACT_DIV_EXPR] = "/";
-  opname_tab[(int) NEGATE_EXPR] = "-";
-  opname_tab[(int) MIN_EXPR] = "<?";
-  opname_tab[(int) MAX_EXPR] = ">?";
-  opname_tab[(int) ABS_EXPR] = "abs";
-  opname_tab[(int) FFS_EXPR] = "ffs";
-  opname_tab[(int) LSHIFT_EXPR] = "<<";
-  opname_tab[(int) RSHIFT_EXPR] = ">>";
-  opname_tab[(int) BIT_IOR_EXPR] = "|";
-  opname_tab[(int) BIT_XOR_EXPR] = "^";
-  opname_tab[(int) BIT_AND_EXPR] = "&";
-  opname_tab[(int) BIT_ANDTC_EXPR] = "&~";
-  opname_tab[(int) BIT_NOT_EXPR] = "~";
-  opname_tab[(int) TRUTH_ANDIF_EXPR] = "&&";
-  opname_tab[(int) TRUTH_ORIF_EXPR] = "||";
-  opname_tab[(int) TRUTH_AND_EXPR] = "strict &&";
-  opname_tab[(int) TRUTH_OR_EXPR] = "strict ||";
-  opname_tab[(int) TRUTH_NOT_EXPR] = "!";
-  opname_tab[(int) LT_EXPR] = "<";
-  opname_tab[(int) LE_EXPR] = "<=";
-  opname_tab[(int) GT_EXPR] = ">";
-  opname_tab[(int) GE_EXPR] = ">=";
-  opname_tab[(int) EQ_EXPR] = "==";
-  opname_tab[(int) NE_EXPR] = "!=";
-  opname_tab[(int) IN_EXPR] = "in";
-  opname_tab[(int) RANGE_EXPR] = "...";
-  opname_tab[(int) CONVERT_EXPR] = "+";
-  opname_tab[(int) ADDR_EXPR] = "&";
-  opname_tab[(int) PREDECREMENT_EXPR] = "--";
-  opname_tab[(int) PREINCREMENT_EXPR] = "++";
-  opname_tab[(int) POSTDECREMENT_EXPR] = "--";
-  opname_tab[(int) POSTINCREMENT_EXPR] = "++";
-  opname_tab[(int) COMPOUND_EXPR] = ",";
-
-  assignop_tab[(int) NOP_EXPR] = "=";
-  assignop_tab[(int) PLUS_EXPR] =  "+=";
-  assignop_tab[(int) CONVERT_EXPR] =  "+=";
-  assignop_tab[(int) MINUS_EXPR] = "-=";
-  assignop_tab[(int) NEGATE_EXPR] = "-=";
-  assignop_tab[(int) MULT_EXPR] = "*=";
-  assignop_tab[(int) INDIRECT_REF] = "*=";
-  assignop_tab[(int) TRUNC_DIV_EXPR] = "/=";
-  assignop_tab[(int) EXACT_DIV_EXPR] = "(exact /=)";
-  assignop_tab[(int) CEIL_DIV_EXPR] = "(ceiling /=)";
-  assignop_tab[(int) FLOOR_DIV_EXPR] = "(floor /=)";
-  assignop_tab[(int) ROUND_DIV_EXPR] = "(round /=)";
-  assignop_tab[(int) TRUNC_MOD_EXPR] = "%=";
-  assignop_tab[(int) CEIL_MOD_EXPR] = "(ceiling %=)";
-  assignop_tab[(int) FLOOR_MOD_EXPR] = "(floor %=)";
-  assignop_tab[(int) ROUND_MOD_EXPR] = "(round %=)";
-  assignop_tab[(int) MIN_EXPR] = "<?=";
-  assignop_tab[(int) MAX_EXPR] = ">?=";
-  assignop_tab[(int) LSHIFT_EXPR] = "<<=";
-  assignop_tab[(int) RSHIFT_EXPR] = ">>=";
-  assignop_tab[(int) BIT_IOR_EXPR] = "|=";
-  assignop_tab[(int) BIT_XOR_EXPR] = "^=";
-  assignop_tab[(int) BIT_AND_EXPR] = "&=";
-  assignop_tab[(int) ADDR_EXPR] = "&=";
-
   init_filename_times ();
 
   /* Some options inhibit certain reserved words.
@@ -908,8 +706,6 @@ init_parse (filename)
   token_count = init_cpp_parse ();
   interface_unknown = 1;
 
-  ggc_add_tree_root (ansi_opname, LAST_CPLUS_TREE_CODE);
-  ggc_add_tree_root (ansi_assopname, LAST_CPLUS_TREE_CODE);
   ggc_add_string_root (&internal_filename, 1);
   ggc_add_tree_root (ridpointers, RID_MAX);
   ggc_add_tree_root (&defarg_fns, 1);
@@ -3322,7 +3118,7 @@ do_identifier (token, parsing, args)
        return build_min_nt (LOOKUP_EXPR, token);
       else if (IDENTIFIER_OPNAME_P (token))
        {
-         if (token != ansi_opname[ERROR_MARK])
+         if (token != ansi_opname (ERROR_MARK))
            cp_error ("`%D' not defined", token);
          id = error_mark_node;
        }
index 1f595e05015d4046ce24873b0bd793b0387d1d9e..13d627ad17bd9beb41befc9e8a7a30e9477e3c6a 100644 (file)
@@ -520,12 +520,10 @@ mangle_expression (value)
     {
       int i;
       int operands = TREE_CODE_LENGTH (TREE_CODE (value));
-      tree id;
       const char *name;
 
-      id = ansi_opname [(int) TREE_CODE (value)];
-      my_friendly_assert (id != NULL_TREE, 0);
-      name = IDENTIFIER_POINTER (id);
+      name = operator_name_info[TREE_CODE (value)].mangled_name;
+      my_friendly_assert (name != NULL, 0);
       if (name[0] != '_' || name[1] != '_')
        /* On some erroneous inputs, we can get here with VALUE a
           LOOKUP_EXPR.  In that case, the NAME will be the
@@ -1576,31 +1574,47 @@ build_static_name (context, name)
    of a class (including a static member) and 2 if the declaration is
    for a constructor.  */
 tree 
-build_decl_overload_real (dname, parms, ret_type, tparms, targs,
+build_decl_overload_real (decl, parms, ret_type, tparms, targs,
                          for_method) 
-     tree dname;
+     tree decl;
      tree parms;
      tree ret_type;
      tree tparms;
      tree targs;
      int for_method;
 {
-  const char *name = IDENTIFIER_POINTER (dname);
+  const char *name;
+  enum tree_code operator_code;
+
+  operator_code = DECL_OVERLOADED_OPERATOR_P (decl);
+  if (!DECL_CONV_FN_P (decl) && operator_code)
+    {
+      /* member operators new and delete look like methods at this
+         point.  */
+      if (! for_method && CP_DECL_CONTEXT (decl) == global_namespace
+         && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST
+         && TREE_CHAIN (parms) == void_list_node)
+       switch (operator_code)
+         {
+         case DELETE_EXPR:
+           return get_identifier ("__builtin_delete");
+         case VEC_DELETE_EXPR:
+           return get_identifier ("__builtin_vec_delete");
+         case NEW_EXPR:
+           return get_identifier ("__builtin_new");
+         case VEC_NEW_EXPR:
+           return get_identifier ("__builtin_vec_new");
+         default:
+           break;
+         }
 
-  /* member operators new and delete look like methods at this point.  */
-  if (! for_method && current_namespace == global_namespace
-      && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST
-      && TREE_CHAIN (parms) == void_list_node)
-    {
-      if (dname == ansi_opname[(int) DELETE_EXPR])
-       return get_identifier ("__builtin_delete");
-      else if (dname == ansi_opname[(int) VEC_DELETE_EXPR])
-       return get_identifier ("__builtin_vec_delete");
-      if (dname == ansi_opname[(int) NEW_EXPR])
-       return get_identifier ("__builtin_new");
-      else if (dname == ansi_opname[(int) VEC_NEW_EXPR])
-       return get_identifier ("__builtin_vec_new");
+      if (DECL_ASSIGNMENT_OPERATOR_P (decl))
+       name = assignment_operator_name_info[(int) operator_code].mangled_name;
+      else
+       name = operator_name_info[(int) operator_code].mangled_name;
     }
+  else
+    name = IDENTIFIER_POINTER (DECL_NAME (decl));
 
   start_squangling ();
   OB_INIT ();
@@ -1618,15 +1632,12 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
       build_template_parm_names (tparms, targs);
       OB_PUTC ('_');
     }
-  else if (!for_method && current_namespace == global_namespace)
-    /* XXX this works only if we call this in the same namespace
-       as the declaration. Unfortunately, we don't have the _DECL,
-       only its name */
+  else if (!for_method && CP_DECL_CONTEXT (decl) == global_namespace)
     OB_PUTC ('F');
 
-  if (!for_method && current_namespace != global_namespace)
+  if (!for_method && CP_DECL_CONTEXT (decl) != global_namespace)
     /* qualify with namespace */
-    build_qualified_name (current_namespace);
+    build_qualified_name (CP_DECL_CONTEXT (decl));
 
   if (parms == NULL_TREE)
     OB_PUTC ('e');
@@ -1639,7 +1650,7 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
          /* Allocate typevec array.  */
          size_t typevec_size = list_length (parms);
           maxtype = 0;
-         if (!for_method && current_namespace != global_namespace)
+         if (!for_method && CP_DECL_CONTEXT (decl) != global_namespace)
            /* The namespace of a global function needs one slot.  */
            typevec_size++;
          VARRAY_TREE_INIT (typevec, typevec_size, "typevec");
@@ -1668,11 +1679,11 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
        {
          /* the namespace qualifier for a global function 
             will count as type */
-         if (current_namespace != global_namespace
+         if (CP_DECL_CONTEXT (decl) != global_namespace
              && !flag_do_squangling)
            {
              my_friendly_assert (maxtype < VARRAY_SIZE (typevec), 387);
-             VARRAY_TREE (typevec, maxtype) = current_namespace;
+             VARRAY_TREE (typevec, maxtype) = CP_DECL_CONTEXT (decl);
              maxtype++;
            }
          build_mangled_name (parms, 0, 0);
@@ -1694,31 +1705,10 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
   end_squangling ();
   {
     tree n = get_identifier (obstack_base (&scratch_obstack));
-    if (IDENTIFIER_OPNAME_P (dname))
-      IDENTIFIER_OPNAME_P (n) = 1;
     return n;
   }
 }
 
-/* Change the name of a function definition so that it may be
-   overloaded. NAME is the name of the function to overload,
-   PARMS is the parameter list (which determines what name the
-   final function obtains).
-
-   FOR_METHOD is 1 if this overload is being performed
-   for a method, rather than a function type.  It is 2 if
-   this overload is being performed for a constructor.  */
-
-tree
-build_decl_overload (dname, parms, for_method)
-     tree dname;
-     tree parms;
-     int for_method;
-{
-  return build_decl_overload_real (dname, parms, NULL_TREE, NULL_TREE,
-                                  NULL_TREE, for_method); 
-}
-
 /* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL.  */
 
 void
@@ -1746,9 +1736,10 @@ set_mangled_name_for_decl (decl)
                        0);
 
   DECL_ASSEMBLER_NAME (decl)
-    = build_decl_overload (DECL_NAME (decl), parm_types, 
-                          DECL_FUNCTION_MEMBER_P (decl)
-                          + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
+    = build_decl_overload_real (decl, parm_types, NULL_TREE,
+                               NULL_TREE, NULL_TREE,
+                               DECL_FUNCTION_MEMBER_P (decl)
+                               + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
 }
 
 /* Build an overload name for the type expression TYPE.  */
@@ -1760,7 +1751,7 @@ build_typename_overload (type)
   tree id;
 
   OB_INIT ();
-  OB_PUTID (ansi_opname[(int) TYPE_EXPR]);
+  OB_PUTS (OPERATOR_TYPENAME_FORMAT);
   nofold = 1;
   start_squangling ();
   build_mangled_name (type, 0, 1);
@@ -2367,7 +2358,7 @@ do_build_assign_ref (fndecl)
            (build_reference_type (basetype), parm,
             CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
          p = convert_from_reference (p);
-         p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
+         p = build_member_call (basetype, ansi_assopname (NOP_EXPR),
                                 build_tree_list (NULL_TREE, p));
          finish_expr_stmt (p);
        }
@@ -2467,7 +2458,7 @@ synthesize_method (fndecl)
   store_parm_decls ();
   clear_last_expr ();
 
-  if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])
+  if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
     {
       do_build_assign_ref (fndecl);
       need_body = 0;
@@ -2550,7 +2541,7 @@ implicitly_declare_fn (kind, type, const_p)
       if (const_p)
        type = build_qualified_type (type, TYPE_QUAL_CONST);
 
-      name = ansi_opname [(int) MODIFY_EXPR];
+      name = ansi_assopname (NOP_EXPR);
 
       argtype = build_reference_type (type);
       args = tree_cons (NULL_TREE,
diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def
new file mode 100644 (file)
index 0000000..1ad8d04
--- /dev/null
@@ -0,0 +1,153 @@
+/* -*-C-*-
+       
+   This file contains definitions of the various C++ operators,
+   including both overloadable operators (like `+') and
+   non-overloadable operators (like the `?:' ternary operator).  
+   Writtey by Mark Mitchell <mark@codesourcery.com>
+
+   Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* The DEF_OPERATOR macro takes the following arguments:
+
+   NAME
+
+     The name of the operator, as a C string, but without the
+     preceeding `operator'.  This is the name that would be given in
+     the source program.  For `operator +', for example, this would be
+     `+'.
+   
+   CODE
+
+     The tree_code for this operator.  For `operator +', for example,
+     this would be PLUS_EXPR.  Because there are no tree codes for
+     assignment operators, the same tree-codes are reused; i.e.,
+     `operator +' will also have PLUS_EXPR as its CODE.
+
+   NEW_MANGLING
+
+     The mangling prefix for the operator, as a C string, and as
+     mangled under the new ABI.  For `operator +', for example, this
+     would be "pl".
+
+   OLD_MANGLING
+
+     Analagous, but for the old ABI.
+
+   ARITY
+   
+     The arity of the operator, or -1 if any arity is allowed.  (As
+     for `operator ()'.)  Postincrement and postdecrement operators
+     are marked as binary.
+
+   ASSN_P
+
+     A boolean value.  If non-zero, this is an assignment operator.  
+
+   Before including this file, you should define DEFOPERATOR
+   to take these arguments.  
+
+   There is code (such as in grok_op_properties) that depends on the
+   order the operators are presented in this file.  In particular,
+   unary operators must preceed binary operators.  */
+/* Use DEF_SIMPLE_OPERATOR to define a non-assignment operator.  Its
+   arguments are as for DEF_OPERATOR, but there is no need to provide
+   an ASSIGNMENT_P argument; it is always zero.  */
+
+#define DEF_SIMPLE_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY) \
+  DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY, 0)
+
+/* Use DEF_ASSN_OPERATOR to define an assignment operator.  Its
+   arguments are as for DEF_OPERATOR, but there is no need to provide
+   an ASSIGNMENT_P argument; it is always one.  */
+
+#define DEF_ASSN_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY) \
+  DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY, 1)
+
+/* Memory allocation operators.  */
+DEF_SIMPLE_OPERATOR ("new", NEW_EXPR, "nw", "__nw", -1)
+DEF_SIMPLE_OPERATOR ("new []", VEC_NEW_EXPR, "na", "__vn", -1)
+DEF_SIMPLE_OPERATOR ("delete", DELETE_EXPR, "dl", "__dl", -1)
+DEF_SIMPLE_OPERATOR ("delete []", VEC_DELETE_EXPR, "da", "__vd", -1)
+
+/* Unary operators.  */
+DEF_SIMPLE_OPERATOR ("+", CONVERT_EXPR, "ps", "__pl", 1)
+DEF_SIMPLE_OPERATOR ("-", NEGATE_EXPR, "ng", "__mi", 1)
+DEF_SIMPLE_OPERATOR ("&", ADDR_EXPR, "ad", "__ad", 1)
+DEF_SIMPLE_OPERATOR ("*", INDIRECT_REF, "de", "__ml", 1)
+DEF_SIMPLE_OPERATOR ("~", BIT_NOT_EXPR, "co", "__co", 1)
+DEF_SIMPLE_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", "__nt", 1)
+DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", "__pp", 1)
+DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", "__mm", 1)
+DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", "__sz", 1)
+/* This is an extension.  */
+DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "vx7alignof", "__al", 1)
+
+/* The cast operator.  */
+DEF_SIMPLE_OPERATOR ("", TYPE_EXPR, "cv", OPERATOR_TYPENAME_FORMAT, 1)
+
+/* Binary operators.  */
+DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", "__pl", 2)
+DEF_SIMPLE_OPERATOR ("-", MINUS_EXPR, "mi", "__mi", 2)
+DEF_SIMPLE_OPERATOR ("*", MULT_EXPR, "ml", "__ml", 2)
+DEF_SIMPLE_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", "__dv", 2)
+DEF_SIMPLE_OPERATOR ("%", TRUNC_MOD_EXPR, "md", "__md", 2)
+DEF_SIMPLE_OPERATOR ("&", BIT_AND_EXPR, "an", "__ad", 2)
+DEF_SIMPLE_OPERATOR ("|", BIT_IOR_EXPR, "or", "__or", 2)
+DEF_SIMPLE_OPERATOR ("^", BIT_XOR_EXPR, "eo", "__er", 2)
+DEF_SIMPLE_OPERATOR ("<<", LSHIFT_EXPR, "ls", "__ls", 2)
+DEF_SIMPLE_OPERATOR (">>", RSHIFT_EXPR, "rs", "__rs", 2)
+DEF_SIMPLE_OPERATOR ("==", EQ_EXPR, "eq", "__eq", 2)
+DEF_SIMPLE_OPERATOR ("!=", NE_EXPR, "ne", "__ne", 2)
+DEF_SIMPLE_OPERATOR ("<", LT_EXPR, "lt", "__lt", 2)
+DEF_SIMPLE_OPERATOR (">", GT_EXPR, "gt", "__gt", 2)
+DEF_SIMPLE_OPERATOR ("<=", LE_EXPR, "le", "__le", 2)
+DEF_SIMPLE_OPERATOR (">=", GE_EXPR, "ge", "__ge", 2)
+DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", "__aa", 2)
+DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", "__oo", 2)
+DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", "__cm", 2)
+DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", "__rm", 2)
+DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", "__rf", 2)
+DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", "__vc", 2)
+DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", "__pp", 2)
+DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", "__mm", 2)
+/* These are extensions.  */
+DEF_SIMPLE_OPERATOR ("<?", MIN_EXPR, "vx3min", "__mn", 2)
+DEF_SIMPLE_OPERATOR ("<?", MAX_EXPR, "vx3max", "__mx", 2)
+
+/* Assignment operators.  */
+DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", "__as", 2)
+DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL", "__apl", 2)
+DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI", "__ami", 2)
+DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL", "__aml", 2)
+DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV", "__adv", 2)
+DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "mD", "__amd", 2)
+DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN", "__aad", 2)
+DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR", "__aor", 2)
+DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO", "__aer", 2)
+DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", "__als", 2)
+DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", "__ars", 2)
+
+/* Ternary operators.  */
+DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", "__cn", 3)
+
+/* Miscellaneous.  */
+DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", "__cl", -1)
+
index 407025e3525ef72bb1e0c42c2702f704a5dee0b4..9cb24dd90b0976566283ae748909df81adcfb195 100644 (file)
@@ -8090,135 +8090,135 @@ case 843:
     break;}
 case 844:
 #line 3674 "parse.y"
-{ yyval.ttype = ansi_opname[MULT_EXPR]; ;
+{ yyval.ttype = ansi_opname (MULT_EXPR); ;
     break;}
 case 845:
 #line 3676 "parse.y"
-{ yyval.ttype = ansi_opname[TRUNC_DIV_EXPR]; ;
+{ yyval.ttype = ansi_opname (TRUNC_DIV_EXPR); ;
     break;}
 case 846:
 #line 3678 "parse.y"
-{ yyval.ttype = ansi_opname[TRUNC_MOD_EXPR]; ;
+{ yyval.ttype = ansi_opname (TRUNC_MOD_EXPR); ;
     break;}
 case 847:
 #line 3680 "parse.y"
-{ yyval.ttype = ansi_opname[PLUS_EXPR]; ;
+{ yyval.ttype = ansi_opname (PLUS_EXPR); ;
     break;}
 case 848:
 #line 3682 "parse.y"
-{ yyval.ttype = ansi_opname[MINUS_EXPR]; ;
+{ yyval.ttype = ansi_opname (MINUS_EXPR); ;
     break;}
 case 849:
 #line 3684 "parse.y"
-{ yyval.ttype = ansi_opname[BIT_AND_EXPR]; ;
+{ yyval.ttype = ansi_opname (BIT_AND_EXPR); ;
     break;}
 case 850:
 #line 3686 "parse.y"
-{ yyval.ttype = ansi_opname[BIT_IOR_EXPR]; ;
+{ yyval.ttype = ansi_opname (BIT_IOR_EXPR); ;
     break;}
 case 851:
 #line 3688 "parse.y"
-{ yyval.ttype = ansi_opname[BIT_XOR_EXPR]; ;
+{ yyval.ttype = ansi_opname (BIT_XOR_EXPR); ;
     break;}
 case 852:
 #line 3690 "parse.y"
-{ yyval.ttype = ansi_opname[BIT_NOT_EXPR]; ;
+{ yyval.ttype = ansi_opname (BIT_NOT_EXPR); ;
     break;}
 case 853:
 #line 3692 "parse.y"
-{ yyval.ttype = ansi_opname[COMPOUND_EXPR]; ;
+{ yyval.ttype = ansi_opname (COMPOUND_EXPR); ;
     break;}
 case 854:
 #line 3694 "parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
+{ yyval.ttype = ansi_opname (yyvsp[0].code); ;
     break;}
 case 855:
 #line 3696 "parse.y"
-{ yyval.ttype = ansi_opname[LT_EXPR]; ;
+{ yyval.ttype = ansi_opname (LT_EXPR); ;
     break;}
 case 856:
 #line 3698 "parse.y"
-{ yyval.ttype = ansi_opname[GT_EXPR]; ;
+{ yyval.ttype = ansi_opname (GT_EXPR); ;
     break;}
 case 857:
 #line 3700 "parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
+{ yyval.ttype = ansi_opname (yyvsp[0].code); ;
     break;}
 case 858:
 #line 3702 "parse.y"
-{ yyval.ttype = ansi_assopname[yyvsp[0].code]; ;
+{ yyval.ttype = ansi_assopname (yyvsp[0].code); ;
     break;}
 case 859:
 #line 3704 "parse.y"
-{ yyval.ttype = ansi_opname [MODIFY_EXPR]; ;
+{ yyval.ttype = ansi_assopname (NOP_EXPR); ;
     break;}
 case 860:
 #line 3706 "parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
+{ yyval.ttype = ansi_opname (yyvsp[0].code); ;
     break;}
 case 861:
 #line 3708 "parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
+{ yyval.ttype = ansi_opname (yyvsp[0].code); ;
     break;}
 case 862:
 #line 3710 "parse.y"
-{ yyval.ttype = ansi_opname[POSTINCREMENT_EXPR]; ;
+{ yyval.ttype = ansi_opname (POSTINCREMENT_EXPR); ;
     break;}
 case 863:
 #line 3712 "parse.y"
-{ yyval.ttype = ansi_opname[PREDECREMENT_EXPR]; ;
+{ yyval.ttype = ansi_opname (PREDECREMENT_EXPR); ;
     break;}
 case 864:
 #line 3714 "parse.y"
-{ yyval.ttype = ansi_opname[TRUTH_ANDIF_EXPR]; ;
+{ yyval.ttype = ansi_opname (TRUTH_ANDIF_EXPR); ;
     break;}
 case 865:
 #line 3716 "parse.y"
-{ yyval.ttype = ansi_opname[TRUTH_ORIF_EXPR]; ;
+{ yyval.ttype = ansi_opname (TRUTH_ORIF_EXPR); ;
     break;}
 case 866:
 #line 3718 "parse.y"
-{ yyval.ttype = ansi_opname[TRUTH_NOT_EXPR]; ;
+{ yyval.ttype = ansi_opname (TRUTH_NOT_EXPR); ;
     break;}
 case 867:
 #line 3720 "parse.y"
-{ yyval.ttype = ansi_opname[COND_EXPR]; ;
+{ yyval.ttype = ansi_opname (COND_EXPR); ;
     break;}
 case 868:
 #line 3722 "parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
+{ yyval.ttype = ansi_opname (yyvsp[0].code); ;
     break;}
 case 869:
 #line 3724 "parse.y"
-{ yyval.ttype = ansi_opname[COMPONENT_REF]; ;
+{ yyval.ttype = ansi_opname (COMPONENT_REF); ;
     break;}
 case 870:
 #line 3726 "parse.y"
-{ yyval.ttype = ansi_opname[MEMBER_REF]; ;
+{ yyval.ttype = ansi_opname (MEMBER_REF); ;
     break;}
 case 871:
 #line 3728 "parse.y"
-{ yyval.ttype = ansi_opname[CALL_EXPR]; ;
+{ yyval.ttype = ansi_opname (CALL_EXPR); ;
     break;}
 case 872:
 #line 3730 "parse.y"
-{ yyval.ttype = ansi_opname[ARRAY_REF]; ;
+{ yyval.ttype = ansi_opname (ARRAY_REF); ;
     break;}
 case 873:
 #line 3732 "parse.y"
-{ yyval.ttype = ansi_opname[NEW_EXPR]; ;
+{ yyval.ttype = ansi_opname (NEW_EXPR); ;
     break;}
 case 874:
 #line 3734 "parse.y"
-{ yyval.ttype = ansi_opname[DELETE_EXPR]; ;
+{ yyval.ttype = ansi_opname (DELETE_EXPR); ;
     break;}
 case 875:
 #line 3736 "parse.y"
-{ yyval.ttype = ansi_opname[VEC_NEW_EXPR]; ;
+{ yyval.ttype = ansi_opname (VEC_NEW_EXPR); ;
     break;}
 case 876:
 #line 3738 "parse.y"
-{ yyval.ttype = ansi_opname[VEC_DELETE_EXPR]; ;
+{ yyval.ttype = ansi_opname (VEC_DELETE_EXPR); ;
     break;}
 case 877:
 #line 3741 "parse.y"
@@ -8226,7 +8226,7 @@ case 877:
     break;}
 case 878:
 #line 3743 "parse.y"
-{ yyval.ttype = ansi_opname[ERROR_MARK]; ;
+{ yyval.ttype = ansi_opname (ERROR_MARK); ;
     break;}
 }
    /* the action file gets copied in in place of this dollarsign */
index 65b90bb7ec91f54dfc180553be33d9061e141b0f..6f26be4e35f48cf6f76b70b56a364a4a96e2512a 100644 (file)
@@ -3671,76 +3671,76 @@ operator:
 
 operator_name:
          operator '*'
-               { $$ = ansi_opname[MULT_EXPR]; }
+               { $$ = ansi_opname (MULT_EXPR); }
        | operator '/'
-               { $$ = ansi_opname[TRUNC_DIV_EXPR]; }
+               { $$ = ansi_opname (TRUNC_DIV_EXPR); }
        | operator '%'
-               { $$ = ansi_opname[TRUNC_MOD_EXPR]; }
+               { $$ = ansi_opname (TRUNC_MOD_EXPR); }
        | operator '+'
-               { $$ = ansi_opname[PLUS_EXPR]; }
+               { $$ = ansi_opname (PLUS_EXPR); }
        | operator '-'
-               { $$ = ansi_opname[MINUS_EXPR]; }
+               { $$ = ansi_opname (MINUS_EXPR); }
        | operator '&'
-               { $$ = ansi_opname[BIT_AND_EXPR]; }
+               { $$ = ansi_opname (BIT_AND_EXPR); }
        | operator '|'
-               { $$ = ansi_opname[BIT_IOR_EXPR]; }
+               { $$ = ansi_opname (BIT_IOR_EXPR); }
        | operator '^'
-               { $$ = ansi_opname[BIT_XOR_EXPR]; }
+               { $$ = ansi_opname (BIT_XOR_EXPR); }
        | operator '~'
-               { $$ = ansi_opname[BIT_NOT_EXPR]; }
+               { $$ = ansi_opname (BIT_NOT_EXPR); }
        | operator ','
-               { $$ = ansi_opname[COMPOUND_EXPR]; }
+               { $$ = ansi_opname (COMPOUND_EXPR); }
        | operator ARITHCOMPARE
-               { $$ = ansi_opname[$2]; }
+               { $$ = ansi_opname ($2); }
        | operator '<'
-               { $$ = ansi_opname[LT_EXPR]; }
+               { $$ = ansi_opname (LT_EXPR); }
        | operator '>'
-               { $$ = ansi_opname[GT_EXPR]; }
+               { $$ = ansi_opname (GT_EXPR); }
        | operator EQCOMPARE
-               { $$ = ansi_opname[$2]; }
+               { $$ = ansi_opname ($2); }
        | operator ASSIGN
-               { $$ = ansi_assopname[$2]; }
+               { $$ = ansi_assopname ($2); }
        | operator '='
-               { $$ = ansi_opname [MODIFY_EXPR]; }
+               { $$ = ansi_assopname (NOP_EXPR); }
        | operator LSHIFT
-               { $$ = ansi_opname[$2]; }
+               { $$ = ansi_opname ($2); }
        | operator RSHIFT
-               { $$ = ansi_opname[$2]; }
+               { $$ = ansi_opname ($2); }
        | operator PLUSPLUS
-               { $$ = ansi_opname[POSTINCREMENT_EXPR]; }
+               { $$ = ansi_opname (POSTINCREMENT_EXPR); }
        | operator MINUSMINUS
-               { $$ = ansi_opname[PREDECREMENT_EXPR]; }
+               { $$ = ansi_opname (PREDECREMENT_EXPR); }
        | operator ANDAND
-               { $$ = ansi_opname[TRUTH_ANDIF_EXPR]; }
+               { $$ = ansi_opname (TRUTH_ANDIF_EXPR); }
        | operator OROR
-               { $$ = ansi_opname[TRUTH_ORIF_EXPR]; }
+               { $$ = ansi_opname (TRUTH_ORIF_EXPR); }
        | operator '!'
-               { $$ = ansi_opname[TRUTH_NOT_EXPR]; }
+               { $$ = ansi_opname (TRUTH_NOT_EXPR); }
        | operator '?' ':'
-               { $$ = ansi_opname[COND_EXPR]; }
+               { $$ = ansi_opname (COND_EXPR); }
        | operator MIN_MAX
-               { $$ = ansi_opname[$2]; }
+               { $$ = ansi_opname ($2); }
        | operator POINTSAT  %prec EMPTY
-               { $$ = ansi_opname[COMPONENT_REF]; }
+               { $$ = ansi_opname (COMPONENT_REF); }
        | operator POINTSAT_STAR  %prec EMPTY
-               { $$ = ansi_opname[MEMBER_REF]; }
+               { $$ = ansi_opname (MEMBER_REF); }
        | operator LEFT_RIGHT
-               { $$ = ansi_opname[CALL_EXPR]; }
+               { $$ = ansi_opname (CALL_EXPR); }
        | operator '[' ']'
-               { $$ = ansi_opname[ARRAY_REF]; }
+               { $$ = ansi_opname (ARRAY_REF); }
        | operator NEW  %prec EMPTY
-               { $$ = ansi_opname[NEW_EXPR]; }
+               { $$ = ansi_opname (NEW_EXPR); }
        | operator DELETE  %prec EMPTY
-               { $$ = ansi_opname[DELETE_EXPR]; }
+               { $$ = ansi_opname (DELETE_EXPR); }
        | operator NEW '[' ']'
-               { $$ = ansi_opname[VEC_NEW_EXPR]; }
+               { $$ = ansi_opname (VEC_NEW_EXPR); }
        | operator DELETE '[' ']'
-               { $$ = ansi_opname[VEC_DELETE_EXPR]; }
+               { $$ = 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]; }
+               { $$ = ansi_opname (ERROR_MARK); }
        ;
 
 %%
index 5e2ff5e4735ed6bb24557da8ff530dbd0cf1f5d2..b64fc72a72edcf1680c99cf30131db7a26c2c6f4 100644 (file)
@@ -5790,7 +5790,7 @@ tsubst_decl (t, args, type, in_decl)
            if (DECL_CONSTRUCTOR_P (r))
              grok_ctor_properties (ctx, r);
          }
-       else if (DECL_OVERLOADED_OPERATOR_P (r))
+       else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
          grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
       }
       break;
@@ -9869,7 +9869,6 @@ static void
 set_mangled_name_for_template_decl (decl)
      tree decl;
 {
-  tree saved_namespace;
   tree context = NULL_TREE;
   tree fn_type;
   tree ret_type;
@@ -9985,21 +9984,10 @@ set_mangled_name_for_template_decl (decl)
   my_friendly_assert (TREE_VEC_LENGTH (tparms) == TREE_VEC_LENGTH (targs),
                      0);
 
-  /* If the template is in a namespace, we need to put that into the
-     mangled name. Unfortunately, build_decl_overload_real does not
-     get the decl to mangle, so it relies on the current
-     namespace. Therefore, we set that here temporarily. */
-  my_friendly_assert (DECL_P (decl), 980702);
-  saved_namespace = current_namespace;
-  current_namespace = CP_DECL_CONTEXT (decl);  
-
   /* Actually set the DCL_ASSEMBLER_NAME.  */
   DECL_ASSEMBLER_NAME (decl)
-    = build_decl_overload_real (DECL_NAME (decl), parm_types, ret_type,
+    = build_decl_overload_real (decl, parm_types, ret_type,
                                tparms, targs, 
                                DECL_FUNCTION_MEMBER_P (decl) 
                                + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
-
-  /* Restore the previously active namespace.  */
-  current_namespace = saved_namespace;
 }
index b62fc611625e2af787149ec7fa85927b7fede6fb..382e254c4f3eeb6ca7b2522d5caf3c5c21229b72 100644 (file)
@@ -2429,7 +2429,7 @@ special_function_p (decl)
     return sfk_copy_constructor;
   if (DECL_CONSTRUCTOR_P (decl))
     return sfk_constructor;
-  if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
+  if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
     return sfk_assignment_operator;
   if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
     return sfk_destructor;
index c0927efbe00a52461601b3cd881ceb0da6c0079b..28ac0f31bc8c7c9782ce09b6844f3da5d3d7cc13 100644 (file)
@@ -6836,15 +6836,15 @@ check_return_expr (retval)
     current_function_returns_null = 1;
 
   /* Only operator new(...) throw(), can return NULL [expr.new/13].  */
-  if ((DECL_NAME (current_function_decl) == ansi_opname[(int) NEW_EXPR]
-       || DECL_NAME (current_function_decl) == ansi_opname[(int) VEC_NEW_EXPR])
+  if ((DECL_OVERLOADED_OPERATOR_P (current_function_decl) == NEW_EXPR
+       || DECL_OVERLOADED_OPERATOR_P (current_function_decl) == VEC_NEW_EXPR)
       && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
       && null_ptr_cst_p (retval))
     cp_warning ("`operator new' should throw an exception, not return NULL");
 
   /* Effective C++ rule 15.  See also start_function.  */
   if (warn_ecpp
-      && DECL_NAME (current_function_decl) == ansi_opname[(int) MODIFY_EXPR]
+      && DECL_NAME (current_function_decl) == ansi_assopname(NOP_EXPR)
       && retval != current_class_ref)
     cp_warning ("`operator=' should return a reference to `*this'");
 
diff --git a/gcc/testsuite/g++.old-deja/g++.other/op1.C b/gcc/testsuite/g++.old-deja/g++.other/op1.C
new file mode 100644 (file)
index 0000000..cf36886
--- /dev/null
@@ -0,0 +1,6 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+struct S {
+  bool operator! (int, ...); // ERROR - 
+};