+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.
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:
$(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 \
{
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)),
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;
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
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)
{
candidates = add_builtin_candidates (candidates,
COND_EXPR,
NOP_EXPR,
- ansi_opname[COND_EXPR],
+ ansi_opname (COND_EXPR),
args,
LOOKUP_NORMAL);
{
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)
{
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
{
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)
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]
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)))
{
/* 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);
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. */
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;
/* 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. */
/* 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
#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
/* 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
};
/* 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));
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));
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
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));
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));
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));
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));
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
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
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;
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);
TREE_PUBLIC (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
TREE_NOTHROW (fn) = 1;
+ SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
return fn;
}
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);
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
/* 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;
}
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))
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;
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
{
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)
{
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. */
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. */
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);
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
{
}
}
- 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))
}
}
- 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;
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))
{
/* 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)),
}
}
}
- 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);
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);
/* 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);
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);
/* 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'");
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
}
#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))));
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);
}
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);
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:
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;
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 *
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 *
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
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. */
/* ??? 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 */
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
}
}
-/* 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 ()
{
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;
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, "");
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);
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.
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);
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;
}
{
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
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 ();
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');
/* 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");
{
/* 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);
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
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. */
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);
(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);
}
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;
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,
--- /dev/null
+/* -*-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)
+
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"
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 */
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); }
;
%%
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;
set_mangled_name_for_template_decl (decl)
tree decl;
{
- tree saved_namespace;
tree context = NULL_TREE;
tree fn_type;
tree ret_type;
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;
}
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;
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'");
--- /dev/null
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+struct S {
+ bool operator! (int, ...); // ERROR -
+};