summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cc/cc1plus/method.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cc/cc1plus/method.c')
-rw-r--r--gnu/usr.bin/cc/cc1plus/method.c2171
1 files changed, 0 insertions, 2171 deletions
diff --git a/gnu/usr.bin/cc/cc1plus/method.c b/gnu/usr.bin/cc/cc1plus/method.c
deleted file mode 100644
index e7fbdad..0000000
--- a/gnu/usr.bin/cc/cc1plus/method.c
+++ /dev/null
@@ -1,2171 +0,0 @@
-/* Handle the hair of processing (but not expanding) inline functions.
- Also manage function and variable name overloading.
- Copyright (C) 1987, 1989, 1992, 1993 Free Software Foundation, Inc.
- Contributed by Michael Tiemann (tiemann@cygnus.com)
-
- 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
-#ifndef PARM_CAN_BE_ARRAY_TYPE
-#define PARM_CAN_BE_ARRAY_TYPE 1
-#endif
-
-/* Handle method declarations. */
-#include <stdio.h>
-#include "config.h"
-#include "tree.h"
-#include "cp-tree.h"
-#include "class.h"
-#include "obstack.h"
-#include <ctype.h>
-#include "rtl.h"
-#include "expr.h"
-#include "output.h"
-#include "hard-reg-set.h"
-#include "flags.h"
-
-/* TREE_LIST of the current inline functions that need to be
- processed. */
-struct pending_inline *pending_inlines;
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-/* Obstack where we build text strings for overloading, etc. */
-static struct obstack scratch_obstack;
-static char *scratch_firstobj;
-
-# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
-# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
-# define OB_PUTC2(C1,C2) \
- (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2)))
-# define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1))
-# define OB_PUTID(ID) \
- (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \
- IDENTIFIER_LENGTH (ID)))
-# define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))
-# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
-
-#ifdef NO_AUTO_OVERLOAD
-int is_overloaded ();
-#endif
-
-void
-init_method ()
-{
- gcc_obstack_init (&scratch_obstack);
- scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
-}
-
-/* This must be large enough to hold any printed integer or floating-point
- value. */
-static char digit_buffer[128];
-
-/* Move inline function definitions out of structure so that they
- can be processed normally. CNAME is the name of the class
- we are working from, METHOD_LIST is the list of method lists
- of the structure. We delete friend methods here, after
- saving away their inline function definitions (if any). */
-
-void
-do_inline_function_hair (type, friend_list)
- tree type, friend_list;
-{
- tree method = TYPE_METHODS (type);
-
- if (method && TREE_CODE (method) == TREE_VEC)
- {
- if (TREE_VEC_ELT (method, 0))
- method = TREE_VEC_ELT (method, 0);
- else
- method = TREE_VEC_ELT (method, 1);
- }
-
- while (method)
- {
- /* Do inline member functions. */
- struct pending_inline *info = DECL_PENDING_INLINE_INFO (method);
- if (info)
- {
- tree args;
-
- my_friendly_assert (info->fndecl == method, 238);
- args = DECL_ARGUMENTS (method);
- while (args)
- {
- DECL_CONTEXT (args) = method;
- args = TREE_CHAIN (args);
- }
-
- /* Allow this decl to be seen in global scope. Don't do this for
- local class methods, though. */
- if (! current_function_decl)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method;
- }
- method = TREE_CHAIN (method);
- }
- while (friend_list)
- {
- tree fndecl = TREE_VALUE (friend_list);
- struct pending_inline *info = DECL_PENDING_INLINE_INFO (fndecl);
- if (info)
- {
- tree args;
-
- my_friendly_assert (info->fndecl == fndecl, 239);
- args = DECL_ARGUMENTS (fndecl);
- while (args)
- {
- DECL_CONTEXT (args) = fndecl;
- args = TREE_CHAIN (args);
- }
-
- /* Allow this decl to be seen in global scope */
- if (! current_function_decl)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (fndecl)) = fndecl;
- }
-
- friend_list = TREE_CHAIN (friend_list);
- }
-}
-
-/* Report an argument type mismatch between the best declared function
- we could find and the current argument list that we have. */
-void
-report_type_mismatch (cp, parmtypes, name_kind)
- struct candidate *cp;
- tree parmtypes;
- char *name_kind;
-{
- int i = cp->u.bad_arg;
- tree ttf, tta;
- char *tmp_firstobj;
-
- switch (i)
- {
- case -4:
- my_friendly_assert (TREE_CODE (cp->function) == TEMPLATE_DECL, 240);
- cp_error ("type unification failed for function template `%#D'",
- cp->function);
- return;
-
- case -3:
- if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))))
- cp_error ("call to const %s `%#D' with non-const object", name_kind,
- cp->function);
- else
- cp_error ("call to non-const %s `%#D' with const object", name_kind,
- cp->function);
- return;
- case -2:
- cp_error ("too few arguments for %s `%#D'", name_kind, cp->function);
- return;
- case -1:
- cp_error ("too many arguments for %s `%#D'", name_kind, cp->function);
- return;
- case 0:
- if (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
- {
- /* Happens when we have an ambiguous base class. */
- my_friendly_assert (get_binfo (DECL_CLASS_CONTEXT (cp->function),
- TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes))), 1) == error_mark_node,
- 241);
- return;
- }
- }
-
- ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function));
- tta = parmtypes;
-
- while (i-- > 0)
- {
- ttf = TREE_CHAIN (ttf);
- tta = TREE_CHAIN (tta);
- }
-
- OB_INIT ();
- OB_PUTS ("bad argument ");
- sprintf (digit_buffer, "%d", cp->u.bad_arg
- - (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
- + 1);
- OB_PUTCP (digit_buffer);
-
- OB_PUTS (" for function `");
- OB_PUTCP (decl_as_string (cp->function, 1));
- OB_PUTS ("' (type was ");
-
- /* Reset `i' so that type printing routines do the right thing. */
- if (tta)
- {
- enum tree_code code = TREE_CODE (TREE_TYPE (TREE_VALUE (tta)));
- if (code == ERROR_MARK)
- OB_PUTS ("(failed type instantiation)");
- else
- {
- i = (code == FUNCTION_TYPE || code == METHOD_TYPE);
- OB_PUTCP (type_as_string (TREE_TYPE (TREE_VALUE (tta)), 1));
- }
- }
- else OB_PUTS ("void");
- OB_PUTC (')');
- OB_FINISH ();
-
- tmp_firstobj = (char *)alloca (obstack_object_size (&scratch_obstack));
- bcopy (obstack_base (&scratch_obstack), tmp_firstobj,
- obstack_object_size (&scratch_obstack));
- error (tmp_firstobj);
-}
-
-/* Here is where overload code starts. */
-
-/* Array of types seen so far in top-level call to `build_overload_name'.
- Allocated and deallocated by caller. */
-static tree *typevec;
-
-/* Number of types interned by `build_overload_name' so far. */
-static int maxtype;
-
-/* Number of occurrences of last type seen. */
-static int nrepeats;
-
-/* Nonzero if we should not try folding parameter types. */
-static int nofold;
-
-#define ALLOCATE_TYPEVEC(PARMTYPES) \
- do { maxtype = 0, nrepeats = 0; \
- typevec = (tree *)alloca (list_length (PARMTYPES) * sizeof (tree)); } while (0)
-
-#define DEALLOCATE_TYPEVEC(PARMTYPES) \
- do { tree t = (PARMTYPES); \
- while (t) { TREE_USED (TREE_VALUE (t)) = 0; t = TREE_CHAIN (t); } \
- } while (0)
-
-/* Code to concatenate an asciified integer to a string. */
-static
-#ifdef __GNUC__
-__inline
-#endif
-void
-icat (i)
- int i;
-{
- /* Handle this case first, to go really quickly. For many common values,
- the result of i/10 below is 1. */
- if (i == 1)
- {
- OB_PUTC ('1');
- return;
- }
-
- if (i < 0)
- {
- OB_PUTC ('m');
- i = -i;
- }
- if (i < 10)
- OB_PUTC ('0' + i);
- else
- {
- icat (i / 10);
- OB_PUTC ('0' + (i % 10));
- }
-}
-
-static
-#ifdef __GNUC__
-__inline
-#endif
-void
-flush_repeats (type)
- tree type;
-{
- int tindex = 0;
-
- while (typevec[tindex] != type)
- tindex++;
-
- if (nrepeats > 1)
- {
- OB_PUTC ('N');
- icat (nrepeats);
- if (nrepeats > 9)
- OB_PUTC ('_');
- }
- else
- OB_PUTC ('T');
- nrepeats = 0;
- icat (tindex);
- if (tindex > 9)
- OB_PUTC ('_');
-}
-
-static int numeric_outputed_need_bar;
-static void build_overload_identifier ();
-
-static void
-build_overload_nested_name (context)
- tree context;
-{
- /* We use DECL_NAME here, because pushtag now sets the DECL_ASSEMBLER_NAME. */
- tree name = DECL_NAME (context);
- if (DECL_CONTEXT (context))
- {
- context = DECL_CONTEXT (context);
- if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
- context = TYPE_NAME (context);
- build_overload_nested_name (context);
- }
- build_overload_identifier (name);
-}
-
-static void
-build_overload_value (type, value)
- tree type, value;
-{
- 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);
- switch (TREE_CODE (type))
- {
- case INTEGER_TYPE:
- case ENUMERAL_TYPE:
- {
- my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243);
- if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT)
- {
- if (tree_int_cst_lt (value, integer_zero_node))
- {
- OB_PUTC ('m');
- value = build_int_2 (~ TREE_INT_CST_LOW (value),
- - TREE_INT_CST_HIGH (value));
- }
- if (TREE_INT_CST_HIGH (value)
- != (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1)))
- {
- /* need to print a DImode value in decimal */
- sorry ("conversion of long long as PT parameter");
- }
- /* else fall through to print in smaller mode */
- }
- /* Wordsize or smaller */
- icat (TREE_INT_CST_LOW (value));
- return;
- }
- case BOOLEAN_TYPE:
- {
- icat (TREE_INT_CST_LOW (value));
- return;
- }
-#ifndef REAL_IS_NOT_DOUBLE
- case REAL_TYPE:
- {
- REAL_VALUE_TYPE val;
- char *bufp = digit_buffer;
- extern char *index ();
-
- my_friendly_assert (TREE_CODE (value) == REAL_CST, 244);
- val = TREE_REAL_CST (value);
- if (val < 0)
- {
- val = -val;
- *bufp++ = 'm';
- }
- sprintf (bufp, "%e", val);
- bufp = (char *) index (bufp, 'e');
- if (!bufp)
- strcat (digit_buffer, "e0");
- else
- {
- char *p;
- bufp++;
- if (*bufp == '-')
- {
- *bufp++ = 'm';
- }
- p = bufp;
- if (*p == '+')
- p++;
- while (*p == '0')
- p++;
- if (*p == 0)
- {
- *bufp++ = '0';
- *bufp = 0;
- }
- else if (p != bufp)
- {
- while (*p)
- *bufp++ = *p++;
- *bufp = 0;
- }
- }
- OB_PUTCP (digit_buffer);
- return;
- }
-#endif
- case POINTER_TYPE:
- value = TREE_OPERAND (value, 0);
- if (TREE_CODE (value) == VAR_DECL)
- {
- my_friendly_assert (DECL_NAME (value) != 0, 245);
- build_overload_identifier (DECL_NAME (value));
- return;
- }
- else if (TREE_CODE (value) == FUNCTION_DECL)
- {
- my_friendly_assert (DECL_NAME (value) != 0, 246);
- build_overload_identifier (DECL_NAME (value));
- return;
- }
- else
- my_friendly_abort (71);
- break; /* not really needed */
-
- default:
- sorry ("conversion of %s as template parameter",
- tree_code_name [(int) TREE_CODE (type)]);
- my_friendly_abort (72);
- }
-}
-
-static void
-build_overload_identifier (name)
- tree name;
-{
- if (IDENTIFIER_TEMPLATE (name))
- {
- tree template, parmlist, arglist, tname;
- int i, nparms;
- template = IDENTIFIER_TEMPLATE (name);
- arglist = TREE_VALUE (template);
- template = TREE_PURPOSE (template);
- tname = DECL_NAME (template);
- parmlist = DECL_ARGUMENTS (template);
- nparms = TREE_VEC_LENGTH (parmlist);
- OB_PUTC ('t');
- icat (IDENTIFIER_LENGTH (tname));
- OB_PUTID (tname);
- icat (nparms);
- for (i = 0; i < nparms; i++)
- {
- tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
- tree arg = TREE_VEC_ELT (arglist, i);
- if (TREE_CODE (parm) == TYPE_DECL)
- {
- /* This parameter is a type. */
- OB_PUTC ('Z');
- build_overload_name (arg, 0, 0);
- }
- else
- {
- /* It's a PARM_DECL. */
- build_overload_name (TREE_TYPE (parm), 0, 0);
- build_overload_value (parm, arg);
- numeric_outputed_need_bar = 1;
- }
- }
- }
- else
- {
- if (numeric_outputed_need_bar)
- {
- OB_PUTC ('_');
- numeric_outputed_need_bar = 0;
- }
- icat (IDENTIFIER_LENGTH (name));
- OB_PUTID (name);
- }
-}
-
-/* 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.
-
- Caller must deal with whether a final `e' goes on the end or not.
-
- Any default conversions must take place before this function
- is called.
-
- BEGIN and END control initialization and finalization of the
- obstack where we build the string. */
-
-char *
-build_overload_name (parmtypes, begin, end)
- tree parmtypes;
- int begin, end;
-{
- int just_one;
- tree parmtype;
-
- if (begin) OB_INIT ();
- numeric_outputed_need_bar = 0;
-
- if ((just_one = (TREE_CODE (parmtypes) != TREE_LIST)))
- {
- parmtype = parmtypes;
- goto only_one;
- }
-
- while (parmtypes)
- {
- parmtype = TREE_VALUE (parmtypes);
-
- only_one:
-
- if (! nofold)
- {
- if (! just_one)
- /* Every argument gets counted. */
- typevec[maxtype++] = parmtype;
-
- if (TREE_USED (parmtype))
- {
- if (! just_one && parmtype == typevec[maxtype-2])
- nrepeats++;
- else
- {
- if (nrepeats)
- flush_repeats (parmtype);
- if (! just_one && TREE_CHAIN (parmtypes)
- && parmtype == TREE_VALUE (TREE_CHAIN (parmtypes)))
- nrepeats++;
- else
- {
- int tindex = 0;
-
- while (typevec[tindex] != parmtype)
- tindex++;
- OB_PUTC ('T');
- icat (tindex);
- if (tindex > 9)
- OB_PUTC ('_');
- }
- }
- goto next;
- }
- if (nrepeats)
- flush_repeats (typevec[maxtype-2]);
- if (! just_one
- /* Only cache types which take more than one character. */
- && (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);
-
- if (TREE_READONLY (parmtype))
- OB_PUTC ('C');
- if (TREE_CODE (parmtype) == INTEGER_TYPE
- && TYPE_MAIN_VARIANT (parmtype) == unsigned_type (TYPE_MAIN_VARIANT (parmtype)))
- OB_PUTC ('U');
- if (TYPE_VOLATILE (parmtype))
- OB_PUTC ('V');
-
- switch (TREE_CODE (parmtype))
- {
- case OFFSET_TYPE:
- OB_PUTC ('O');
- build_overload_name (TYPE_OFFSET_BASETYPE (parmtype), 0, 0);
- OB_PUTC ('_');
- build_overload_name (TREE_TYPE (parmtype), 0, 0);
- break;
-
- case REFERENCE_TYPE:
- OB_PUTC ('R');
- goto more;
-
- case ARRAY_TYPE:
-#if PARM_CAN_BE_ARRAY_TYPE
- {
- tree length;
-
- OB_PUTC ('A');
- if (TYPE_DOMAIN (parmtype) == NULL_TREE)
- error ("pointer or reference to array of unknown bound in parm type");
- else
- {
- length = array_type_nelts (parmtype);
- if (TREE_CODE (length) == INTEGER_CST)
- icat (TREE_INT_CST_LOW (length) + 1);
- }
- OB_PUTC ('_');
- goto more;
- }
-#else
- OB_PUTC ('P');
- goto more;
-#endif
-
- case POINTER_TYPE:
- OB_PUTC ('P');
- more:
- build_overload_name (TREE_TYPE (parmtype), 0, 0);
- 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;
- nofold = 1;
-
- if (nrepeats)
- flush_repeats (typevec[maxtype-1]);
-
- /* @@ 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_overload_name (firstarg, 0, 0);
- }
- else
- {
- int constp = TYPE_READONLY (TREE_TYPE (TREE_VALUE (firstarg)));
- int volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (firstarg)));
- OB_PUTC ('M');
- firstarg = TREE_CHAIN (firstarg);
-
- build_overload_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_overload_name (firstarg, 0, 0);
- }
-
- /* Separate args from return type. */
- OB_PUTC ('_');
- build_overload_name (TREE_TYPE (parmtype), 0, 0);
- nofold = old_nofold;
- break;
- }
-
- case INTEGER_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
- if (parmtype == integer_type_node
- || parmtype == unsigned_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)
- OB_PUTC ('s');
- else if (parmtype == signed_char_type_node)
- {
- OB_PUTC ('S');
- OB_PUTC ('c');
- }
- else if (parmtype == char_type_node
- || parmtype == unsigned_char_type_node)
- OB_PUTC ('c');
- else if (parmtype == wchar_type_node)
- OB_PUTC ('w');
- else if (parmtype == long_long_integer_type_node
- || parmtype == long_long_unsigned_type_node)
- OB_PUTC ('x');
-#if 0
- /* it would seem there is no way to enter these in source code,
- yet. (mrs) */
- else if (parmtype == long_long_long_integer_type_node
- || parmtype == long_long_long_unsigned_type_node)
- OB_PUTC ('q');
-#endif
- else
- my_friendly_abort (73);
- break;
-
- case BOOLEAN_TYPE:
- OB_PUTC ('b');
- break;
-
- case REAL_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
- if (parmtype == long_double_type_node)
- OB_PUTC ('r');
- else if (parmtype == double_type_node)
- OB_PUTC ('d');
- else if (parmtype == float_type_node)
- OB_PUTC ('f');
- else my_friendly_abort (74);
- break;
-
- case VOID_TYPE:
- if (! just_one)
- {
-#if 0
- extern tree void_list_node;
-
- /* 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);
- }
- OB_PUTC ('v');
- break;
-
- case ERROR_MARK: /* not right, but nothing is anyway */
- break;
-
- /* have to do these */
- case UNION_TYPE:
- case RECORD_TYPE:
- if (! just_one)
- /* Make this type signature look incompatible
- with AT&T. */
- OB_PUTC ('G');
- goto common;
- case ENUMERAL_TYPE:
- common:
- {
- tree name = TYPE_NAME (parmtype);
- int i = 1;
-
- if (TREE_CODE (name) == TYPE_DECL)
- {
- tree context = name;
- while (DECL_CONTEXT (context))
- {
- i += 1;
- context = DECL_CONTEXT (context);
- if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
- context = TYPE_NAME (context);
- }
- name = DECL_NAME (name);
- }
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 248);
- if (i > 1)
- {
- OB_PUTC ('Q');
- if (i > 9)
- OB_PUTC ('_');
- icat (i);
- if (i > 9)
- OB_PUTC ('_');
- numeric_outputed_need_bar = 0;
- build_overload_nested_name (TYPE_NAME (parmtype));
- }
- else
- build_overload_identifier (name);
- break;
- }
-
- case UNKNOWN_TYPE:
- /* This will take some work. */
- OB_PUTC ('?');
- break;
-
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_CONST_PARM:
- case UNINSTANTIATED_P_TYPE:
- /* 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);
- }
- break;
-
- default:
- my_friendly_abort (75);
- }
-
- next:
- if (just_one) break;
- parmtypes = TREE_CHAIN (parmtypes);
- }
- if (! just_one)
- {
- if (nrepeats)
- 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);
-}
-
-tree
-build_static_name (basetype, name)
- tree basetype, name;
-{
- char *basename = build_overload_name (basetype, 1, 1);
- char *buf = (char *) alloca (IDENTIFIER_LENGTH (name)
- + sizeof (STATIC_NAME_FORMAT)
- + strlen (basename));
- sprintf (buf, STATIC_NAME_FORMAT, basename, IDENTIFIER_POINTER (name));
- return get_identifier (buf);
-}
-
-/* Generate an identifier that encodes the (ANSI) exception TYPE. */
-
-/* This should be part of `ansi_opname', or at least be defined by the std. */
-#define EXCEPTION_NAME_PREFIX "__ex"
-#define EXCEPTION_NAME_LENGTH 4
-
-tree
-cplus_exception_name (type)
- tree type;
-{
- OB_INIT ();
- OB_PUTS (EXCEPTION_NAME_PREFIX);
- return get_identifier (build_overload_name (type, 0, 1));
-}
-
-/* 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;
-{
- char *name = IDENTIFIER_POINTER (dname);
-
- /* member operators new and delete look like methods at this point. */
- if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST)
- {
- 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");
- else if (TREE_CHAIN (parms) == void_list_node)
- {
- 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");
- }
- }
-
- OB_INIT ();
- if (for_method != 2)
- OB_PUTCP (name);
- /* Otherwise, we can divine that this is a constructor,
- 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
- {
- 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
- OB_PUTC ('F');
-
- if (parms == NULL_TREE)
- OB_PUTC2 ('e', '\0');
- else if (parms == void_list_node)
- OB_PUTC2 ('v', '\0');
- else
- {
- ALLOCATE_TYPEVEC (parms);
- nofold = 0;
- if (for_method)
- {
- build_overload_name (TREE_VALUE (parms), 0, 0);
-
- typevec[maxtype++] = TREE_VALUE (parms);
- TREE_USED (TREE_VALUE (parms)) = 1;
-
- if (TREE_CHAIN (parms))
- build_overload_name (TREE_CHAIN (parms), 0, 1);
- else
- OB_PUTC2 ('e', '\0');
- }
- else
- build_overload_name (parms, 0, 1);
- DEALLOCATE_TYPEVEC (parms);
- }
- {
- tree n = get_identifier (obstack_base (&scratch_obstack));
- if (IDENTIFIER_OPNAME_P (dname))
- IDENTIFIER_OPNAME_P (n) = 1;
- return n;
- }
-}
-
-/* Build an overload name for the type expression TYPE. */
-tree
-build_typename_overload (type)
- tree type;
-{
- tree id;
-
- OB_INIT ();
- OB_PUTID (ansi_opname[(int) TYPE_EXPR]);
- nofold = 1;
- build_overload_name (type, 0, 1);
- id = get_identifier (obstack_base (&scratch_obstack));
- IDENTIFIER_OPNAME_P (id) = 1;
-#if 0
- IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type);
-#endif
- TREE_TYPE (id) = type;
- return id;
-}
-
-#ifndef NO_DOLLAR_IN_LABEL
-#define T_DESC_FORMAT "TD$"
-#define I_DESC_FORMAT "ID$"
-#define M_DESC_FORMAT "MD$"
-#else
-#if !defined(NO_DOT_IN_LABEL)
-#define T_DESC_FORMAT "TD."
-#define I_DESC_FORMAT "ID."
-#define M_DESC_FORMAT "MD."
-#else
-#define T_DESC_FORMAT "__t_desc_"
-#define I_DESC_FORMAT "__i_desc_"
-#define M_DESC_FORMAT "__m_desc_"
-#endif
-#endif
-
-/* Build an overload name for the type expression TYPE. */
-tree
-build_t_desc_overload (type)
- tree type;
-{
- OB_INIT ();
- OB_PUTS (T_DESC_FORMAT);
- nofold = 1;
-
-#if 0
- /* Use a different format if the type isn't defined yet. */
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- char *p;
- int changed;
-
- for (p = tname; *p; p++)
- if (isupper (*p))
- {
- changed = 1;
- *p = tolower (*p);
- }
- /* If there's no change, we have an inappropriate T_DESC_FORMAT. */
- my_friendly_assert (changed != 0, 249);
- }
-#endif
-
- build_overload_name (type, 0, 1);
- return get_identifier (obstack_base (&scratch_obstack));
-}
-
-/* Top-level interface to explicit overload requests. Allow NAME
- to be overloaded. Error if NAME is already declared for the current
- scope. Warning if function is redundantly overloaded. */
-
-void
-declare_overloaded (name)
- tree name;
-{
-#ifdef NO_AUTO_OVERLOAD
- if (is_overloaded (name))
- warning ("function `%s' already declared overloaded",
- IDENTIFIER_POINTER (name));
- else if (IDENTIFIER_GLOBAL_VALUE (name))
- error ("overloading function `%s' that is already defined",
- IDENTIFIER_POINTER (name));
- else
- {
- TREE_OVERLOADED (name) = 1;
- IDENTIFIER_GLOBAL_VALUE (name) = build_tree_list (name, NULL_TREE);
- TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)) = unknown_type_node;
- }
-#else
- if (current_lang_name == lang_name_cplusplus)
- {
- if (0)
- warning ("functions are implicitly overloaded in C++");
- }
- else if (current_lang_name == lang_name_c)
- error ("overloading function `%s' cannot be done in C language context");
- else
- my_friendly_abort (76);
-#endif
-}
-
-#ifdef NO_AUTO_OVERLOAD
-/* Check to see if NAME is overloaded. For first approximation,
- check to see if its TREE_OVERLOADED is set. This is used on
- IDENTIFIER nodes. */
-int
-is_overloaded (name)
- tree name;
-{
- /* @@ */
- return (TREE_OVERLOADED (name)
- && (! IDENTIFIER_CLASS_VALUE (name) || current_class_type == 0)
- && ! IDENTIFIER_LOCAL_VALUE (name));
-}
-#endif
-
-/* Given a tree_code CODE, and some arguments (at least one),
- attempt to use an overloaded operator on the arguments.
-
- For unary operators, only the first argument need be checked.
- For binary operators, both arguments may need to be checked.
-
- Member functions can convert class references to class pointers,
- for one-level deep indirection. More than that is not supported.
- Operators [](), ()(), and ->() must be member functions.
-
- We call function call building calls with LOOKUP_COMPLAIN if they
- are our only hope. This is true when we see a vanilla operator
- applied to something of aggregate type. If this fails, we are free
- to return `error_mark_node', because we will have reported the
- error.
-
- Operators NEW and DELETE overload in funny ways: operator new takes
- a single `size' parameter, and operator delete takes a pointer to the
- storage being deleted. When overloading these operators, success is
- assumed. If there is a failure, report an error message and return
- `error_mark_node'. */
-
-/* NOSTRICT */
-tree
-build_opfncall (code, flags, xarg1, xarg2, arg3)
- enum tree_code code;
- int flags;
- tree xarg1, xarg2, arg3;
-{
- tree rval = 0;
- tree arg1, arg2;
- tree type1, type2, fnname;
- tree fields1 = 0, parms = 0;
- tree global_fn;
- int try_second;
- int binary_is_unary;
-
- if (xarg1 == error_mark_node)
- return error_mark_node;
-
- if (code == COND_EXPR)
- {
- if (TREE_CODE (xarg2) == ERROR_MARK
- || TREE_CODE (arg3) == ERROR_MARK)
- return error_mark_node;
- }
- if (code == COMPONENT_REF)
- if (TREE_CODE (TREE_TYPE (xarg1)) == POINTER_TYPE)
- return rval;
-
- /* First, see if we can work with the first argument */
- type1 = TREE_TYPE (xarg1);
-
- /* Some tree codes have length > 1, but we really only want to
- overload them if their first argument has a user defined type. */
- switch (code)
- {
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- case COMPONENT_REF:
- binary_is_unary = 1;
- try_second = 0;
- break;
-
- /* ARRAY_REFs and CALL_EXPRs must overload successfully.
- If they do not, return error_mark_node instead of NULL_TREE. */
- case ARRAY_REF:
- if (xarg2 == error_mark_node)
- return error_mark_node;
- case CALL_EXPR:
- rval = error_mark_node;
- binary_is_unary = 0;
- try_second = 0;
- break;
-
- case VEC_NEW_EXPR:
- case NEW_EXPR:
- {
- tree args = tree_cons (NULL_TREE, xarg2, arg3);
- fnname = ansi_opname[(int) code];
- if (flags & LOOKUP_GLOBAL)
- return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN,
- (struct candidate *)0);
-
- rval = build_method_call
- (build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node),
- "new"),
- fnname, args, NULL_TREE, flags);
- if (rval == error_mark_node)
- /* User might declare fancy operator new, but invoke it
- like standard one. */
- return rval;
-
- TREE_TYPE (rval) = xarg1;
- TREE_CALLS_NEW (rval) = 1;
- return rval;
- }
- break;
-
- case VEC_DELETE_EXPR:
- case DELETE_EXPR:
- {
- fnname = ansi_opname[(int) code];
- if (flags & LOOKUP_GLOBAL)
- return build_overload_call (fnname,
- build_tree_list (NULL_TREE, xarg1),
- flags & LOOKUP_COMPLAIN,
- (struct candidate *)0);
-
- rval = build_method_call
- (build_indirect_ref (build1 (NOP_EXPR, TREE_TYPE (xarg1),
- error_mark_node),
- NULL_PTR),
- fnname, tree_cons (NULL_TREE, xarg1,
- build_tree_list (NULL_TREE, xarg2)),
- NULL_TREE, flags);
- /* This happens when the user mis-declares `operator delete'.
- Should now be impossible. */
- my_friendly_assert (rval != error_mark_node, 250);
- TREE_TYPE (rval) = void_type_node;
- return rval;
- }
- break;
-
- default:
- binary_is_unary = 0;
- try_second = tree_code_length [(int) code] == 2;
- if (try_second && xarg2 == error_mark_node)
- return error_mark_node;
- break;
- }
-
- if (try_second && xarg2 == error_mark_node)
- return error_mark_node;
-
- /* What ever it was, we do not know how to deal with it. */
- if (type1 == NULL_TREE)
- return rval;
-
- if (TREE_CODE (type1) == OFFSET_TYPE)
- type1 = TREE_TYPE (type1);
-
- if (TREE_CODE (type1) == REFERENCE_TYPE)
- {
- arg1 = convert_from_reference (xarg1);
- type1 = TREE_TYPE (arg1);
- }
- else
- {
- arg1 = xarg1;
- }
-
- if (!IS_AGGR_TYPE (type1) || TYPE_PTRMEMFUNC_P (type1))
- {
- /* Try to fail. First, fail if unary */
- if (! try_second)
- return rval;
- /* Second, see if second argument is non-aggregate. */
- type2 = TREE_TYPE (xarg2);
- if (TREE_CODE (type2) == OFFSET_TYPE)
- type2 = TREE_TYPE (type2);
- if (TREE_CODE (type2) == REFERENCE_TYPE)
- {
- arg2 = convert_from_reference (xarg2);
- type2 = TREE_TYPE (arg2);
- }
- else
- {
- arg2 = xarg2;
- }
-
- if (!IS_AGGR_TYPE (type2))
- return rval;
- try_second = 0;
- }
-
- if (try_second)
- {
- /* First arg may succeed; see whether second should. */
- type2 = TREE_TYPE (xarg2);
- if (TREE_CODE (type2) == OFFSET_TYPE)
- type2 = TREE_TYPE (type2);
- if (TREE_CODE (type2) == REFERENCE_TYPE)
- {
- arg2 = convert_from_reference (xarg2);
- type2 = TREE_TYPE (arg2);
- }
- else
- {
- arg2 = xarg2;
- }
-
- if (! IS_AGGR_TYPE (type2))
- try_second = 0;
- }
-
- if (type1 == unknown_type_node
- || (try_second && TREE_TYPE (xarg2) == unknown_type_node))
- {
- /* This will not be implemented in the foreseeable future. */
- return rval;
- }
-
- if (code == MODIFY_EXPR)
- fnname = ansi_assopname[(int) TREE_CODE (arg3)];
- else
- fnname = ansi_opname[(int) code];
-
- global_fn = lookup_name_nonclass (fnname);
-
- /* This is the last point where we will accept failure. This
- may be too eager if we wish an overloaded operator not to match,
- but would rather a normal operator be called on a type-converted
- argument. */
-
- if (IS_AGGR_TYPE (type1))
- {
- fields1 = lookup_fnfields (TYPE_BINFO (type1), fnname, 0);
- /* ARM $13.4.7, prefix/postfix ++/--. */
- if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
- {
- xarg2 = integer_zero_node;
- binary_is_unary = 0;
-
- if (fields1)
- {
- tree t, t2;
- int have_postfix = 0;
-
- /* Look for an `operator++ (int)'. If they didn't have
- one, then we fall back to the old way of doing things. */
- for (t = TREE_VALUE (fields1); t ; t = TREE_CHAIN (t))
- {
- t2 = TYPE_ARG_TYPES (TREE_TYPE (t));
- if (TREE_CHAIN (t2) != NULL_TREE
- && TREE_VALUE (TREE_CHAIN (t2)) == integer_type_node)
- {
- have_postfix = 1;
- break;
- }
- }
-
- if (! have_postfix)
- {
- char *op = POSTINCREMENT_EXPR ? "++" : "--";
-
- /* There's probably a LOT of code in the world that
- relies upon this old behavior. So we'll only give this
- warning when we've been given -pedantic. A few
- releases after 2.4, we'll convert this to be a pedwarn
- or something else more appropriate. */
- if (pedantic)
- warning ("no `operator%s (int)' declared for postfix `%s'",
- op, op);
- xarg2 = NULL_TREE;
- binary_is_unary = 1;
- }
- }
- }
- }
-
- if (fields1 == NULL_TREE && global_fn == NULL_TREE)
- return rval;
-
- /* If RVAL winds up being `error_mark_node', we will return
- that... There is no way that normal semantics of these
- operators will succeed. */
-
- /* This argument may be an uncommitted OFFSET_REF. This is
- the case for example when dealing with static class members
- which are referenced from their class name rather than
- from a class instance. */
- if (TREE_CODE (xarg1) == OFFSET_REF
- && TREE_CODE (TREE_OPERAND (xarg1, 1)) == VAR_DECL)
- xarg1 = TREE_OPERAND (xarg1, 1);
- if (try_second && xarg2 && TREE_CODE (xarg2) == OFFSET_REF
- && TREE_CODE (TREE_OPERAND (xarg2, 1)) == VAR_DECL)
- xarg2 = TREE_OPERAND (xarg2, 1);
-
- if (global_fn)
- flags |= LOOKUP_GLOBAL;
-
- if (code == CALL_EXPR)
- {
- /* This can only be a member function. */
- return build_method_call (xarg1, fnname, xarg2,
- NULL_TREE, LOOKUP_NORMAL);
- }
- else if (tree_code_length[(int) code] == 1 || binary_is_unary)
- {
- parms = NULL_TREE;
- rval = build_method_call (xarg1, fnname, NULL_TREE, NULL_TREE, flags);
- }
- else if (code == COND_EXPR)
- {
- parms = tree_cons (0, xarg2, build_tree_list (NULL_TREE, arg3));
- rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);
- }
- else if (code == METHOD_CALL_EXPR)
- {
- /* must be a member function. */
- parms = tree_cons (NULL_TREE, xarg2, arg3);
- return build_method_call (xarg1, fnname, parms, NULL_TREE,
- LOOKUP_NORMAL);
- }
- else if (fields1)
- {
- parms = build_tree_list (NULL_TREE, xarg2);
- rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);
- }
- else
- {
- parms = tree_cons (NULL_TREE, xarg1,
- build_tree_list (NULL_TREE, xarg2));
- rval = build_overload_call (fnname, parms, flags,
- (struct candidate *)0);
- }
-
- return rval;
-}
-
-/* This function takes an identifier, ID, and attempts to figure out what
- it means. There are a number of possible scenarios, presented in increasing
- order of hair:
-
- 1) not in a class's scope
- 2) in class's scope, member name of the class's method
- 3) in class's scope, but not a member name of the class
- 4) in class's scope, member name of a class's variable
-
- NAME is $1 from the bison rule. It is an IDENTIFIER_NODE.
- VALUE is $$ from the bison rule. It is the value returned by lookup_name ($1)
- yychar is the pending input character (suitably encoded :-).
-
- As a last ditch, try to look up the name as a label and return that
- address.
-
- Values which are declared as being of REFERENCE_TYPE are
- automatically dereferenced here (as a hack to make the
- compiler faster). */
-
-tree
-hack_identifier (value, name, yychar)
- tree value, name;
- int yychar;
-{
- tree type;
-
- if (TREE_CODE (value) == ERROR_MARK)
- {
- if (current_class_name)
- {
- tree fields = lookup_fnfields (TYPE_BINFO (current_class_type), name, 1);
- if (fields == error_mark_node)
- return error_mark_node;
- if (fields)
- {
- tree fndecl;
-
- fndecl = TREE_VALUE (fields);
- my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251);
- if (DECL_CHAIN (fndecl) == NULL_TREE)
- {
- warning ("methods cannot be converted to function pointers");
- return fndecl;
- }
- else
- {
- error ("ambiguous request for method pointer `%s'",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- }
- }
- if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name))
- {
- return IDENTIFIER_LABEL_VALUE (name);
- }
- return error_mark_node;
- }
-
- type = TREE_TYPE (value);
- if (TREE_CODE (value) == FIELD_DECL)
- {
- if (current_class_decl == NULL_TREE)
- {
- error ("request for member `%s' in static member function",
- IDENTIFIER_POINTER (DECL_NAME (value)));
- return error_mark_node;
- }
- TREE_USED (current_class_decl) = 1;
- if (yychar == '(')
- if (! ((TYPE_LANG_SPECIFIC (type)
- && TYPE_OVERLOADS_CALL_EXPR (type))
- || (TREE_CODE (type) == REFERENCE_TYPE
- && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
- && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (type))))
- && TREE_CODE (type) != FUNCTION_TYPE
- && TREE_CODE (type) != METHOD_TYPE
- && !TYPE_PTRMEMFUNC_P (type)
- && (TREE_CODE (type) != POINTER_TYPE
- || (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE)))
- {
- error ("component `%s' is not a method",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- /* Mark so that if we are in a constructor, and then find that
- this field was initialized by a base initializer,
- we can emit an error message. */
- TREE_USED (value) = 1;
- return build_component_ref (C_C_D, name, 0, 1);
- }
-
- if (really_overloaded_fn (value))
- {
- tree t = get_first_fn (value);
- for (; t; t = DECL_CHAIN (t))
- {
- if (TREE_CODE (t) == TEMPLATE_DECL)
- continue;
-
- assemble_external (t);
- TREE_USED (t) = 1;
- }
- }
- else if (TREE_CODE (value) == TREE_LIST)
- {
- tree t = value;
- while (t && TREE_CODE (t) == TREE_LIST)
- {
- assemble_external (TREE_VALUE (t));
- TREE_USED (t) = 1;
- t = TREE_CHAIN (t);
- }
- }
- else
- {
- assemble_external (value);
- TREE_USED (value) = 1;
- }
-
- if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))
- {
- if (DECL_LANG_SPECIFIC (value)
- && DECL_CLASS_CONTEXT (value) != current_class_type)
- {
- tree path;
- enum access_type access;
- register tree context
- = (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value))
- ? DECL_CLASS_CONTEXT (value)
- : DECL_CONTEXT (value);
-
- get_base_distance (context, current_class_type, 0, &path);
- if (path)
- {
- access = compute_access (path, value);
- if (access != access_public)
- {
- if (TREE_CODE (value) == VAR_DECL)
- error ("static member `%s' is %s",
- IDENTIFIER_POINTER (name),
- TREE_PRIVATE (value) ? "private" :
- "from a private base class");
- else
- error ("enum `%s' is from private base class",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- }
- }
- return value;
- }
- if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value))
- {
- if (type == 0)
- {
- error ("request for member `%s' is ambiguous in multiple inheritance lattice",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
-
- return value;
- }
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- my_friendly_assert (TREE_CODE (value) == VAR_DECL
- || TREE_CODE (value) == PARM_DECL
- || TREE_CODE (value) == RESULT_DECL, 252);
- if (DECL_REFERENCE_SLOT (value))
- return DECL_REFERENCE_SLOT (value);
- }
- return value;
-}
-
-
-#if 0
-/* Given an object OF, and a type conversion operator COMPONENT
- build a call to the conversion operator, if a call is requested,
- or return the address (as a pointer to member function) if one is not.
-
- OF can be a TYPE_DECL or any kind of datum that would normally
- be passed to `build_component_ref'. It may also be NULL_TREE,
- in which case `current_class_type' and `current_class_decl'
- provide default values.
-
- BASETYPE_PATH, if non-null, is the path of basetypes
- to go through before we get the the instance of interest.
-
- PROTECT says whether we apply C++ scoping rules or not. */
-tree
-build_component_type_expr (of, component, basetype_path, protect)
- tree of, component, basetype_path;
- int protect;
-{
- tree cname = NULL_TREE;
- tree tmp, last;
- tree name;
- int flags = protect ? LOOKUP_NORMAL : LOOKUP_COMPLAIN;
-
- if (of)
- my_friendly_assert (IS_AGGR_TYPE (TREE_TYPE (of)), 253);
- my_friendly_assert (TREE_CODE (component) == TYPE_EXPR, 254);
-
- tmp = TREE_OPERAND (component, 0);
- last = NULL_TREE;
-
- while (tmp)
- {
- switch (TREE_CODE (tmp))
- {
- case CALL_EXPR:
- if (last)
- TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0);
- else
- TREE_OPERAND (component, 0) = TREE_OPERAND (tmp, 0);
-
- last = groktypename (build_tree_list (TREE_TYPE (component),
- TREE_OPERAND (component, 0)));
- name = build_typename_overload (last);
- TREE_TYPE (name) = last;
-
- if (TREE_OPERAND (tmp, 0)
- && TREE_OPERAND (tmp, 0) != void_list_node)
- {
- cp_error ("`operator %T' requires empty parameter list", last);
- TREE_OPERAND (tmp, 0) = NULL_TREE;
- }
-
- if (of && TREE_CODE (of) != TYPE_DECL)
- return build_method_call (of, name, NULL_TREE, NULL_TREE, flags);
- else if (of)
- {
- tree this_this;
-
- if (current_class_decl == NULL_TREE)
- {
- cp_error ("object required for `operator %T' call",
- TREE_TYPE (name));
- return error_mark_node;
- }
-
- this_this = convert_pointer_to (TREE_TYPE (of),
- current_class_decl);
- this_this = build_indirect_ref (this_this, NULL_PTR);
- return build_method_call (this_this, name, NULL_TREE,
- NULL_TREE, flags | LOOKUP_NONVIRTUAL);
- }
- else if (current_class_decl)
- return build_method_call (tmp, name, NULL_TREE, NULL_TREE, flags);
-
- cp_error ("object required for `operator %T' call",
- TREE_TYPE (name));
- return error_mark_node;
-
- case INDIRECT_REF:
- case ADDR_EXPR:
- case ARRAY_REF:
- break;
-
- case SCOPE_REF:
- my_friendly_assert (cname == 0, 255);
- cname = TREE_OPERAND (tmp, 0);
- tmp = TREE_OPERAND (tmp, 1);
- break;
-
- default:
- my_friendly_abort (77);
- }
- last = tmp;
- tmp = TREE_OPERAND (tmp, 0);
- }
-
- last = groktypename (build_tree_list (TREE_TYPE (component), TREE_OPERAND (component, 0)));
- name = build_typename_overload (last);
- TREE_TYPE (name) = last;
- if (of && TREE_CODE (of) == TYPE_DECL)
- {
- if (cname == NULL_TREE)
- {
- cname = DECL_NAME (of);
- of = NULL_TREE;
- }
- else my_friendly_assert (cname == DECL_NAME (of), 256);
- }
-
- if (of)
- {
- tree this_this;
-
- if (current_class_decl == NULL_TREE)
- {
- cp_error ("object required for `operator %T' call",
- TREE_TYPE (name));
- return error_mark_node;
- }
-
- this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl);
- return build_component_ref (this_this, name, 0, protect);
- }
- else if (cname)
- return build_offset_ref (cname, name);
- else if (current_class_name)
- return build_offset_ref (current_class_name, name);
-
- cp_error ("object required for `operator %T' member reference",
- TREE_TYPE (name));
- return error_mark_node;
-}
-#endif
-
-static char *
-thunk_printable_name (decl)
- tree decl;
-{
- return "<thunk function>";
-}
-
-tree
-make_thunk (function, delta)
- tree function;
- int delta;
-{
- char buffer[250];
- tree thunk_fndecl, thunk_id;
- tree thunk;
- char *func_name;
- static int thunk_number = 0;
- 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));
- sprintf (buffer, "__thunk_%d_%s", -delta, func_name);
- thunk_id = get_identifier (buffer);
- thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
- if (thunk && TREE_CODE (thunk) != THUNK_DECL)
- {
- error_with_decl ("implementation-reserved name `%s' used");
- IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE;
- }
- if (thunk == NULL_TREE)
- {
- thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl));
- DECL_RESULT (thunk)
- = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type));
- make_function_rtl (thunk);
- DECL_INITIAL (thunk) = function;
- THUNK_DELTA (thunk) = delta;
- /* So that finish_file can write out any thunks that need to be: */
- pushdecl_top_level (thunk);
- }
- return thunk;
-}
-
-void
-emit_thunk (thunk_fndecl)
- tree thunk_fndecl;
-{
- rtx insns;
- char *fnname;
- char buffer[250];
- tree argp;
- struct args_size stack_args_size;
- tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0);
- int delta = THUNK_DELTA (thunk_fndecl);
- int tem;
- int failure = 0;
- int current_call_is_indirect = 0; /* needed for HPPA FUNCTION_ARG */
-
- /* Used to remember which regs we need to emit a USE rtx for. */
- rtx need_use[FIRST_PSEUDO_REGISTER];
- int need_use_count = 0;
-
- /* rtx for the 'this' parameter. */
- rtx this_rtx = 0, this_reg_rtx = 0, fixed_this_rtx;
-
- char *(*save_decl_printable_name) () = decl_printable_name;
- /* Data on reg parms scanned so far. */
- CUMULATIVE_ARGS args_so_far;
-
- if (TREE_ASM_WRITTEN (thunk_fndecl))
- return;
-
- TREE_ASM_WRITTEN (thunk_fndecl) = 1;
-
- if (TREE_PUBLIC (function))
- {
- TREE_PUBLIC (thunk_fndecl) = 1;
- if (DECL_EXTERNAL (function))
- {
- DECL_EXTERNAL (thunk_fndecl) = 1;
- assemble_external (thunk_fndecl);
- return;
- }
- }
-
- decl_printable_name = thunk_printable_name;
- if (current_function_decl)
- abort ();
- current_function_decl = thunk_fndecl;
- init_function_start (thunk_fndecl, input_filename, lineno);
- pushlevel (0);
- expand_start_bindings (1);
-
- /* Start updating where the next arg would go. */
- INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (function), NULL_RTX);
- stack_args_size.constant = 0;
- stack_args_size.var = 0;
- /* SETUP for possible structure return address FIXME */
-
- /* Now look through all the parameters, make sure that we
- don't clobber any registers used for parameters.
- Also, pick up an rtx for the first "this" parameter. */
- for (argp = TYPE_ARG_TYPES (TREE_TYPE (function));
- argp != NULL_TREE;
- argp = TREE_CHAIN (argp))
-
- {
- tree passed_type = TREE_VALUE (argp);
- register rtx entry_parm;
- int named = 1; /* FIXME */
- struct args_size stack_offset;
- struct args_size arg_size;
-
- if (passed_type == void_type_node)
- break;
-
- if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST
- && contains_placeholder_p (TYPE_SIZE (passed_type)))
-#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
- || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far,
- TYPE_MODE (passed_type),
- passed_type, named)
-#endif
- )
- passed_type = build_pointer_type (passed_type);
-
- entry_parm = FUNCTION_ARG (args_so_far,
- TYPE_MODE (passed_type),
- passed_type,
- named);
- if (entry_parm != 0)
- need_use[need_use_count++] = entry_parm;
-
- locate_and_pad_parm (TYPE_MODE (passed_type), passed_type,
-#ifdef STACK_PARMS_IN_REG_PARM_AREA
- 1,
-#else
- entry_parm != 0,
-#endif
- thunk_fndecl,
- &stack_args_size, &stack_offset, &arg_size);
-
-/* REGNO (entry_parm);*/
- if (this_rtx == 0)
- {
- this_reg_rtx = entry_parm;
- if (!entry_parm)
- {
- rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
-
- rtx internal_arg_pointer, stack_parm;
-
- if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
- || ! (fixed_regs[ARG_POINTER_REGNUM]
- || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
- internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
- else
- internal_arg_pointer = virtual_incoming_args_rtx;
-
- if (offset_rtx == const0_rtx)
- entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
- internal_arg_pointer);
- else
- entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type),
- gen_rtx (PLUS, Pmode,
- internal_arg_pointer,
- offset_rtx));
- }
-
- this_rtx = entry_parm;
- }
-
- FUNCTION_ARG_ADVANCE (args_so_far,
- TYPE_MODE (passed_type),
- passed_type,
- named);
- }
-
- fixed_this_rtx = plus_constant (this_rtx, delta);
- if (this_rtx != fixed_this_rtx)
- emit_move_insn (this_rtx, fixed_this_rtx);
-
- if (this_reg_rtx)
- emit_insn (gen_rtx (USE, VOIDmode, this_reg_rtx));
-
- emit_indirect_jump (XEXP (DECL_RTL (function), 0));
-
- while (need_use_count > 0)
- emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
-
- expand_end_bindings (NULL, 1, 0);
- poplevel (0, 0, 0);
-
- /* From now on, allocate rtl in current_obstack, not in saveable_obstack.
- Note that that may have been done above, in save_for_inline_copying.
- The call to resume_temporary_allocation near the end of this function
- goes back to the usual state of affairs. */
-
- rtl_in_current_obstack ();
-
- insns = get_insns ();
-
- /* Copy any shared structure that should not be shared. */
-
- unshare_all_rtl (insns);
-
- /* We are no longer anticipating cse in this function, at least. */
-
- cse_not_expected = 1;
-
- /* Now we choose between stupid (pcc-like) register allocation
- (if we got the -noreg switch and not -opt)
- and smart register allocation. */
-
- if (optimize > 0) /* Stupid allocation probably won't work */
- obey_regdecls = 0; /* if optimizations being done. */
-
- regclass_init ();
-
- regclass (insns, max_reg_num ());
- if (obey_regdecls)
- {
- stupid_life_analysis (insns, max_reg_num (), NULL);
- failure = reload (insns, 0, NULL);
- }
- else
- {
- /* Do control and data flow analysis,
- and write some of the results to dump file. */
-
- flow_analysis (insns, max_reg_num (), NULL);
- local_alloc ();
- failure = global_alloc (NULL);
- }
-
- reload_completed = 1;
-
-#ifdef LEAF_REGISTERS
- leaf_function = 0;
- if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ())
- leaf_function = 1;
-#endif
-
- /* If a machine dependent reorganization is needed, call it. */
-#ifdef MACHINE_DEPENDENT_REORG
- MACHINE_DEPENDENT_REORG (insns);
-#endif
-
- /* Now turn the rtl into assembler code. */
-
- {
- char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
- assemble_start_function (thunk_fndecl, fnname);
- final (insns, asm_out_file, optimize, 0);
- assemble_end_function (thunk_fndecl, fnname);
- };
-
- exit_rest_of_compilation:
-
- reload_completed = 0;
-
- /* Cancel the effect of rtl_in_current_obstack. */
-
- resume_temporary_allocation ();
-
- decl_printable_name = save_decl_printable_name;
- current_function_decl = 0;
-}
-
-/* Code for synthesizing methods which have default semantics defined. */
-
-void
-build_default_constructor (fndecl)
- tree fndecl;
-{
- start_function (NULL_TREE, fndecl, NULL_TREE, 1);
- store_parm_decls ();
- setup_vtbl_ptr ();
- finish_function (lineno, 0);
-}
-
-/* For the anonymous union in TYPE, return the member that is at least as
- large as the rest of the members, so we can copy it. */
-static tree
-largest_union_member (type)
- tree type;
-{
- tree f, type_size = TYPE_SIZE (type);
-
- for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
- if (simple_cst_equal (DECL_SIZE (f), type_size))
- return f;
-
- /* We should always find one. */
- my_friendly_abort (323);
- return NULL_TREE;
-}
-
-/* Generate code for default X(X&) constructor. */
-void
-build_copy_constructor (fndecl)
- tree fndecl;
-{
- tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
- tree t;
-
- start_function (NULL_TREE, fndecl, NULL_TREE, 1);
- store_parm_decls ();
- clear_last_expr ();
- push_momentary ();
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- parm = TREE_CHAIN (parm);
- parm = convert_from_reference (parm);
-
- if (! TYPE_HAS_COMPLEX_INIT_REF (current_class_type))
- {
- t = build (INIT_EXPR, void_type_node, C_C_D, parm);
- TREE_SIDE_EFFECTS (t) = 1;
- cplus_expand_expr_stmt (t);
- }
- else
- {
- tree fields = TYPE_FIELDS (current_class_type);
- int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
- tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
- int i;
-
- for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;
- t = TREE_CHAIN (t))
- {
- tree basetype = BINFO_TYPE (t);
- tree p = convert (build_reference_type (basetype), parm);
- p = convert_from_reference (p);
- current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
- p, current_base_init_list);
- }
-
- for (i = 0; i < n_bases; ++i)
- {
- tree p, basetype = TREE_VEC_ELT (binfos, i);
- if (TREE_VIA_VIRTUAL (basetype))
- continue;
-
- basetype = BINFO_TYPE (basetype);
- p = convert (build_reference_type (basetype), parm);
- p = convert_from_reference (p);
- current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
- p, current_base_init_list);
- }
- for (; fields; fields = TREE_CHAIN (fields))
- {
- tree name, init, t;
- if (TREE_CODE (fields) != FIELD_DECL)
- continue;
- if (DECL_NAME (fields))
- {
- if (VFIELD_NAME_P (DECL_NAME (fields)))
- continue;
- if (VBASE_NAME_P (DECL_NAME (fields)))
- continue;
-
- /* True for duplicate members. */
- if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
- continue;
- }
- else if ((t = TREE_TYPE (fields)) != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
- && TYPE_FIELDS (t) != NULL_TREE)
- fields = largest_union_member (t);
- else
- continue;
-
- init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
- init = build_tree_list (NULL_TREE, init);
-
- current_member_init_list
- = tree_cons (DECL_NAME (fields), init, current_member_init_list);
- }
- current_member_init_list = nreverse (current_member_init_list);
- setup_vtbl_ptr ();
- }
-
- pop_momentary ();
- finish_function (lineno, 0);
-}
-
-void
-build_assign_ref (fndecl)
- tree fndecl;
-{
- tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
-
- start_function (NULL_TREE, fndecl, NULL_TREE, 1);
- store_parm_decls ();
- push_momentary ();
-
- parm = convert_from_reference (parm);
-
- if (! TYPE_HAS_COMPLEX_ASSIGN_REF (current_class_type))
- {
- tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm);
- TREE_SIDE_EFFECTS (t) = 1;
- cplus_expand_expr_stmt (t);
- }
- else
- {
- tree fields = TYPE_FIELDS (current_class_type);
- int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
- tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
- int i;
-
- for (i = 0; i < n_bases; ++i)
- {
- tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
- if (TYPE_HAS_ASSIGN_REF (basetype))
- {
- tree p = convert (build_reference_type (basetype), parm);
- p = convert_from_reference (p);
- p = build_member_call (TYPE_NESTED_NAME (basetype),
- ansi_opname [MODIFY_EXPR],
- build_tree_list (NULL_TREE, p));
- expand_expr_stmt (p);
- }
- }
- for (; fields; fields = TREE_CHAIN (fields))
- {
- tree comp, init, t;
- if (TREE_CODE (fields) != FIELD_DECL)
- continue;
- if (DECL_NAME (fields))
- {
- if (VFIELD_NAME_P (DECL_NAME (fields)))
- continue;
- if (VBASE_NAME_P (DECL_NAME (fields)))
- continue;
-
- /* True for duplicate members. */
- if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
- continue;
- }
- else if ((t = TREE_TYPE (fields)) != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
- && TYPE_FIELDS (t) != NULL_TREE)
- fields = largest_union_member (t);
- else
- continue;
-
- comp = build (COMPONENT_REF, TREE_TYPE (fields), C_C_D, fields);
- init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
-
- expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
- }
- }
- c_expand_return (C_C_D);
- pop_momentary ();
- finish_function (lineno, 0);
-}
-
-void
-build_dtor (fndecl)
- tree fndecl;
-{
- start_function (NULL_TREE, fndecl, NULL_TREE, 1);
- store_parm_decls ();
- finish_function (lineno, 0);
-}
OpenPOWER on IntegriCloud