/* Handle the hair of processing (but not expanding) inline functions.
Also manage function and variable name overloading.
- Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
- This file is part of GNU CC.
+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
/* Handle method declarations. */
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "tree.h"
#include "cp-tree.h"
#include "obstack.h"
-#include <ctype.h>
#include "rtl.h"
#include "expr.h"
#include "output.h"
#include "hard-reg-set.h"
#include "flags.h"
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
-#ifdef NEED_DECLARATION_INDEX
-extern char *index ();
-#endif
+#include "toplev.h"
/* TREE_LIST of the current inline functions that need to be
processed. */
static void icat PROTO((HOST_WIDE_INT));
static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT));
-static void flush_repeats PROTO((tree));
+static void flush_repeats PROTO((int, tree));
static void build_overload_identifier PROTO((tree));
static void build_overload_nested_name PROTO((tree));
static void build_overload_int PROTO((tree, int));
static void build_overload_identifier PROTO((tree));
static void build_qualified_name PROTO((tree));
static void build_overload_value PROTO((tree, tree, int));
-static void issue_nrepeats PROTO((tree));
+static void issue_nrepeats PROTO((int, tree));
static char *build_mangled_name PROTO((tree,int,int));
static void process_modifiers PROTO((tree));
static void process_overload_item PROTO((tree,int));
-static char *thunk_printable_name PROTO((tree));
static void do_build_assign_ref PROTO((tree));
static void do_build_copy_constructor PROTO((tree));
static tree largest_union_member PROTO((tree));
static void build_template_template_parm_names PROTO((tree));
static void build_template_parm_names PROTO((tree, tree));
static void build_underscore_int PROTO((int));
+static void start_squangling PROTO((void));
+static void end_squangling PROTO((void));
+static int check_ktype PROTO((tree, int));
+static int issue_ktype PROTO((tree));
+static void build_overload_scope_ref PROTO((tree));
+static void build_mangled_template_parm_index PROTO((char *, tree));
+static int is_back_referenceable_type PROTO((tree));
+static int check_btype PROTO((tree));
+static void build_mangled_name_for_type PROTO((tree));
+static void build_mangled_name_for_type_with_Gcode PROTO((tree, int));
# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
/* type tables for K and B type compression */
static tree *btypelist = NULL;
static tree *ktypelist = NULL;
-static tree lasttype = NULL;
static int maxbsize = 0;
static int maxksize = 0;
static int maxbtype = 0;
static int maxktype = 0;
-/* Number of occurrences of last b type seen. */
-static int nrepeats = 0;
-
/* Array of types seen so far in top-level call to `build_mangled_name'.
Allocated and deallocated by caller. */
static tree *typevec = NULL;
+static int typevec_size;
/* Number of types interned by `build_mangled_name' so far. */
static int maxtype = 0;
-/* Number of occurrences of last type seen. */
-static int Nrepeats = 0;
-
/* Nonzero if we should not try folding parameter types. */
static int nofold;
{
if (flag_do_squangling)
{
- lasttype = NULL;
nofold = 0;
- nrepeats = 0;
maxbtype = 0;
maxktype = 0;
maxbsize = 50;
{
if (flag_do_squangling)
{
- lasttype = NULL;
if (ktypelist)
free (ktypelist);
if (btypelist)
}
static __inline void
-flush_repeats (type)
+flush_repeats (nrepeats, type)
+ int nrepeats;
tree type;
{
int tindex = 0;
while (typevec[tindex] != type)
tindex++;
- if (Nrepeats > 1)
+ if (nrepeats > 1)
{
OB_PUTC ('N');
- icat (Nrepeats);
- if (Nrepeats > 9)
+ icat (nrepeats);
+ if (nrepeats > 9)
OB_PUTC ('_');
}
else
OB_PUTC ('T');
- Nrepeats = 0;
icat (tindex);
if (tindex > 9)
OB_PUTC ('_');
}
+/* Returns nonzero iff this is a type to which we will want to make
+ back-references (using the `B' code). */
-/* issue squangling type repeating */
-static void
-issue_nrepeats (lasttype)
- tree lasttype;
+int
+is_back_referenceable_type (type)
+ tree type;
{
- if (nrepeats == 1)
+ if (btypelist == NULL)
+ /* We're not generating any back-references. */
+ return 0;
+
+ switch (TREE_CODE (type))
{
- switch (TREE_CODE (lasttype))
- {
- case INTEGER_TYPE:
- case REAL_TYPE:
- case VOID_TYPE:
- case BOOLEAN_TYPE:
- process_overload_item (lasttype, FALSE);
- nrepeats = 0;
- return;
- }
+ case INTEGER_TYPE:
+ case REAL_TYPE:
+ case VOID_TYPE:
+ case BOOLEAN_TYPE:
+ /* These types have single-character manglings, so there's no
+ point in generating back-references. */
+ return 0;
+
+ case TEMPLATE_TYPE_PARM:
+ /* It would be a bit complex to demangle signatures correctly if
+ we generated back-references to these, and the manglings of
+ type parameters are short. */
+ return 0;
+
+ default:
+ return 1;
}
- OB_PUTC ('n');
- icat (nrepeats);
- if (nrepeats > 9)
- OB_PUTC ('_');
- nrepeats = 0;
}
+/* Issue the squangling code indicating NREPEATS repetitions of TYPE,
+ which was the last parameter type output. */
+
+static void
+issue_nrepeats (nrepeats, type)
+ int nrepeats;
+ tree type;
+{
+ if (nrepeats == 1 && !is_back_referenceable_type (type))
+ /* For types whose manglings are short, don't bother using the
+ repetition code if there's only one repetition, since the
+ repetition code will be about as long as the ordinary mangling. */
+ build_mangled_name_for_type (type);
+ else
+ {
+ OB_PUTC ('n');
+ icat (nrepeats);
+ if (nrepeats > 9)
+ OB_PUTC ('_');
+ }
+}
/* Check to see if a tree node has been entered into the Kcode typelist */
/* if not, add it. Return -1 if it isn't found, otherwise return the index */
if (maxksize <= maxktype)
{
maxksize = maxksize* 3 / 2;
- ktypelist = (tree *)xrealloc (sizeof (tree) * maxksize);
+ ktypelist = (tree *)xrealloc (ktypelist, sizeof (tree) * maxksize);
}
ktypelist[maxktype++] = localnode;
}
}
return FALSE;
}
+
+/* Build a representation for DECL, which may be an entity not at
+ global scope. If so, a marker indicating that the name is
+ qualified has already been output, but the qualifying context has
+ not. */
static void
build_overload_nested_name (decl)
tree decl;
{
+ tree context;
if (ktypelist && issue_ktype (decl))
return;
- if (DECL_CONTEXT (decl))
- {
- tree context = DECL_CONTEXT (decl);
+ if (decl == global_namespace)
+ return;
- /* try to issue a K type, and if we can't continue the normal path */
- if (!(ktypelist && issue_ktype (context)))
- {
- /* For a template type parameter, we want to output an 'Xn'
- rather than 'T' or some such. */
- if (TREE_CODE (context) == TEMPLATE_TYPE_PARM
- || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM)
- build_mangled_name (context, 0, 0);
- else
- {
- if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
- context = TYPE_NAME (context);
- build_overload_nested_name (context);
- }
- }
+ context = CP_DECL_CONTEXT (decl);
+
+ /* try to issue a K type, and if we can't continue the normal path */
+ if (!(ktypelist && issue_ktype (context)))
+ {
+ /* For a template type parameter, we want to output an 'Xn'
+ rather than 'T' or some such. */
+ if (TREE_CODE (context) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM)
+ build_mangled_name_for_type (context);
+ else
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
+ context = TYPE_NAME (context);
+ build_overload_nested_name (context);
}
- else if (decl == global_namespace)
- return;
- else if (DECL_NAMESPACE (decl))
- build_overload_nested_name (DECL_NAMESPACE (decl));
- else
- /* XXX the above does not work for non-namespaces */
- if (current_namespace && TREE_CODE (decl) != NAMESPACE_DECL)
- build_overload_nested_name (current_namespace);
+ }
if (TREE_CODE (decl) == FUNCTION_DECL)
{
build_overload_identifier (decl);
}
+/* Output the decimal representation of I. If I > 9, the decimal
+ representation is preceeded and followed by an underscore. */
+
static void
build_underscore_int (i)
int i;
OB_PUTC ('_');
}
+static void
+build_overload_scope_ref (value)
+ tree value;
+{
+ OB_PUTC2 ('Q', '2');
+ numeric_output_need_bar = 0;
+ build_mangled_name_for_type (TREE_OPERAND (value, 0));
+ build_overload_identifier (TREE_OPERAND (value, 1));
+}
+
/* Encoding for an INTEGER_CST value. */
static void
int in_template;
{
if (in_template && TREE_CODE (value) != INTEGER_CST)
- /* We don't ever want this output, but it's inconvenient not to
- be able to build the string. This should cause assembler
- errors we'll notice. */
{
- static int n;
- sprintf (digit_buffer, " *%d", n++);
- OB_PUTCP (digit_buffer);
+ if (TREE_CODE (value) == SCOPE_REF)
+ {
+ build_overload_scope_ref (value);
+ return;
+ }
+
+ OB_PUTC ('E');
+ numeric_output_need_bar = 0;
+
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value))))
+ {
+ int i;
+ int operands = tree_code_length[(int) TREE_CODE (value)];
+ tree id;
+ char* name;
+
+ id = ansi_opname [(int) TREE_CODE (value)];
+ my_friendly_assert (id != NULL_TREE, 0);
+ name = IDENTIFIER_POINTER (id);
+ 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
+ identifier for "<invalid operator>". We must survive
+ this routine in order to issue a sensible error
+ message, so we fall through to the case below. */
+ goto bad_value;
+
+ for (i = 0; i < operands; ++i)
+ {
+ tree operand;
+ enum tree_code tc;
+
+ /* We just outputted either the `E' or the name of the
+ operator. */
+ numeric_output_need_bar = 0;
+
+ if (i != 0)
+ /* Skip the leading underscores. */
+ OB_PUTCP (name + 2);
+
+ operand = TREE_OPERAND (value, i);
+ tc = TREE_CODE (operand);
+
+ if (TREE_CODE_CLASS (tc) == 't')
+ /* We can get here with sizeof, e.g.:
+
+ template <class T> void f(A<sizeof(T)>); */
+ build_mangled_name_for_type (operand);
+ else if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc)))
+ build_overload_int (operand, in_template);
+ else
+ build_overload_value (TREE_TYPE (operand),
+ operand,
+ in_template);
+ }
+ }
+ else
+ {
+ /* We don't ever want this output, but it's
+ inconvenient not to be able to build the string.
+ This should cause assembler errors we'll notice. */
+
+ static int n;
+ bad_value:
+ sprintf (digit_buffer, " *%d", n++);
+ OB_PUTCP (digit_buffer);
+ }
+
+ OB_PUTC ('W');
+ numeric_output_need_bar = 0;
return;
}
{
/* need to print a DImode value in decimal */
dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value));
+ numeric_output_need_bar = 1;
return;
}
/* else fall through to print in smaller mode */
}
/* Wordsize or smaller */
icat (TREE_INT_CST_LOW (value));
+ numeric_output_need_bar = 1;
}
while (TREE_CODE (value) == NON_LVALUE_EXPR
|| TREE_CODE (value) == NOP_EXPR)
value = TREE_OPERAND (value, 0);
- my_friendly_assert (TREE_CODE (type) == PARM_DECL, 242);
- type = TREE_TYPE (type);
+
+ if (TREE_CODE (type) == PARM_DECL)
+ type = TREE_TYPE (type);
+
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0);
if (numeric_output_need_bar)
{
case BOOLEAN_TYPE:
{
build_overload_int (value, in_template);
- numeric_output_need_bar = 1;
return;
}
case REAL_TYPE:
{
OB_PUTC ('i');
build_overload_int (a3, in_template);
- numeric_output_need_bar = 1;
return;
}
}
if (TREE_CODE (value) == INTEGER_CST)
{
build_overload_int (value, in_template);
- numeric_output_need_bar = 1;
return;
}
else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
return;
}
else if (TREE_CODE (value) == SCOPE_REF)
- {
- OB_PUTC2 ('Q', '1');
- numeric_output_need_bar = 0;
- build_mangled_name (TREE_OPERAND (value, 0), 0, 0);
- build_overload_identifier (TREE_OPERAND (value, 1));
- return;
- }
+ build_overload_scope_ref (value);
else
my_friendly_abort (71);
break; /* not really needed */
build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm));
}
else
- {
- /* It's a PARM_DECL. */
- build_mangled_name (TREE_TYPE (parm), 0, 0);
- }
+ /* It's a PARM_DECL. */
+ build_mangled_name_for_type (TREE_TYPE (parm));
}
}
{
/* This parameter is a type. */
OB_PUTC ('Z');
- build_mangled_name (arg, 0, 0);
+ build_mangled_name_for_type (arg);
}
else if (TREE_CODE (parm) == TEMPLATE_DECL)
{
/* This parameter is a template. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
/* Output parameter declaration, argument index and level */
- build_mangled_name (arg, 0, 0);
+ build_mangled_name_for_type (arg);
else
{
/* A TEMPLATE_DECL node, output the parameter declaration
{
parm = tsubst (parm, arglist, NULL_TREE);
/* It's a PARM_DECL. */
- build_mangled_name (TREE_TYPE (parm), 0, 0);
+ build_mangled_name_for_type (TREE_TYPE (parm));
build_overload_value (parm, arg, uses_template_parms (arglist));
}
}
}
+/* Output the representation for NAME, which is either a TYPE_DECL or
+ an IDENTIFIER. */
static void
build_overload_identifier (name)
(TREE_TYPE (name))))
== FUNCTION_DECL)))
{
+ /* NAME is the TYPE_DECL for a template specialization. */
tree template, parmlist, arglist, tname;
template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
- arglist = TREE_VALUE (template);
+ arglist = innermost_args (TREE_VALUE (template), 0);
template = TREE_PURPOSE (template);
tname = DECL_NAME (template);
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
if (TREE_CODE (decl) == TYPE_DECL
&& DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling)
{
- OB_PUTID (DECL_ASSEMBLER_NAME (decl));
+ tree id = DECL_ASSEMBLER_NAME (decl);
+ OB_PUTID (id);
+ if (ISDIGIT (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1]))
+ numeric_output_need_bar = 1;
return;
}
/* if we can't find a Ktype, do it the hard way */
if (check_ktype (context, FALSE) == -1)
{
- /* count type scopes */
- while (DECL_CONTEXT (context))
+ /* count type and namespace scopes */
+ while (DECL_CONTEXT (context) && DECL_CONTEXT (context) != global_namespace)
{
i += 1;
context = DECL_CONTEXT (context);
if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
context = TYPE_NAME (context);
}
- /* now count namespace scopes */
- if (TREE_CODE (decl) == NAMESPACE_DECL)
- {
- i = 0; /* we have nothing done, yet: reset */
- context = decl;
- }
- else
- /* decl must be a type, which we have to scope with the
- namespace */
- {
- /* XXX MvL somehow, types have no lang_decl, so no namespace */
- context = current_namespace;
- }
- }
-
- while (context != global_namespace)
- {
- i += 1;
- context = DECL_NAMESPACE (context);
}
if (i > 1)
{
OB_PUTC ('Q');
- if (i > 9)
- OB_PUTC ('_');
- icat (i);
- if (i > 9)
- OB_PUTC ('_');
+ build_underscore_int (i);
numeric_output_need_bar = 0;
}
build_overload_nested_name (decl);
}
+/* Output the mangled representation for TYPE. If EXTRA_GCODE is
+ non-zero, mangled names for structure/union types are intentionally
+ mangled differently from the method described in the ARM. */
+
+void
+build_mangled_name_for_type_with_Gcode (type, extra_Gcode)
+ tree type;
+ int extra_Gcode;
+{
+ if (TYPE_PTRMEMFUNC_P (type))
+ type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+ type = CANONICAL_TYPE_VARIANT (type);
+ process_modifiers (type);
+ process_overload_item (type, extra_Gcode);
+}
+
+/* Like build_mangled_name_for_type_with_Gcode, but never outputs the
+ `G'. */
+
+void
+build_mangled_name_for_type (type)
+ tree type;
+{
+ build_mangled_name_for_type_with_Gcode (type, 0);
+}
+
/* Given a list of parameters in PARMTYPES, create an unambiguous
overload string. Should distinguish any type that C (or C++) can
distinguish. I.e., pointers to functions are treated correctly.
return ret ;
}
+/* Output the mangled representation for PARMTYPES. If PARMTYPES is a
+ TREE_LIST, then it is a list of parameter types. Otherwise,
+ PARMTYPES must be a single type. */
+
static char *
build_mangled_name (parmtypes, begin, end)
tree parmtypes;
int begin, end;
{
- tree parmtype;
-
if (begin)
OB_INIT ();
- numeric_output_need_bar = 0;
- if (TREE_CODE (parmtypes) != TREE_LIST) /* just one item */
+ if (TREE_CODE (parmtypes) != TREE_LIST)
+ /* There is only one type. */
+ build_mangled_name_for_type (parmtypes);
+ else
{
- if (TYPE_PTRMEMFUNC_P (parmtypes))
- parmtypes = TYPE_PTRMEMFUNC_FN_TYPE (parmtypes);
- process_modifiers (parmtypes);
- process_overload_item (parmtypes, FALSE);
- }
- else {
- for ( ; parmtypes!=NULL; parmtypes = TREE_CHAIN (parmtypes))
- {
- parmtype = TREE_VALUE (parmtypes);
- if (flag_do_squangling) /* squangling style repeats */
- {
- if (parmtype == lasttype)
- {
- nrepeats++;
- continue;
- }
- else
- if (nrepeats != 0)
- {
- issue_nrepeats (lasttype);
- }
- lasttype = parmtype;
- }
- else
- if (!nofold && typevec)
- {
- /* Every argument gets counted. */
- typevec[maxtype++] = parmtype;
+ /* There are several types in a parameter list. */
+ int nrepeats = 0;
+ int old_style_repeats = !flag_do_squangling && !nofold && typevec;
+ tree last_type = NULL_TREE;
- if (TREE_USED (parmtype) && parmtype == typevec[maxtype-2])
- {
- Nrepeats++;
- continue;
- }
+ for (; parmtypes && parmtypes != void_list_node;
+ parmtypes = TREE_CHAIN (parmtypes))
+ {
+ tree parmtype = CANONICAL_TYPE_VARIANT (TREE_VALUE (parmtypes));
- if (Nrepeats)
- flush_repeats (typevec[maxtype-2]);
+ if (old_style_repeats)
+ {
+ /* Every argument gets counted. */
+ my_friendly_assert (maxtype < typevec_size, 387);
+ typevec[maxtype++] = parmtype;
+ }
- if (TREE_USED (parmtype))
- {
+ if (parmtype == last_type)
+ {
+ if (flag_do_squangling
+ || (old_style_repeats && TREE_USED (parmtype)
+ && !TYPE_FOR_JAVA (parmtype)))
+ {
+ /* The next type is the same as this one. Keep
+ track of the repetition, and output the repeat
+ count later. */
+ nrepeats++;
+ continue;
+ }
+ }
+ else if (nrepeats != 0)
+ {
+ /* Indicate how many times the previous parameter was
+ repeated. */
+ if (old_style_repeats)
+ flush_repeats (nrepeats, last_type);
+ else
+ issue_nrepeats (nrepeats, last_type);
+ nrepeats = 0;
+ }
+
+ last_type = parmtype;
+
+ if (old_style_repeats)
+ {
+ if (nrepeats)
+ {
+ flush_repeats (nrepeats, last_type);
+ nrepeats = 0;
+ }
+
+ if (TREE_USED (parmtype))
+ {
#if 0
- /* We can turn this on at some point when we want
- improved symbol mangling. */
- Nrepeats++;
+ /* We can turn this on at some point when we want
+ improved symbol mangling. */
+ nrepeats++;
#else
- /* This is bug compatible with 2.7.x */
- flush_repeats (parmtype);
+ /* This is bug compatible with 2.7.x */
+ flush_repeats (nrepeats, parmtype);
#endif
- continue;
- }
-
- /* Only cache types which take more than one character. */
- if (parmtype != TYPE_MAIN_VARIANT (parmtype)
- || (TREE_CODE (parmtype) != INTEGER_TYPE
- && TREE_CODE (parmtype) != REAL_TYPE))
- TREE_USED (parmtype) = 1;
- }
- if (TYPE_PTRMEMFUNC_P (parmtype))
- parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype);
- process_modifiers (parmtype);
- if (TREE_CODE(parmtype)==VOID_TYPE)
- {
-#if 0
- extern tree void_list_node;
+ nrepeats = 0;
+ continue;
+ }
+
+ /* Only cache types which take more than one character. */
+ if ((parmtype != TYPE_MAIN_VARIANT (parmtype)
+ || (TREE_CODE (parmtype) != INTEGER_TYPE
+ && TREE_CODE (parmtype) != REAL_TYPE))
+ && ! TYPE_FOR_JAVA (parmtype))
+ TREE_USED (parmtype) = 1;
+ }
+
+ /* Output the PARMTYPE. */
+ build_mangled_name_for_type_with_Gcode (parmtype, 1);
+ }
+
+ /* Output the repeat count for the last parameter, if
+ necessary. */
+ if (nrepeats != 0)
+ {
+ if (old_style_repeats)
+ flush_repeats (nrepeats, last_type);
+ else
+ issue_nrepeats (nrepeats, last_type);
+ nrepeats = 0;
+ }
+
+ if (!parmtypes)
+ /* The parameter list ends in an ellipsis. */
+ OB_PUTC ('e');
+ }
- /* See if anybody is wasting memory. */
- my_friendly_assert (parmtypes == void_list_node, 247);
-#endif
- /* This is the end of a parameter list. */
- if (end)
- OB_FINISH ();
- return (char *)obstack_base (&scratch_obstack);
- }
- process_overload_item (parmtype, TRUE);
- }
- if (flag_do_squangling && nrepeats != 0)
- issue_nrepeats (lasttype);
- else
- if (Nrepeats && typevec)
- flush_repeats (typevec[maxtype-1]);
-
- /* To get here, parms must end with `...'. */
- OB_PUTC ('e');
- }
if (end)
OB_FINISH ();
return (char *)obstack_base (&scratch_obstack);
process_modifiers (parmtype)
tree parmtype;
{
-
-
if (TREE_READONLY (parmtype))
OB_PUTC ('C');
- if (TREE_CODE (parmtype) == INTEGER_TYPE &&
- TYPE_MAIN_VARIANT (parmtype) ==
- unsigned_type (TYPE_MAIN_VARIANT (parmtype)))
+ if (TREE_CODE (parmtype) == INTEGER_TYPE
+ && (TYPE_MAIN_VARIANT (parmtype)
+ == unsigned_type (TYPE_MAIN_VARIANT (parmtype)))
+ && ! TYPE_FOR_JAVA (parmtype))
OB_PUTC ('U');
if (TYPE_VOLATILE (parmtype))
OB_PUTC ('V');
}
-/* Check to see if a tree node has been entered into the Bcode typelist
- if not, add it. Otherwise emit the code and return TRUE */
-static int
-check_btype (node)
- tree node;
+/* Check to see if TYPE has been entered into the Bcode typelist. If
+ so, return 1 and emit a backreference to TYPE. Otherwise, add TYPE
+ to the list of back-referenceable types and return 0. */
+
+int
+check_btype (type)
+ tree type;
{
int x;
if (btypelist == NULL)
return 0;
- switch (TREE_CODE (node))
- {
- case INTEGER_TYPE:
- case REAL_TYPE:
- case VOID_TYPE:
- case BOOLEAN_TYPE:
- return 0; /* don't compress single char basic types */
- }
+ if (!is_back_referenceable_type (type))
+ return 0;
+
+ /* We assume that our caller has put out any necessary
+ qualifiers. */
+ type = TYPE_MAIN_VARIANT (type);
- node = TYPE_MAIN_VARIANT (node);
for (x = 0; x < maxbtype; x++)
- {
- if (node == btypelist[x])
- {
- OB_PUTC ('B');
- icat (x);
- if (x > 9)
- OB_PUTC ('_');
- return 1 ;
- }
- }
- /* didn't find it, so add it here */
+ if (type == btypelist[x])
+ {
+ OB_PUTC ('B');
+ icat (x);
+ if (x > 9)
+ OB_PUTC ('_');
+ return 1 ;
+ }
+
if (maxbsize <= maxbtype)
{
+ /* Enlarge the table. */
maxbsize = maxbsize * 3 / 2;
- btypelist = (tree *)xrealloc (sizeof (tree) * maxbsize);
+ btypelist = (tree *)xrealloc (btypelist, sizeof (tree) * maxbsize);
}
- btypelist[maxbtype++] = node;
+
+ /* Register the TYPE. */
+ btypelist[maxbtype++] = type;
+
return 0;
}
tree parmtype;
int extra_Gcode;
{
+ numeric_output_need_bar = 0;
/* These tree types are considered modifiers for B code squangling , */
/* and therefore should not get entries in the Btypelist */
case POINTER_TYPE:
OB_PUTC ('P');
more:
- build_mangled_name (TREE_TYPE (parmtype), 0, 0);
+ build_mangled_name_for_type (TREE_TYPE (parmtype));
return;
break;
+
+ default:
+ break;
}
- /* check if type is already in the typelist. If not, add it now */
-
- if (flag_do_squangling && btypelist != NULL) {
- if (check_btype (parmtype)) /* emits the code if it finds it */
- return;
- }
+ if (flag_do_squangling && check_btype (parmtype))
+ /* If PARMTYPE is already in the list of back-referenceable types,
+ then check_btype will output the appropriate reference, and
+ there's nothing more to do. */
+ return;
switch (TREE_CODE (parmtype))
{
case OFFSET_TYPE:
OB_PUTC ('O');
- build_mangled_name (TYPE_OFFSET_BASETYPE (parmtype), 0, 0);
+ build_mangled_name_for_type (TYPE_OFFSET_BASETYPE (parmtype));
OB_PUTC ('_');
- build_mangled_name (TREE_TYPE (parmtype), 0, 0);
+ build_mangled_name_for_type (TREE_TYPE (parmtype));
break;
case FUNCTION_TYPE:
case METHOD_TYPE:
{
- tree firstarg = TYPE_ARG_TYPES (parmtype);
- /* Otherwise have to implement reentrant typevecs,
- unmark and remark types, etc. */
- int old_nofold = nofold;
- if (!flag_do_squangling) {
- nofold = 1;
- if (Nrepeats)
- flush_repeats (typevec[maxtype-1]);
- }
- else
- if (nrepeats != 0)
- issue_nrepeats (lasttype);
+ tree parms = TYPE_ARG_TYPES (parmtype);
- /* @@ It may be possible to pass a function type in
- which is not preceded by a 'P'. */
- if (TREE_CODE (parmtype) == FUNCTION_TYPE)
- {
- OB_PUTC ('F');
- if (firstarg == NULL_TREE)
- OB_PUTC ('e');
- else if (firstarg == void_list_node)
- OB_PUTC ('v');
- else
- build_mangled_name (firstarg, 0, 0);
- }
- else
- {
- int constp = TYPE_READONLY (TREE_TYPE (TREE_VALUE (firstarg)));
- int volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (firstarg)));
+ /* Rather than implementing a reentrant TYPEVEC, we turn off
+ repeat codes here, unless we're squangling. Squangling
+ doesn't make use of the TYPEVEC, so there's no reentrancy
+ problem. */
+ int old_nofold = nofold;
+ if (!flag_do_squangling)
+ nofold = 1;
+
+ if (TREE_CODE (parmtype) == METHOD_TYPE)
+ {
+ /* Mark this as a method. */
OB_PUTC ('M');
- firstarg = TREE_CHAIN (firstarg);
-
- build_mangled_name (TYPE_METHOD_BASETYPE (parmtype), 0, 0);
- if (constp)
- OB_PUTC ('C');
- if (volatilep)
- OB_PUTC ('V');
-
- /* For cfront 2.0 compatibility. */
- OB_PUTC ('F');
-
- if (firstarg == NULL_TREE)
- OB_PUTC ('e');
- else if (firstarg == void_list_node)
- OB_PUTC ('v');
- else
- build_mangled_name (firstarg, 0, 0);
- }
+ /* Output the class of which this method is a member. */
+ build_mangled_name_for_type (TYPE_METHOD_BASETYPE (parmtype));
+ /* Output any qualifiers for the `this' parameter. */
+ process_modifiers (TREE_TYPE (TREE_VALUE (parms)));
+ }
- /* Separate args from return type. */
+ /* Output the parameter types. */
+ OB_PUTC ('F');
+ if (parms == NULL_TREE)
+ OB_PUTC ('e');
+ else if (parms == void_list_node)
+ OB_PUTC ('v');
+ else
+ build_mangled_name (parms, 0, 0);
+
+ /* Output the return type. */
OB_PUTC ('_');
- build_mangled_name (TREE_TYPE (parmtype), 0, 0);
+ build_mangled_name_for_type (TREE_TYPE (parmtype));
+
nofold = old_nofold;
break;
}
case INTEGER_TYPE:
parmtype = TYPE_MAIN_VARIANT (parmtype);
if (parmtype == integer_type_node
- || parmtype == unsigned_type_node)
+ || parmtype == unsigned_type_node
+ || parmtype == java_int_type_node)
OB_PUTC ('i');
else if (parmtype == long_integer_type_node
|| parmtype == long_unsigned_type_node)
OB_PUTC ('l');
else if (parmtype == short_integer_type_node
- || parmtype == short_unsigned_type_node)
+ || parmtype == short_unsigned_type_node
+ || parmtype == java_short_type_node)
OB_PUTC ('s');
else if (parmtype == signed_char_type_node)
{
OB_PUTC ('c');
}
else if (parmtype == char_type_node
- || parmtype == unsigned_char_type_node)
+ || parmtype == unsigned_char_type_node
+ || parmtype == java_byte_type_node)
OB_PUTC ('c');
- else if (parmtype == wchar_type_node)
+ else if (parmtype == wchar_type_node
+ || parmtype == java_char_type_node)
OB_PUTC ('w');
else if (parmtype == long_long_integer_type_node
- || parmtype == long_long_unsigned_type_node)
+ || parmtype == long_long_unsigned_type_node
+ || parmtype == java_long_type_node)
OB_PUTC ('x');
#if 0
/* it would seem there is no way to enter these in source code,
|| parmtype == long_long_long_unsigned_type_node)
OB_PUTC ('q');
#endif
+ else if (parmtype == java_boolean_type_node)
+ OB_PUTC ('b');
else
my_friendly_abort (73);
break;
parmtype = TYPE_MAIN_VARIANT (parmtype);
if (parmtype == long_double_type_node)
OB_PUTC ('r');
- else if (parmtype == double_type_node)
+ else if (parmtype == double_type_node
+ || parmtype == java_double_type_node)
OB_PUTC ('d');
- else if (parmtype == float_type_node)
+ else if (parmtype == float_type_node
+ || parmtype == java_float_type_node)
OB_PUTC ('f');
else my_friendly_abort (74);
break;
case COMPLEX_TYPE:
OB_PUTC ('J');
- build_mangled_name (TREE_TYPE (parmtype), 0, 0);
+ build_mangled_name_for_type (TREE_TYPE (parmtype));
break;
case VOID_TYPE:
and figure out its name without any extra encoding. */
OB_PUTC2 ('_', '_');
- if (for_method)
- {
-#if 0
- /* We can get away without doing this. */
- OB_PUTC ('M');
-#endif
- if (tparms != NULL_TREE)
- OB_PUTC ('H');
- {
- tree this_type = TREE_VALUE (parms);
-
- if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */
- parms = temp_tree_cons (NULL_TREE, SIGNATURE_TYPE (this_type),
- TREE_CHAIN (parms));
- else
- parms = temp_tree_cons (NULL_TREE, TREE_TYPE (this_type),
- TREE_CHAIN (parms));
- }
- }
- else if (tparms)
- OB_PUTC ('H');
- /* 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 (current_namespace == global_namespace)
- OB_PUTC ('F');
if (tparms)
{
+ OB_PUTC ('H');
build_template_parm_names (tparms, targs);
OB_PUTC ('_');
}
-
- /* qualify with namespace */
- if (!for_method && current_namespace != global_namespace)
+ 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 */
+ OB_PUTC ('F');
+ else if (!for_method)
+ /* qualify with namespace */
build_qualified_name (current_namespace);
if (parms == NULL_TREE)
if (!flag_do_squangling) /* Allocate typevec array. */
{
maxtype = 0;
- Nrepeats = 0;
- typevec = (tree *)alloca (list_length (parms) * sizeof (tree));
+ typevec_size = list_length (parms);
+ if (!for_method && current_namespace != global_namespace)
+ /* the namespace of a global function needs one slot */
+ typevec_size++;
+ typevec = (tree *)alloca (typevec_size * sizeof (tree));
}
nofold = 0;
+
if (for_method)
{
- build_mangled_name (TREE_VALUE (parms), 0, 0);
+ tree this_type = TREE_VALUE (parms);
- if (!flag_do_squangling) {
- typevec[maxtype++] = TREE_VALUE (parms);
- TREE_USED (TREE_VALUE (parms)) = 1;
- }
+ if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */
+ this_type = SIGNATURE_TYPE (this_type);
+ else
+ this_type = TREE_TYPE (this_type);
+
+ build_mangled_name_for_type (this_type);
+
+ if (!flag_do_squangling)
+ {
+ my_friendly_assert (maxtype < typevec_size, 387);
+ typevec[maxtype++] = this_type;
+ TREE_USED (this_type) = 1;
+
+ /* By setting up PARMS in this way, the loop below will
+ automatically clear TREE_USED on THIS_TYPE. */
+ parms = temp_tree_cons (NULL_TREE, this_type,
+ TREE_CHAIN (parms));
+ }
if (TREE_CHAIN (parms))
build_mangled_name (TREE_CHAIN (parms), 0, 0);
will count as type */
if (current_namespace != global_namespace
&& !flag_do_squangling)
- typevec[maxtype++] = current_namespace;
+ {
+ my_friendly_assert (maxtype < typevec_size, 387);
+ typevec[maxtype++] = current_namespace;
+ }
build_mangled_name (parms, 0, 0);
}
typevec = NULL;
while (t)
{
- TREE_USED (TREE_VALUE (t)) = 0;
+ tree temp = TREE_VALUE (t);
+ TREE_USED (temp) = 0;
+ /* clear out the type variant in case we used it */
+ temp = CANONICAL_TYPE_VARIANT (temp);
+ TREE_USED (temp) = 0;
t = TREE_CHAIN (t);
}
}
{
/* Add the return type. */
OB_PUTC ('_');
- build_mangled_name (ret_type, 0, 0);
+ build_mangled_name_for_type (ret_type);
}
OB_FINISH ();
/* Like build_decl_overload, but for template functions. */
tree
-build_template_decl_overload (dname, parms, ret_type, tparms, targs,
+build_template_decl_overload (decl, parms, ret_type, tparms, targs,
for_method)
- tree dname;
+ tree decl;
tree parms;
tree ret_type;
tree tparms;
tree targs;
int for_method;
{
- return build_decl_overload_real (dname, parms, ret_type, tparms, targs,
- for_method);
+ tree res, saved_ctx;
+
+ /* 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 (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702);
+ saved_ctx = current_namespace;
+ current_namespace = CP_DECL_CONTEXT (decl);
+
+ res = build_decl_overload_real (DECL_NAME (decl), parms, ret_type,
+ tparms, targs, for_method);
+
+ current_namespace = saved_ctx;
+ return res;
}
OB_FINISH ();
return get_identifier (obstack_base (&scratch_obstack));
}
+
+/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */
+
+tree
+build_destructor_name (type)
+ tree type;
+{
+ return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX),
+ type);
+}
\f
/* Given a tree_code CODE, and some arguments (at least one),
attempt to use an overloaded operator on the arguments.
fndecl = TREE_VALUE (fields);
my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251);
+ /* I could not trigger this code. MvL */
+ my_friendly_abort (980325);
+#ifdef DEAD
if (DECL_CHAIN (fndecl) == NULL_TREE)
{
warning ("methods cannot be converted to function pointers");
IDENTIFIER_POINTER (name));
return error_mark_node;
}
+#endif
}
}
if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name))
}
#endif
}
+ else if (TREE_CODE (value) == OVERLOAD)
+ /* not really overloaded function */
+ mark_used (OVL_FUNCTION (value));
else if (TREE_CODE (value) == TREE_LIST)
{
/* Ambiguous reference to base members, possibly other cases?. */
t = TREE_CHAIN (t);
}
}
+ else if (TREE_CODE (value) == NAMESPACE_DECL)
+ {
+ cp_error ("use of namespace `%D' as expression", value);
+ return error_mark_node;
+ }
+ else if (DECL_CLASS_TEMPLATE_P (value))
+ {
+ cp_error ("use of class template `%T' as expression", value);
+ return error_mark_node;
+ }
else
mark_used (value);
}
\f
-static char *
-thunk_printable_name (decl)
- tree decl;
-{
- return "<thunk function>";
-}
-
tree
make_thunk (function, delta)
tree function;
int delta;
{
- char *buffer;
tree thunk_id;
tree thunk;
- char *func_name;
tree func_decl;
+
if (TREE_CODE (function) != ADDR_EXPR)
abort ();
func_decl = TREE_OPERAND (function, 0);
if (TREE_CODE (func_decl) != FUNCTION_DECL)
abort ();
- func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl));
- buffer = (char *)alloca (strlen (func_name) + 32);
- if (delta<=0)
- sprintf (buffer, "__thunk_%d_%s", -delta, func_name);
+
+ OB_INIT ();
+ OB_PUTS ("__thunk_");
+ if (delta > 0)
+ {
+ OB_PUTC ('n');
+ icat (delta);
+ }
else
- sprintf (buffer, "__thunk_n%d_%s", delta, func_name);
- thunk_id = get_identifier (buffer);
+ icat (-delta);
+ OB_PUTC ('_');
+ OB_PUTID (DECL_ASSEMBLER_NAME (func_decl));
+ OB_FINISH ();
+ thunk_id = get_identifier (obstack_base (&scratch_obstack));
+
thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
if (thunk && TREE_CODE (thunk) != THUNK_DECL)
{
cp_error ("implementation-reserved name `%D' used", thunk_id);
- IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE;
+ thunk = NULL_TREE;
+ SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
}
if (thunk == NULL_TREE)
{
= build_decl (RESULT_DECL, 0, integer_type_node);
fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
init_function_start (thunk_fndecl, input_filename, lineno);
+ current_function_is_thunk = 1;
assemble_start_function (thunk_fndecl, fnname);
ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
assemble_end_function (thunk_fndecl, fnname);
parm = TREE_CHAIN (parm);
parm = convert_from_reference (parm);
- if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
+ if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
+ && is_empty_class (current_class_type))
+ /* Don't copy the padding byte; it might not have been allocated
+ if *this is a base subobject. */;
+ else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
{
t = build (INIT_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1;
continue;
}
else if ((t = TREE_TYPE (field)) != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+ && ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE)
{
do
field = largest_union_member (t);
}
while ((t = TREE_TYPE (field)) != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+ && ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE);
}
else
parm = convert_from_reference (parm);
- if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
+ if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
+ && is_empty_class (current_class_type))
+ /* Don't copy the padding byte; it might not have been allocated
+ if *this is a base subobject. */;
+ else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
{
tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1;
continue;
}
else if ((t = TREE_TYPE (field)) != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+ && ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE)
{
do
field = largest_union_member (t);
}
while ((t = TREE_TYPE (field)) != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+ && ANON_UNION_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE);
}
else