aboutsummaryrefslogtreecommitdiff
path: root/gnu/gcc2/cc1plus
diff options
context:
space:
mode:
authorsvn2git <svn2git@FreeBSD.org>1994-05-01 08:00:00 +0000
committersvn2git <svn2git@FreeBSD.org>1994-05-01 08:00:00 +0000
commita16f65c7d117419bd266c28a1901ef129a337569 (patch)
tree2626602f66dc3551e7a7c7bc9ad763c3bc7ab40a /gnu/gcc2/cc1plus
parent8503f4f13f77abf7adc8f7e329c6f9c1d52b6a20 (diff)
This commit was manufactured to restore the state of the 1.1-RELEASE image. Releases prior to 5.3-RELEASE are omitting the secure/ and crypto/ subdirs.
Diffstat (limited to 'gnu/gcc2/cc1plus')
-rw-r--r--gnu/gcc2/cc1plus/Makefile24
-rw-r--r--gnu/gcc2/cc1plus/cp-call.c2823
-rw-r--r--gnu/gcc2/cc1plus/cp-class.c4274
-rw-r--r--gnu/gcc2/cc1plus/cp-class.h115
-rw-r--r--gnu/gcc2/cc1plus/cp-cvt.c1790
-rw-r--r--gnu/gcc2/cc1plus/cp-decl.c11551
-rw-r--r--gnu/gcc2/cc1plus/cp-decl.h59
-rw-r--r--gnu/gcc2/cc1plus/cp-decl2.c2451
-rw-r--r--gnu/gcc2/cc1plus/cp-edsel.c927
-rw-r--r--gnu/gcc2/cc1plus/cp-except.c1221
-rw-r--r--gnu/gcc2/cc1plus/cp-expr.c222
-rw-r--r--gnu/gcc2/cc1plus/cp-gc.c793
-rw-r--r--gnu/gcc2/cc1plus/cp-hash.h186
-rw-r--r--gnu/gcc2/cc1plus/cp-init.c4008
-rw-r--r--gnu/gcc2/cc1plus/cp-input.c184
-rw-r--r--gnu/gcc2/cc1plus/cp-lex.c4232
-rw-r--r--gnu/gcc2/cc1plus/cp-lex.h107
-rw-r--r--gnu/gcc2/cc1plus/cp-method.c2679
-rw-r--r--gnu/gcc2/cc1plus/cp-parse.c7295
-rw-r--r--gnu/gcc2/cc1plus/cp-parse.h88
-rw-r--r--gnu/gcc2/cc1plus/cp-pt.c2123
-rw-r--r--gnu/gcc2/cc1plus/cp-ptree.c153
-rw-r--r--gnu/gcc2/cc1plus/cp-search.c4284
-rw-r--r--gnu/gcc2/cc1plus/cp-spew.c1086
-rw-r--r--gnu/gcc2/cc1plus/cp-tree.c1706
-rw-r--r--gnu/gcc2/cc1plus/cp-tree.def85
-rw-r--r--gnu/gcc2/cc1plus/cp-tree.h2006
-rw-r--r--gnu/gcc2/cc1plus/cp-type2.c1635
-rw-r--r--gnu/gcc2/cc1plus/cp-typeck.c6374
-rw-r--r--gnu/gcc2/cc1plus/cp-xref.c825
-rw-r--r--gnu/gcc2/cc1plus/stack.h41
31 files changed, 0 insertions, 65347 deletions
diff --git a/gnu/gcc2/cc1plus/Makefile b/gnu/gcc2/cc1plus/Makefile
deleted file mode 100644
index 2d7210fbb832..000000000000
--- a/gnu/gcc2/cc1plus/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-PROG= gcc1plus
-BINDIR= /usr/libexec
-SRCS= cp-parse.c cp-decl.c cp-decl2.c cp-typeck.c cp-type2.c \
- cp-tree.c cp-ptree.c cp-cvt.c cp-search.c cp-lex.c \
- cp-gc.c cp-call.c cp-class.c cp-init.c cp-method.c \
- cp-except.c cp-expr.c cp-pt.c cp-edsel.c cp-xref.c \
- cp-spew.c
-
-CFLAGS+= -I. -I$(.CURDIR) -I$(.CURDIR)/../lib
-NOMAN= noman
-YFLAGS=
-
-.if exists(${.CURDIR}/../lib/obj)
-LDADD= -L${.CURDIR}/../lib/obj -lgcc2
-DPADD= ${.CURDIR}../lib/obj/libgcc2.a
-.else
-LDADD= -L${.CURDIR}/../lib/ -lgcc2
-DPADD= ${.CURDIR}../lib/libgcc2.a
-.endif
-
-LDADD+= -lgnumalloc
-DPADD+= ${LIBGNUMALLOC}
-
-.include <bsd.prog.mk>
diff --git a/gnu/gcc2/cc1plus/cp-call.c b/gnu/gcc2/cc1plus/cp-call.c
deleted file mode 100644
index b0650cad5661..000000000000
--- a/gnu/gcc2/cc1plus/cp-call.c
+++ /dev/null
@@ -1,2823 +0,0 @@
-/* Functions related to invoking methods and overloaded functions.
- Copyright (C) 1987, 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. */
-
-
-/* High-level class interface. */
-
-#include "config.h"
-#include "tree.h"
-#include <stdio.h>
-#include "cp-tree.h"
-#include "flags.h"
-
-#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-extern void sorry ();
-
-extern int inhibit_warnings;
-extern int flag_assume_nonnull_objects;
-extern tree ctor_label, dtor_label;
-
-/* From cp-typeck.c: */
-extern tree unary_complex_lvalue ();
-
-/* Compute the ease with which a conversion can be performed
- between an expected and the given type. */
-static int convert_harshness ();
-
-#define EVIL_HARSHNESS(ARG) ((ARG) & 1)
-#define ELLIPSIS_HARSHNESS(ARG) ((ARG) & 2)
-#define USER_HARSHNESS(ARG) ((ARG) & 4)
-#define CONTRAVARIANT_HARSHNESS(ARG) ((ARG) & 8)
-#define BASE_DERIVED_HARSHNESS(ARG) ((ARG) & 16)
-#define INT_TO_BD_HARSHNESS(ARG) (((ARG) << 5) | 16)
-#define INT_FROM_BD_HARSHNESS(ARG) ((ARG) >> 5)
-#define INT_TO_EASY_HARSHNESS(ARG) ((ARG) << 5)
-#define INT_FROM_EASY_HARSHNESS(ARG) ((ARG) >> 5)
-#define ONLY_EASY_HARSHNESS(ARG) (((ARG) & 31) == 0)
-#define CONST_HARSHNESS(ARG) ((ARG) & 2048)
-
-/* Ordering function for overload resolution. */
-int
-rank_for_overload (x, y)
- struct candidate *x, *y;
-{
- if (y->evil - x->evil)
- return y->evil - x->evil;
- if (CONST_HARSHNESS (y->harshness[0]) ^ CONST_HARSHNESS (x->harshness[0]))
- return y->harshness[0] - x->harshness[0];
- if (y->ellipsis - x->ellipsis)
- return y->ellipsis - x->ellipsis;
- if (y->user - x->user)
- return y->user - x->user;
- if (y->b_or_d - x->b_or_d)
- return y->b_or_d - x->b_or_d;
- return y->easy - x->easy;
-}
-
-/* TYPE is the type we wish to convert to. PARM is the parameter
- we have to work with. We use a somewhat arbitrary cost function
- to measure this conversion. */
-static int
-convert_harshness (type, parmtype, parm)
- register tree type, parmtype;
- tree parm;
-{
- register enum tree_code codel = TREE_CODE (type);
- register enum tree_code coder = TREE_CODE (parmtype);
-
-#ifdef GATHER_STATISTICS
- n_convert_harshness++;
-#endif
-
- if (TYPE_MAIN_VARIANT (parmtype) == TYPE_MAIN_VARIANT (type))
- return 0;
-
- if (coder == ERROR_MARK)
- return 1;
-
- if (codel == POINTER_TYPE
- && (coder == METHOD_TYPE || coder == FUNCTION_TYPE))
- {
- tree p1, p2;
- int harshness, new_harshness;
-
- /* Get to the METHOD_TYPE or FUNCTION_TYPE that this might be. */
- type = TREE_TYPE (type);
-
- if (coder != TREE_CODE (type))
- return 1;
-
- harshness = 0;
-
- /* We allow the default conversion between function type
- and pointer-to-function type for free. */
- if (type == parmtype)
- return 0;
-
- /* Compare return types. */
- p1 = TREE_TYPE (type);
- p2 = TREE_TYPE (parmtype);
- new_harshness = convert_harshness (p1, p2, NULL_TREE);
- if (new_harshness & 1)
- return 1;
-
- if (BASE_DERIVED_HARSHNESS (new_harshness))
- {
- tree binfo;
-
- /* This only works for pointers. */
- if (TREE_CODE (p1) != POINTER_TYPE
- && TREE_CODE (p1) != REFERENCE_TYPE)
- return 1;
-
- p1 = TREE_TYPE (p1);
- p2 = TREE_TYPE (p2);
- if (CONTRAVARIANT_HARSHNESS (new_harshness))
- binfo = get_binfo (p2, p1, 0);
- else
- binfo = get_binfo (p1, p2, 0);
-
- if (! BINFO_OFFSET_ZEROP (binfo))
- {
- static int explained = 0;
- if (CONTRAVARIANT_HARSHNESS (new_harshness))
- message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p2, p1);
- else
- message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p1, p2);
-
- if (! explained++)
- sorry ("(because pointer values change during conversion)");
- return 1;
- }
- }
-
- harshness |= new_harshness;
-
- p1 = TYPE_ARG_TYPES (type);
- p2 = TYPE_ARG_TYPES (parmtype);
- while (p1 && TREE_VALUE (p1) != void_type_node
- && p2 && TREE_VALUE (p2) != void_type_node)
- {
- new_harshness = convert_harshness (TREE_VALUE (p1), TREE_VALUE (p2), NULL_TREE);
- if (EVIL_HARSHNESS (new_harshness))
- return 1;
-
- if (BASE_DERIVED_HARSHNESS (new_harshness))
- {
- /* This only works for pointers and references. */
- if (TREE_CODE (TREE_VALUE (p1)) != POINTER_TYPE
- && TREE_CODE (TREE_VALUE (p1)) != REFERENCE_TYPE)
- return 1;
- new_harshness ^= CONTRAVARIANT_HARSHNESS (new_harshness);
- harshness |= new_harshness;
- }
- /* This trick allows use to accumulate easy type
- conversions without messing up the bits that encode
- info about more involved things. */
- else if (ONLY_EASY_HARSHNESS (new_harshness))
- harshness += new_harshness;
- else
- harshness |= new_harshness;
- p1 = TREE_CHAIN (p1);
- p2 = TREE_CHAIN (p2);
- }
- if (p1 == p2)
- return harshness;
- if (p2)
- return p1 ? 1 : (harshness | ELLIPSIS_HARSHNESS (-1));
- if (p1)
- return harshness | (TREE_PURPOSE (p1) == NULL_TREE);
- }
- else if (codel == POINTER_TYPE && coder == OFFSET_TYPE)
- {
- /* XXX: Note this is set a few times, but it's never actually
- used! (bpk) */
- int harshness;
-
- /* Get to the OFFSET_TYPE that this might be. */
- type = TREE_TYPE (type);
-
- if (coder != TREE_CODE (type))
- return 1;
-
- harshness = 0;
-
- if (TYPE_OFFSET_BASETYPE (type) == TYPE_OFFSET_BASETYPE (parmtype))
- harshness = 0;
- else if (UNIQUELY_DERIVED_FROM_P (TYPE_OFFSET_BASETYPE (type),
- TYPE_OFFSET_BASETYPE (parmtype)))
- harshness = INT_TO_BD_HARSHNESS (1);
- else if (UNIQUELY_DERIVED_FROM_P (TYPE_OFFSET_BASETYPE (parmtype),
- TYPE_OFFSET_BASETYPE (type)))
- harshness = CONTRAVARIANT_HARSHNESS (-1);
- else
- return 1;
- /* Now test the OFFSET_TYPE's target compatibility. */
- type = TREE_TYPE (type);
- parmtype = TREE_TYPE (parmtype);
- }
-
- if (coder == UNKNOWN_TYPE)
- {
- if (codel == FUNCTION_TYPE
- || codel == METHOD_TYPE
- || (codel == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)))
- return 0;
- return 1;
- }
-
- if (coder == VOID_TYPE)
- return 1;
-
- if (codel == ENUMERAL_TYPE || codel == INTEGER_TYPE)
- {
- /* Control equivalence of ints an enums. */
-
- if (codel == ENUMERAL_TYPE
- && flag_int_enum_equivalence == 0)
- {
- /* Enums can be converted to ints, but not vice-versa. */
- if (coder != ENUMERAL_TYPE
- || TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (parmtype))
- return 1;
- }
-
- /* else enums and ints (almost) freely interconvert. */
-
- if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE)
- {
- int easy = TREE_UNSIGNED (type) ^ TREE_UNSIGNED (parmtype);
- if (codel != coder)
- easy += 1;
- if (TYPE_MODE (type) != TYPE_MODE (parmtype))
- easy += 2;
- return INT_TO_EASY_HARSHNESS (easy);
- }
- else if (coder == REAL_TYPE)
- return INT_TO_EASY_HARSHNESS (4);
- }
-
- if (codel == REAL_TYPE)
- if (coder == REAL_TYPE)
- /* Shun converting between float and double if a choice exists. */
- {
- if (TYPE_MODE (type) != TYPE_MODE (parmtype))
- return INT_TO_EASY_HARSHNESS (2);
- return 0;
- }
- else if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE)
- return INT_TO_EASY_HARSHNESS (4);
-
- /* convert arrays which have not previously been converted. */
- if (codel == ARRAY_TYPE)
- codel = POINTER_TYPE;
- if (coder == ARRAY_TYPE)
- coder = POINTER_TYPE;
-
- /* Conversions among pointers */
- if (codel == POINTER_TYPE && coder == POINTER_TYPE)
- {
- register tree ttl = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype));
- int penalty = 4 * (ttl != ttr);
- /* Anything converts to void *. void * converts to anything.
- Since these may be `const void *' (etc.) use VOID_TYPE
- instead of void_type_node.
- Otherwise, the targets must be the same,
- except that we do allow (at some cost) conversion
- between signed and unsinged pointer types. */
-
- if ((TREE_CODE (ttl) == METHOD_TYPE
- || TREE_CODE (ttl) == FUNCTION_TYPE)
- && TREE_CODE (ttl) == TREE_CODE (ttr))
- {
- if (comptypes (ttl, ttr, -1))
- return INT_TO_EASY_HARSHNESS (penalty);
- return 1;
- }
-
- if (!(TREE_CODE (ttl) == VOID_TYPE
- || TREE_CODE (ttr) == VOID_TYPE
- || (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (ttr)
- && (ttl = unsigned_type (ttl),
- ttr = unsigned_type (ttr),
- penalty = 10, 0))
- || (comp_target_types (ttl, ttr, 0))))
- return 1;
-
- if (penalty == 10)
- return INT_TO_EASY_HARSHNESS (10);
- if (ttr == ttl)
- return INT_TO_BD_HARSHNESS (0);
-
- if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
- {
- int b_or_d = get_base_distance (ttl, ttr, 0, 0);
- if (b_or_d < 0)
- {
- b_or_d = get_base_distance (ttr, ttl, 0, 0);
- if (b_or_d < 0)
- return 1;
- return CONTRAVARIANT_HARSHNESS (-1);
- }
- return INT_TO_BD_HARSHNESS (b_or_d);
- }
- /* If converting from a `class*' to a `void*', make it
- less favorable than any inheritance relationship. */
- if (TREE_CODE (ttl) == VOID_TYPE && IS_AGGR_TYPE (ttr))
- return INT_TO_BD_HARSHNESS (CLASSTYPE_MAX_DEPTH (ttr)+1);
- return INT_TO_EASY_HARSHNESS (penalty);
- }
-
- if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
- {
- /* This is not a bad match, but don't let it beat
- integer-enum combinations. */
- if (parm && integer_zerop (parm))
- return INT_TO_EASY_HARSHNESS (4);
- }
-
- /* C++: one of the types must be a reference type. */
- {
- tree ttl, ttr;
- register tree intype = TYPE_MAIN_VARIANT (parmtype);
- register enum tree_code form = TREE_CODE (intype);
- int penalty;
-
- if (codel == REFERENCE_TYPE || coder == REFERENCE_TYPE)
- {
- ttl = TYPE_MAIN_VARIANT (type);
-
- if (codel == REFERENCE_TYPE)
- {
- ttl = TREE_TYPE (ttl);
-
- /* When passing a non-const argument into a const reference,
- dig it a little, so a non-const reference is preferred over
- this one. (mrs) */
- if (parm && TREE_READONLY (ttl) && ! TREE_READONLY (parm))
- penalty = 2;
- else
- penalty = 0;
-
- ttl = TYPE_MAIN_VARIANT (ttl);
-
- if (form == OFFSET_TYPE)
- {
- intype = TREE_TYPE (intype);
- form = TREE_CODE (intype);
- }
-
- if (form == REFERENCE_TYPE)
- {
- intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype));
-
- if (ttl == intype)
- return 0;
- penalty = 2;
- }
- else
- {
- /* Can reference be built up? */
- if (ttl == intype && penalty == 0) {
- /* Because the READONLY bits and VOLATILE bits are not
- always in the type, this extra check is necessary. The
- problem should be fixed someplace else, and this extra
- code removed.
-
- Also, if type if a reference, the readonly bits could
- either be in the outer type (with reference) or on the
- inner type (the thing being referenced). (mrs) */
- if (parm
- && ((TREE_READONLY (parm)
- && ! (TYPE_READONLY (type)
- || (TREE_CODE (type) == REFERENCE_TYPE
- && TYPE_READONLY (TREE_TYPE (type)))))
- || (TREE_SIDE_EFFECTS (parm)
- && ! (TYPE_VOLATILE (type)
- || (TREE_CODE (type) == REFERENCE_TYPE
- && TYPE_VOLATILE (TREE_TYPE (type)))))))
-
- penalty = 2;
- else
- return 0;
- }
- else
- penalty = 2;
- }
- }
- else if (form == REFERENCE_TYPE)
- {
- if (parm)
- {
- tree tmp = convert_from_reference (parm);
- intype = TYPE_MAIN_VARIANT (TREE_TYPE (tmp));
- }
- else
- {
- intype = parmtype;
- do
- {
- intype = TREE_TYPE (intype);
- }
- while (TREE_CODE (intype) == REFERENCE_TYPE);
- intype = TYPE_MAIN_VARIANT (intype);
- }
-
- if (ttl == intype)
- return 0;
- else
- penalty = 2;
- }
-
- if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
- {
- ttl = unsigned_type (ttl);
- intype = unsigned_type (intype);
- penalty += 2;
- }
-
- ttr = intype;
-
- /* If the initializer is not an lvalue, then it does not
- matter if we make life easier for the programmer
- by creating a temporary variable with which to
- hold the result. */
- if (parm && (coder == INTEGER_TYPE
- || coder == ENUMERAL_TYPE
- || coder == REAL_TYPE)
- && ! lvalue_p (parm))
- return (convert_harshness (ttl, ttr, NULL_TREE)
- | INT_TO_EASY_HARSHNESS (penalty));
-
- if (ttl == ttr)
- {
- if (penalty)
- return INT_TO_EASY_HARSHNESS (penalty);
- return INT_TO_BD_HARSHNESS (0);
- }
-
- /* Pointers to voids always convert for pointers. But
- make them less natural than more specific matches. */
- if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)
- if (TREE_TYPE (ttl) == void_type_node
- || TREE_TYPE (ttr) == void_type_node)
- return INT_TO_EASY_HARSHNESS (penalty+1);
-
- if (parm && codel != REFERENCE_TYPE)
- return (convert_harshness (ttl, ttr, NULL_TREE)
- | INT_TO_EASY_HARSHNESS (penalty));
-
- /* Here it does matter. If this conversion is from
- derived to base, allow it. Otherwise, types must
- be compatible in the strong sense. */
- if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
- {
- int b_or_d = get_base_distance (ttl, ttr, 0, 0);
- if (b_or_d < 0)
- {
- b_or_d = get_base_distance (ttr, ttl, 0, 0);
- if (b_or_d < 0)
- return 1;
- return CONTRAVARIANT_HARSHNESS (-1);
- }
- /* Say that this conversion is relatively painless.
- If it turns out that there is a user-defined X(X&)
- constructor, then that will be invoked, but that's
- preferable to dealing with other user-defined conversions
- that may produce surprising results. */
- return INT_TO_BD_HARSHNESS (b_or_d);
- }
-
- if (comp_target_types (ttl, intype, 1))
- return INT_TO_EASY_HARSHNESS (penalty);
- }
- }
- if (codel == RECORD_TYPE && coder == RECORD_TYPE)
- {
- int b_or_d = get_base_distance (type, parmtype, 0, 0);
- if (b_or_d < 0)
- {
- b_or_d = get_base_distance (parmtype, type, 0, 0);
- if (b_or_d < 0)
- return 1;
- return CONTRAVARIANT_HARSHNESS (-1);
- }
- return INT_TO_BD_HARSHNESS (b_or_d);
- }
- return 1;
-}
-
-/* Algorithm: Start out with no strikes against. For each argument
- which requires a (subjective) hard conversion (such as between
- floating point and integer), issue a strike. If there are the same
- number of formal and actual parameters in the list, there will be at
- least on strike, otherwise an exact match would have been found. If
- there are not the same number of arguments in the type lists, we are
- not dead yet: a `...' means that we can have more parms then were
- declared, and if we wind up in the default argument section of the
- list those can be used as well. If an exact match could be found for
- one of those cases, return it immediately. Otherwise, rank the fields
- so that fields with fewer strikes are tried first.
-
- Conversions between builtin and user-defined types are allowed, but
- no function involving such a conversion is preferred to one which
- does not require such a conversion. Furthermore, such conversions
- must be unique. */
-
-void
-compute_conversion_costs (function, tta_in, cp, arglen)
- tree function;
- tree tta_in;
- struct candidate *cp;
- int arglen;
-{
- tree ttf_in = TYPE_ARG_TYPES (TREE_TYPE (function));
- tree ttf = ttf_in;
- tree tta = tta_in;
-
- /* Start out with no strikes against. */
- int evil_strikes = 0;
- int ellipsis_strikes = 0;
- int user_strikes = 0;
- int b_or_d_strikes = 0;
- int easy_strikes = 0;
-
- int strike_index = 0, win, lose;
-
-#ifdef GATHER_STATISTICS
- n_compute_conversion_costs++;
-#endif
-
- cp->function = function;
- cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE;
- cp->u.bad_arg = 0; /* optimistic! */
-
- bzero (cp->harshness, (arglen+1) * sizeof (short));
-
- while (ttf && tta)
- {
- int harshness;
-
- if (ttf == void_list_node)
- break;
-
- if (type_unknown_p (TREE_VALUE (tta)))
- {
- /* Must perform some instantiation here. */
- tree rhs = TREE_VALUE (tta);
- tree lhstype = TREE_VALUE (ttf);
-
- /* Keep quiet about possible contravariance violations. */
- int old_inhibit_warnings = inhibit_warnings;
- inhibit_warnings = 1;
-
- /* @@ This is to undo what `grokdeclarator' does to
- parameter types. It really should go through
- something more general. */
-
- TREE_TYPE (tta) = unknown_type_node;
- rhs = instantiate_type (lhstype, rhs, 0);
- inhibit_warnings = old_inhibit_warnings;
-
- if (TREE_CODE (rhs) == ERROR_MARK)
- harshness = 1;
- else
- {
- harshness = convert_harshness (lhstype, TREE_TYPE (rhs), rhs);
- /* harshness |= 2; */
- }
- }
- else
- harshness = convert_harshness (TREE_VALUE (ttf), TREE_TYPE (TREE_VALUE (tta)), TREE_VALUE (tta));
-
- cp->harshness[strike_index] = harshness;
- if (EVIL_HARSHNESS (harshness)
- || CONTRAVARIANT_HARSHNESS (harshness))
- {
- cp->u.bad_arg = strike_index;
- evil_strikes = 1;
- }
- else if (ELLIPSIS_HARSHNESS (harshness))
- {
- ellipsis_strikes += 1;
- }
-#if 0
- /* This is never set by `convert_harshness'. */
- else if (USER_HARSHNESS (harshness))
- {
- user_strikes += 1;
- }
-#endif
- else if (BASE_DERIVED_HARSHNESS (harshness))
- {
- b_or_d_strikes += INT_FROM_BD_HARSHNESS (harshness);
- }
- else
- easy_strikes += INT_FROM_EASY_HARSHNESS (harshness);
- ttf = TREE_CHAIN (ttf);
- tta = TREE_CHAIN (tta);
- strike_index += 1;
- }
-
- if (tta)
- {
- /* ran out of formals, and parmlist is fixed size. */
- if (ttf /* == void_type_node */)
- {
- cp->evil = 1;
- cp->u.bad_arg = -1;
- return;
- }
- }
- else if (ttf && ttf != void_list_node)
- {
- /* ran out of actuals, and no defaults. */
- if (TREE_PURPOSE (ttf) == NULL_TREE)
- {
- cp->evil = 1;
- cp->u.bad_arg = -2;
- return;
- }
- /* Store index of first default. */
- cp->harshness[arglen] = strike_index+1;
- }
- else cp->harshness[arglen] = 0;
-
- /* Argument list lengths work out, so don't need to check them again. */
- if (evil_strikes)
- {
- /* We do not check for derived->base conversions here, since in
- no case would they give evil strike counts, unless such conversions
- are somehow ambiguous. */
-
- /* See if any user-defined conversions apply.
- But make sure that we do not loop. */
- static int dont_convert_types = 0;
-
- if (dont_convert_types)
- {
- cp->evil = 1;
- return;
- }
-
- win = 0; /* Only get one chance to win. */
- ttf = TYPE_ARG_TYPES (TREE_TYPE (function));
- tta = tta_in;
- strike_index = 0;
- evil_strikes = 0;
-
- while (ttf && tta)
- {
- if (ttf == void_list_node)
- break;
-
- lose = cp->harshness[strike_index];
- if (EVIL_HARSHNESS (lose)
- || CONTRAVARIANT_HARSHNESS (lose))
- {
- tree actual_type = TREE_TYPE (TREE_VALUE (tta));
- tree formal_type = TREE_VALUE (ttf);
-
- dont_convert_types = 1;
-
- if (TREE_CODE (formal_type) == REFERENCE_TYPE)
- formal_type = TREE_TYPE (formal_type);
- if (TREE_CODE (actual_type) == REFERENCE_TYPE)
- actual_type = TREE_TYPE (actual_type);
-
- if (formal_type != error_mark_node
- && actual_type != error_mark_node)
- {
- formal_type = TYPE_MAIN_VARIANT (formal_type);
- actual_type = TYPE_MAIN_VARIANT (actual_type);
-
- if (TYPE_HAS_CONSTRUCTOR (formal_type))
- {
- /* If it has a constructor for this type, try to use it. */
- if (convert_to_aggr (formal_type, TREE_VALUE (tta), 0, 1)
- != error_mark_node)
- {
- /* @@ There is no way to save this result yet.
- @@ So success is NULL_TREE for now. */
- win++;
- }
- }
- if (TYPE_LANG_SPECIFIC (actual_type) && TYPE_HAS_CONVERSION (actual_type))
- {
- if (TREE_CODE (formal_type) == INTEGER_TYPE
- && TYPE_HAS_INT_CONVERSION (actual_type))
- win++;
- else if (TREE_CODE (formal_type) == REAL_TYPE
- && TYPE_HAS_REAL_CONVERSION (actual_type))
- win++;
- else
- {
- tree conv = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0);
- if (conv)
- {
- if (conv == error_mark_node)
- win += 2;
- else
- win++;
- }
- else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE)
- {
- conv = build_type_conversion (CALL_EXPR, formal_type, TREE_VALUE (tta), 0);
- if (conv)
- {
- if (conv == error_mark_node)
- win += 2;
- else
- win++;
- }
- }
- }
- }
- }
- dont_convert_types = 0;
-
- if (win == 1)
- {
- user_strikes += 1;
- cp->harshness[strike_index] = USER_HARSHNESS (-1);
- win = 0;
- }
- else
- {
- if (cp->u.bad_arg > strike_index)
- cp->u.bad_arg = strike_index;
-
- evil_strikes = win ? 2 : 1;
- break;
- }
- }
-
- ttf = TREE_CHAIN (ttf);
- tta = TREE_CHAIN (tta);
- strike_index += 1;
- }
- }
-
- /* Const member functions get a small penalty because defaulting
- to const is less useful than defaulting to non-const. */
- /* This is bogus, it does not correspond to anything in the ARM.
- This code will be fixed when this entire section is rewritten
- to conform to the ARM. (mrs) */
- if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
- {
- if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (ttf_in))))
- {
- cp->harshness[0] += INT_TO_EASY_HARSHNESS (1);
- ++easy_strikes;
- }
- else
- {
- /* Calling a non-const member function from a const member function
- is probably invalid, but for now we let it only draw a warning.
- We indicate that such a mismatch has occurred by setting the
- harshness to a maximum value. */
- if (TREE_CODE (TREE_TYPE (TREE_VALUE (tta_in))) == POINTER_TYPE
- && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (TREE_VALUE (tta_in))))))
- cp->harshness[0] |= CONST_HARSHNESS (-1);
- }
- }
-
- cp->evil = evil_strikes;
- cp->ellipsis = ellipsis_strikes;
- cp->user = user_strikes;
- cp->b_or_d = b_or_d_strikes;
- cp->easy = easy_strikes;
-}
-
-/* When one of several possible overloaded functions and/or methods
- can be called, choose the best candidate for overloading.
-
- BASETYPE is the context from which we start method resolution
- or NULL if we are comparing overloaded functions.
- CANDIDATES is the array of candidates we have to choose from.
- N_CANDIDATES is the length of CANDIDATES.
- PARMS is a TREE_LIST of parameters to the function we'll ultimately
- choose. It is modified in place when resolving methods. It is not
- modified in place when resolving overloaded functions.
- LEN is the length of the parameter list. */
-
-static struct candidate *
-ideal_candidate (basetype, candidates, n_candidates, parms, len)
- tree basetype;
- struct candidate *candidates;
- int n_candidates;
- tree parms;
- int len;
-{
- struct candidate *cp = candidates + n_candidates;
- int index, i;
- tree ttf;
-
- qsort (candidates, /* char *base */
- n_candidates, /* int nel */
- sizeof (struct candidate), /* int width */
- rank_for_overload); /* int (*compar)() */
-
- /* If the best candidate requires user-defined conversions,
- and its user-defined conversions are a strict subset
- of all other candidates requiring user-defined conversions,
- then it is, in fact, the best. */
- for (i = -1; cp + i != candidates; i--)
- if (cp[i].user == 0)
- break;
-
- if (i < -1)
- {
- tree ttf0;
-
- /* Check that every other candidate requires those conversions
- as a strict subset of their conversions. */
- if (cp[i].user == cp[-1].user)
- goto non_subset;
-
- /* Look at subset relationship more closely. */
- while (i != -1)
- {
- for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)),
- ttf0 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function)),
- index = 0;
- index < len;
- ttf = TREE_CHAIN (ttf), ttf0 = TREE_CHAIN (ttf0), index++)
- if (USER_HARSHNESS (cp[i].harshness[index]))
- {
- /* If our "best" candidate also needs a conversion,
- it must be the same one. */
- if (USER_HARSHNESS (cp[-1].harshness[index])
- && TREE_VALUE (ttf) != TREE_VALUE (ttf0))
- goto non_subset;
- }
- i++;
- }
- /* The best was the best. */
- return cp - 1;
- non_subset:
- /* Use other rules for determining "bestness". */
- ;
- }
-
- /* If the best two candidates we find require user-defined
- conversions, we may need to report and error message. */
- if (cp[-1].user && cp[-2].user
- && (cp[-1].b_or_d || cp[-2].b_or_d == 0))
- {
- /* If the best two methods found involved user-defined
- type conversions, then we must see whether one
- of them is exactly what we wanted. If not, then
- we have an ambiguity. */
- int best = 0;
- tree tta = parms;
- tree f1;
-#if 0
- /* for LUCID */
- tree p1;
-#endif
-
- /* Stash all of our parameters in safe places
- so that we can perform type conversions in place. */
- while (tta)
- {
- TREE_PURPOSE (tta) = TREE_VALUE (tta);
- tta = TREE_CHAIN (tta);
- }
-
- i = 0;
- do
- {
- int exact_conversions = 0;
-
- i -= 1;
- tta = parms;
- if (DECL_STATIC_FUNCTION_P (cp[i].function))
- tta = TREE_CHAIN (tta);
- /* special note, we don't go through len parameters, because we
- may only need len-1 parameters because of a call to a static
- member. */
- for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)), index = 0;
- tta;
- tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++)
- {
- if (USER_HARSHNESS (cp[i].harshness[index]))
- {
- tree this_parm = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_PURPOSE (tta), 2);
- if (basetype != NULL_TREE)
- TREE_VALUE (tta) = this_parm;
- if (this_parm)
- {
- if (TREE_CODE (this_parm) != CONVERT_EXPR
- && (TREE_CODE (this_parm) != NOP_EXPR
- || comp_target_types (TREE_TYPE (this_parm),
- TREE_TYPE (TREE_OPERAND (this_parm, 0)), 1)))
- exact_conversions += 1;
- }
- else if (PROMOTES_TO_AGGR_TYPE (TREE_VALUE (ttf), REFERENCE_TYPE))
- {
- /* To get here we had to have succeeded via
- a constructor. */
- TREE_VALUE (tta) = TREE_PURPOSE (tta);
- exact_conversions += 1;
- }
- }
- }
- if (exact_conversions == cp[i].user)
- {
- if (best == 0)
- {
- best = i;
- f1 = cp[best].function;
-#if 0
- /* For LUCID */
- p1 = TYPE_ARG_TYPES (TREE_TYPE (f1));
-#endif
- }
- else
- {
- /* Don't complain if next best is from base class. */
- tree f2 = cp[i].function;
-
- if (TREE_CODE (TREE_TYPE (f1)) == METHOD_TYPE
- && TREE_CODE (TREE_TYPE (f2)) == METHOD_TYPE
- && BASE_DERIVED_HARSHNESS (cp[i].harshness[0])
- && cp[best].harshness[0] < cp[i].harshness[0])
- {
-#if 0
- tree p2 = TYPE_ARG_TYPES (TREE_TYPE (f2));
- /* For LUCID. */
- if (! compparms (TREE_CHAIN (p1), TREE_CHAIN (p2), 1))
- goto ret0;
- else
-#endif
- continue;
- }
- else
- {
- /* Ensure that there's nothing ambiguous about these
- two fns. */
- int identical = 1;
- for (index = 0; index < len; index++)
- {
- /* Type conversions must be piecewise equivalent. */
- if (USER_HARSHNESS (cp[best].harshness[index])
- != USER_HARSHNESS (cp[i].harshness[index]))
- goto ret0;
- /* If there's anything we like better about the
- other function, consider it ambiguous. */
- if (cp[i].harshness[index] < cp[best].harshness[index])
- goto ret0;
- /* If any single one it diffent, then the whole is
- not identical. */
- if (cp[i].harshness[index] != cp[best].harshness[index])
- identical = 0;
- }
-
- /* If we can't tell the difference between the two, it
- is ambiguous. */
- if (identical)
- goto ret0;
-
- /* If we made it to here, it means we're satisfied that
- BEST is still best. */
- continue;
- }
- }
- }
- } while (cp + i != candidates);
-
- if (best)
- {
- int exact_conversions = cp[best].user;
- tta = parms;
- if (DECL_STATIC_FUNCTION_P (cp[best].function))
- tta = TREE_CHAIN (parms);
- for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[best].function)), index = 0;
- exact_conversions > 0;
- tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++)
- {
- if (USER_HARSHNESS (cp[best].harshness[index]))
- {
- /* We must now fill in the slot we left behind.
- @@ This could be optimized to use the value previously
- @@ computed by build_type_conversion in some cases. */
- if (basetype != NULL_TREE)
- TREE_VALUE (tta) = convert (TREE_VALUE (ttf), TREE_PURPOSE (tta));
- exact_conversions -= 1;
- }
- else TREE_VALUE (tta) = TREE_PURPOSE (tta);
- }
- return cp + best;
- }
- goto ret0;
- }
- /* If the best two candidates we find both use default parameters,
- we may need to report and error. Don't need to worry if next-best
- candidate is forced to use user-defined conversion when best is not. */
- if (cp[-2].user == 0
- && cp[-1].harshness[len] != 0 && cp[-2].harshness[len] != 0)
- {
- tree tt1 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function));
- tree tt2 = TYPE_ARG_TYPES (TREE_TYPE (cp[-2].function));
- unsigned i = cp[-1].harshness[len];
-
- if (cp[-2].harshness[len] < i)
- i = cp[-2].harshness[len];
- while (--i > 0)
- {
- if (TYPE_MAIN_VARIANT (TREE_VALUE (tt1))
- != TYPE_MAIN_VARIANT (TREE_VALUE (tt2)))
- /* These lists are not identical, so we can choose our best candidate. */
- return cp - 1;
- tt1 = TREE_CHAIN (tt1);
- tt2 = TREE_CHAIN (tt2);
- }
- /* To get here, both lists had the same parameters up to the defaults
- which were used. This is an ambiguous request. */
- goto ret0;
- }
-
- /* Otherwise, return our best candidate. Note that if we get candidates
- from independent base classes, we have an ambiguity, even if one
- argument list look a little better than another one. */
- if (cp[-1].b_or_d && basetype && TYPE_USES_MULTIPLE_INHERITANCE (basetype))
- {
- int i = n_candidates - 1, best = i;
- tree base1 = NULL_TREE;
-
- if (TREE_CODE (TREE_TYPE (candidates[i].function)) == FUNCTION_TYPE)
- return cp - 1;
-
- for (; i >= 0 && candidates[i].user == 0 && candidates[i].evil == 0; i--)
- {
- if (TREE_CODE (TREE_TYPE (candidates[i].function)) == METHOD_TYPE)
- {
- tree newbase = DECL_CLASS_CONTEXT (candidates[i].function);
-
- if (base1 != NULL_TREE)
- {
- /* newbase could be a base or a parent of base1 */
- if (newbase != base1 && ! UNIQUELY_DERIVED_FROM_P (newbase, base1)
- && ! UNIQUELY_DERIVED_FROM_P (base1, newbase))
- {
- error_with_aggr_type (basetype, "ambiguous request for function from distinct base classes of type `%s'");
- error (" first candidate is `%s'",
- fndecl_as_string (0, candidates[best].function, 1));
- error (" second candidate is `%s'",
- fndecl_as_string (0, candidates[i].function, 1));
- cp[-1].evil = 1;
- return cp - 1;
- }
- }
- else
- {
- best = i;
- base1 = newbase;
- }
- }
- else return cp - 1;
- }
- }
-
- /* Don't accept a candidate as being ideal if it's indistinguishable
- from another candidate. */
- if (rank_for_overload (cp-1, cp-2) == 0)
- {
- /* If the types are distinguishably different (like
- `long' vs. `unsigned long'), that's ok. But if they are arbitrarily
- different, such as `int (*)(void)' vs. `void (*)(int)',
- that's not ok. */
- tree p1 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function));
- tree p2 = TYPE_ARG_TYPES (TREE_TYPE (cp[-2].function));
- while (p1 && p2)
- {
- if (TREE_CODE (TREE_VALUE (p1)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_VALUE (p1))) == FUNCTION_TYPE
- && TREE_VALUE (p1) != TREE_VALUE (p2))
- return 0;
- p1 = TREE_CHAIN (p1);
- p2 = TREE_CHAIN (p2);
- }
- if (p1 || p2)
- return 0;
- }
-
- return cp - 1;
-
- ret0:
- /* In the case where there is no ideal candidate, restore
- TREE_VALUE slots of PARMS from TREE_PURPOSE slots. */
- while (parms)
- {
- TREE_VALUE (parms) = TREE_PURPOSE (parms);
- parms = TREE_CHAIN (parms);
- }
- return 0;
-}
-
-/* Assume that if the class referred to is not in the
- current class hierarchy, that it may be remote.
- PARENT is assumed to be of aggregate type here. */
-static int
-may_be_remote (parent)
- tree parent;
-{
- if (TYPE_OVERLOADS_METHOD_CALL_EXPR (parent) == 0)
- return 0;
-
- if (current_class_type == NULL_TREE)
- return 0;
- if (parent == current_class_type)
- return 0;
-
- if (UNIQUELY_DERIVED_FROM_P (parent, current_class_type))
- return 0;
- return 1;
-}
-
-tree
-build_vfield_ref (datum, type)
- tree datum, type;
-{
- tree rval;
- int old_assume_nonnull_objects = flag_assume_nonnull_objects;
-
- if (datum == error_mark_node)
- return error_mark_node;
-
- /* Vtable references are always made from non-null objects. */
- flag_assume_nonnull_objects = 1;
- if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
- datum = convert_from_reference (datum);
-
- if (! TYPE_USES_COMPLEX_INHERITANCE (type))
- rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)),
- datum, CLASSTYPE_VFIELD (type));
- else
- rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), 0, 0);
- flag_assume_nonnull_objects = old_assume_nonnull_objects;
-
- return rval;
-}
-
-/* Build a call to a member of an object. I.e., one that overloads
- operator ()(), or is a pointer-to-function or pointer-to-method. */
-static tree
-build_field_call (basetype_path, instance_ptr, name, parms, err_name)
- tree basetype_path;
- tree instance_ptr, name, parms;
- char *err_name;
-{
- tree field, instance;
-
- if (instance_ptr == current_class_decl)
- {
- /* Check to see if we really have a reference to an instance variable
- with `operator()()' overloaded. */
- field = IDENTIFIER_CLASS_VALUE (name);
-
- if (field == NULL_TREE)
- {
- error ("`this' has no member named `%s'", err_name);
- return error_mark_node;
- }
-
- if (TREE_CODE (field) == FIELD_DECL)
- {
- /* If it's a field, try overloading operator (),
- or calling if the field is a pointer-to-function. */
- instance = build_component_ref_1 (C_C_D, field, 0);
- if (instance == error_mark_node)
- return error_mark_node;
-
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance))
- && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance)))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE);
-
- if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
- if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
- return build_function_call (instance, parms);
- else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE)
- return build_function_call (instance, tree_cons (NULL_TREE, current_class_decl, parms));
- }
- return NULL_TREE;
- }
-
- /* Check to see if this is not really a reference to an instance variable
- with `operator()()' overloaded. */
- field = lookup_field (basetype_path, name, 1, 0);
-
- /* This can happen if the reference was ambiguous
- or for visibility violations. */
- if (field == error_mark_node)
- return error_mark_node;
- if (field)
- {
- tree basetype;
- tree ftype = TREE_TYPE (field);
-
- if (TYPE_LANG_SPECIFIC (ftype) && TYPE_OVERLOADS_CALL_EXPR (ftype))
- {
- /* Make the next search for this field very short. */
- basetype = DECL_FIELD_CONTEXT (field);
- instance_ptr = convert_pointer_to (basetype, instance_ptr);
-
- instance = build_indirect_ref (instance_ptr, NULL);
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
- build_component_ref_1 (instance, field, 0),
- parms, NULL_TREE);
- }
- if (TREE_CODE (ftype) == POINTER_TYPE)
- {
- if (TREE_CODE (TREE_TYPE (ftype)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (ftype)) == METHOD_TYPE)
- {
- /* This is a member which is a pointer to function. */
- tree ref
- = build_component_ref_1 (build_indirect_ref (instance_ptr,
- NULL),
- field, LOOKUP_COMPLAIN);
- if (ref == error_mark_node)
- return error_mark_node;
- return build_function_call (ref, parms);
- }
- }
- else if (TREE_CODE (ftype) == METHOD_TYPE)
- {
- error ("invalid call via pointer-to-member function");
- return error_mark_node;
- }
- else
- return NULL_TREE;
- }
- return NULL_TREE;
-}
-
-tree
-find_scoped_type (type, inner_name, inner_types)
- tree type, inner_name, inner_types;
-{
- tree tags = CLASSTYPE_TAGS (type);
-
- while (tags)
- {
- /* The TREE_PURPOSE of an enum tag (which becomes a member of the
- enclosing class) is set to the name for the enum type. So, if
- inner_name is `bar', and we strike `baz' for `enum bar { baz }',
- then this test will be true. */
- if (TREE_PURPOSE (tags) == inner_name)
- {
- if (inner_types == NULL_TREE)
- return DECL_NESTED_TYPENAME (TYPE_NAME (TREE_VALUE (tags)));
- return resolve_scope_to_name (TREE_VALUE (tags), inner_types);
- }
- tags = TREE_CHAIN (tags);
- }
-
- /* Look for a TYPE_DECL. */
- for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags))
- if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name)
- {
- /* Code by raeburn. */
- if (inner_types == NULL_TREE)
- return DECL_NESTED_TYPENAME (tags);
- return resolve_scope_to_name (TREE_TYPE (tags), inner_types);
- }
-
- return NULL_TREE;
-}
-
-/* Resolve an expression NAME1::NAME2::...::NAMEn to
- the name that names the above nested type. INNER_TYPES
- is a chain of nested type names (held together by SCOPE_REFs);
- OUTER_TYPE is the type we know to enclose INNER_TYPES.
- Returns NULL_TREE if there is an error. */
-tree
-resolve_scope_to_name (outer_type, inner_types)
- tree outer_type, inner_types;
-{
- register tree tmp;
- tree inner_name;
-
- if (outer_type == NULL_TREE && current_class_type != NULL_TREE)
- {
- /* We first try to look for a nesting in our current class context,
- then try any enclosing classes. */
- tree type = current_class_type;
-
- while (type && (TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE))
- {
- tree rval = resolve_scope_to_name (type, inner_types);
-
- if (rval != NULL_TREE)
- return rval;
- type = DECL_CONTEXT (TYPE_NAME (type));
- }
- }
-
- if (TREE_CODE (inner_types) == SCOPE_REF)
- {
- inner_name = TREE_OPERAND (inner_types, 0);
- inner_types = TREE_OPERAND (inner_types, 1);
- }
- else
- {
- inner_name = inner_types;
- inner_types = NULL_TREE;
- }
-
- if (outer_type == NULL_TREE)
- {
- /* If we have something that's already a type by itself,
- use that. */
- if (IDENTIFIER_HAS_TYPE_VALUE (inner_name))
- {
- if (inner_types)
- return resolve_scope_to_name (IDENTIFIER_TYPE_VALUE (inner_name),
- inner_types);
- return inner_name;
- }
- return NULL_TREE;
- }
-
- if (! IS_AGGR_TYPE (outer_type))
- return NULL_TREE;
-
- /* Look for member classes or enums. */
- tmp = find_scoped_type (outer_type, inner_name, inner_types);
-
- /* If it's not a type in this class, then go down into the
- base classes and search there. */
- if (! tmp && TYPE_BINFO (outer_type))
- {
- tree binfos = TYPE_BINFO_BASETYPES (outer_type);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tmp = find_scoped_type (BINFO_TYPE (base_binfo),
- inner_name, inner_types);
- if (tmp)
- return tmp;
- }
- tmp = NULL_TREE;
- }
-
- return tmp;
-}
-
-/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
- This is how virtual function calls are avoided. */
-tree
-build_scoped_method_call (exp, scopes, name, parms)
- tree exp;
- tree scopes;
- tree name;
- tree parms;
-{
- /* Because this syntactic form does not allow
- a pointer to a base class to be `stolen',
- we need not protect the derived->base conversion
- that happens here.
-
- @@ But we do have to check visibility privileges later. */
- tree basename = resolve_scope_to_name (NULL_TREE, scopes);
- tree basetype, binfo, decl;
- tree type = TREE_TYPE (exp);
-
- if (type == error_mark_node
- || basename == NULL_TREE
- || ! is_aggr_typedef (basename, 1))
- return error_mark_node;
-
- if (! IS_AGGR_TYPE (type))
- {
- error ("base object of scoped method call is not of aggregate type");
- return error_mark_node;
- }
-
- basetype = IDENTIFIER_TYPE_VALUE (basename);
-
- if (binfo = binfo_or_else (basetype, type))
- {
- if (binfo == error_mark_node)
- return error_mark_node;
- if (TREE_CODE (exp) == INDIRECT_REF)
- decl = build_indirect_ref (convert_pointer_to (binfo,
- build_unary_op (ADDR_EXPR, exp, 0)), NULL);
- else
- decl = build_scoped_ref (exp, scopes);
-
- /* Call to a destructor. */
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- /* Explicit call to destructor. */
- name = TREE_OPERAND (name, 0);
- if (! is_aggr_typedef (name, 1))
- return error_mark_node;
- if (TREE_TYPE (decl) != IDENTIFIER_TYPE_VALUE (name))
- {
- error_with_aggr_type (TREE_TYPE (decl),
- "qualified type `%s' does not match destructor type `%s'",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
- error_with_aggr_type (TREE_TYPE (decl), "type `%s' has no destructor");
- return build_delete (TREE_TYPE (decl), decl, integer_two_node,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
- 0, 0);
- }
-
- /* Call to a method. */
- return build_method_call (decl, name, parms, NULL_TREE,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
- }
- return error_mark_node;
-}
-
-/* Build something of the form ptr->method (args)
- or object.method (args). This can also build
- calls to constructors, and find friends.
-
- Member functions always take their class variable
- as a pointer.
-
- INSTANCE is a class instance.
-
- NAME is the NAME field of the struct, union, or class
- whose type is that of INSTANCE.
-
- PARMS help to figure out what that NAME really refers to.
-
- BASETYPE_PATH, if non-NULL, tells which basetypes of INSTANCE
- we should be traversed before starting our search. We need
- this information to get protected accesses correct.
-
- FLAGS is the logical disjunction of zero or more LOOKUP_
- flags. See cp-tree.h for more info.
-
- If this is all OK, calls build_function_call with the resolved
- member function.
-
- This function must also handle being called to perform
- initialization, promotion/coercion of arguments, and
- instantiation of default parameters.
-
- Note that NAME may refer to an instance variable name. If
- `operator()()' is defined for the type of that field, then we return
- that result. */
-tree
-build_method_call (instance, name, parms, basetype_path, flags)
- tree instance, name, parms, basetype_path;
- int flags;
-{
- register tree function, fntype, value_type;
- register tree basetype, save_basetype;
- register tree baselink, result, method_name, parmtypes, parm;
- tree last;
- int pass;
- enum visibility_type visibility;
-
- /* Range of cases for vtable optimization. */
- enum vtable_needs { not_needed, maybe_needed, unneeded, needed };
- enum vtable_needs need_vtbl = not_needed;
-
- char *err_name;
- char *name_kind;
- int ever_seen = 0;
- tree instance_ptr = NULL_TREE;
- int all_virtual = flag_all_virtual;
- int static_call_context = 0;
- tree saw_private = NULL_TREE;
- tree saw_protected = NULL_TREE;
-
- /* Keep track of `const' and `volatile' objects. */
- int constp, volatilep;
-
-#ifdef GATHER_STATISTICS
- n_build_method_call++;
-#endif
-
- if (instance == error_mark_node
- || name == error_mark_node
- || parms == error_mark_node
- || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
- return error_mark_node;
-
- /* This is the logic that magically deletes the second argument to
- operator delete, if it is not needed. */
- if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2)
- {
- tree save_last = TREE_CHAIN (parms);
- tree result;
- /* get rid of unneeded argument */
- TREE_CHAIN (parms) = NULL_TREE;
- result = build_method_call (instance, name, parms, basetype_path,
- (LOOKUP_SPECULATIVELY|flags)
- &~LOOKUP_COMPLAIN);
- /* If it works, return it. */
- if (result && result != error_mark_node)
- return build_method_call (instance, name, parms, basetype_path, flags);
- /* If it doesn't work, two argument delete must work */
- TREE_CHAIN (parms) = save_last;
- }
-
-#if 0
- /* C++ 2.1 does not allow this, but ANSI probably will. */
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- error ("invalid call to destructor, use qualified name `%s::~%s'",
- IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
-#else
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- flags |= LOOKUP_DESTRUCTOR;
- name = TREE_OPERAND (name, 0);
- if (! is_aggr_typedef (name, 1))
- return error_mark_node;
- if (parms)
- error ("destructors take no parameters");
- basetype = IDENTIFIER_TYPE_VALUE (name);
- if (! TYPE_HAS_DESTRUCTOR (basetype))
- {
-#if 0 /* ARM says tp->~T() without T::~T() is valid. */
- error_with_aggr_type (basetype, "type `%s' has no destructor");
-#endif
- /* A destructive destructor wouldn't be a bad idea, but let's
- not bother for now. */
- return build_c_cast (void_type_node, instance);
- }
- instance = default_conversion (instance);
- if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
- instance_ptr = instance;
- else
- instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
- return build_delete (build_pointer_type (basetype),
- instance_ptr, integer_two_node,
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0);
- }
-#endif
-
- /* Initialize name for error reporting. */
- if (IDENTIFIER_TYPENAME_P (name))
- err_name = "type conversion operator";
- else if (IDENTIFIER_OPNAME_P (name))
- {
- char *p = operator_name_string (name);
- err_name = (char *)alloca (strlen (p) + 10);
- sprintf (err_name, "operator %s", p);
- }
- else if (TREE_CODE (name) == SCOPE_REF)
- err_name = IDENTIFIER_POINTER (TREE_OPERAND (name, 1));
- else
- err_name = IDENTIFIER_POINTER (name);
-
- if (IDENTIFIER_OPNAME_P (name))
- GNU_xref_call (current_function_decl, IDENTIFIER_POINTER (name));
- else
- GNU_xref_call (current_function_decl, err_name);
-
- if (instance == NULL_TREE)
- {
- basetype = NULL_TREE;
- /* Check cases where this is really a call to raise
- an exception. */
- if (current_class_type && TREE_CODE (name) == IDENTIFIER_NODE)
- {
- basetype = purpose_member (name, CLASSTYPE_TAGS (current_class_type));
- if (basetype)
- basetype = TREE_VALUE (basetype);
- }
- else if (TREE_CODE (name) == SCOPE_REF
- && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
- {
- if (! is_aggr_typedef (TREE_OPERAND (name, 0), 1))
- return error_mark_node;
- basetype = purpose_member (TREE_OPERAND (name, 1),
- CLASSTYPE_TAGS (IDENTIFIER_TYPE_VALUE (TREE_OPERAND (name, 0))));
- if (basetype)
- basetype = TREE_VALUE (basetype);
- }
-
- if (basetype != NULL_TREE)
- ;
- /* call to a constructor... */
- else if (IDENTIFIER_HAS_TYPE_VALUE (name))
- {
- basetype = IDENTIFIER_TYPE_VALUE (name);
- name = constructor_name (basetype);
- }
- else
- {
- tree typedef_name = lookup_name (name, 1);
- if (typedef_name && TREE_CODE (typedef_name) == TYPE_DECL)
- {
- /* Canonicalize the typedef name. */
- basetype = TREE_TYPE (typedef_name);
- name = TYPE_IDENTIFIER (basetype);
- }
- else
- {
- error ("no constructor named `%s' in visible scope",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- }
-
- if (! IS_AGGR_TYPE (basetype))
- {
- non_aggr_error:
- if ((flags & LOOKUP_COMPLAIN) && TREE_CODE (basetype) != ERROR_MARK)
- error ("request for member `%s' in something not a structure or union", err_name);
-
- return error_mark_node;
- }
- }
- else if (instance == C_C_D || instance == current_class_decl)
- {
- /* When doing initialization, we side-effect the TREE_TYPE of
- C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */
- basetype = TREE_TYPE (C_C_D);
-
- /* Anything manifestly `this' in constructors and destructors
- has a known type, so virtual function tables are not needed. */
- if (TYPE_VIRTUAL_P (basetype)
- && !(flags & LOOKUP_NONVIRTUAL))
- need_vtbl = (dtor_label || ctor_label)
- ? unneeded : maybe_needed;
-
- instance = C_C_D;
- instance_ptr = current_class_decl;
- result = build_field_call (TYPE_BINFO (current_class_type),
- instance_ptr, name, parms, err_name);
-
- if (result)
- return result;
- }
- else if (TREE_CODE (instance) == RESULT_DECL)
- {
- basetype = TREE_TYPE (instance);
- /* Should we ever have to make a virtual function reference
- from a RESULT_DECL, know that it must be of fixed type
- within the scope of this function. */
- if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
- need_vtbl = maybe_needed;
- instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance);
- }
- else if (instance == current_exception_object)
- {
- instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (current_exception_type),
- TREE_OPERAND (current_exception_object, 0));
- mark_addressable (TREE_OPERAND (current_exception_object, 0));
- result = build_field_call (TYPE_BINFO (current_exception_type),
- instance_ptr, name, parms, err_name);
- if (result)
- return result;
- error ("exception member `%s' cannot be invoked", err_name);
- return error_mark_node;
- }
- else
- {
- /* The MAIN_VARIANT of the type that `instance_ptr' winds up being. */
- tree inst_ptr_basetype;
-
- static_call_context = (TREE_CODE (instance) == NOP_EXPR
- && TREE_OPERAND (instance, 0) == error_mark_node);
-
- /* the base type of an instance variable is pointer to class */
- basetype = TREE_TYPE (instance);
-
- if (TREE_CODE (basetype) == REFERENCE_TYPE)
- {
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (basetype));
- if (! IS_AGGR_TYPE (basetype))
- goto non_aggr_error;
- /* Call to convert not needed because we are remaining
- within the same type. */
- instance_ptr = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), instance);
- inst_ptr_basetype = basetype;
- }
- else
- {
- if (TREE_CODE (basetype) == POINTER_TYPE)
- {
- basetype = TREE_TYPE (basetype);
- instance_ptr = instance;
- }
-
- if (! IS_AGGR_TYPE (basetype))
- goto non_aggr_error;
-
- if (! instance_ptr)
- {
- if ((lvalue_p (instance)
- && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0)))
- || (instance_ptr = unary_complex_lvalue (ADDR_EXPR, instance)))
- {
- if (instance_ptr == error_mark_node)
- return error_mark_node;
- }
- else if (TREE_CODE (instance) == NOP_EXPR
- || TREE_CODE (instance) == CONSTRUCTOR)
- {
- /* A cast is not an lvalue. Initialize a fresh temp
- with the value we are casting from, and proceed with
- that temporary. We can't cast to a reference type,
- so that simplifies the initialization to something
- we can manage. */
- tree temp = get_temp_name (TREE_TYPE (instance), 0);
- if (IS_AGGR_TYPE (TREE_TYPE (instance)))
- expand_aggr_init (temp, instance, 0);
- else
- {
- store_init_value (temp, instance);
- expand_decl_init (temp);
- }
- instance = temp;
- instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
- }
- else
- {
- if (TREE_CODE (instance) != CALL_EXPR)
- my_friendly_abort (125);
- if (TYPE_NEEDS_CONSTRUCTOR (basetype))
- instance = build_cplus_new (basetype, instance, 0);
- else
- {
- instance = get_temp_name (basetype, 0);
- TREE_ADDRESSABLE (instance) = 1;
- }
- instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
- }
- /* @@ Should we call comp_target_types here? */
- inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr));
- if (TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (inst_ptr_basetype))
- basetype = inst_ptr_basetype;
- else
- {
- instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr);
- if (instance_ptr == error_mark_node)
- return error_mark_node;
- }
- }
- else
- inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr));
- }
-
- if (basetype_path == NULL_TREE)
- basetype_path = TYPE_BINFO (inst_ptr_basetype);
-
- result = build_field_call (basetype_path, instance_ptr, name, parms, err_name);
- if (result)
- return result;
-
- if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
- {
- if (TREE_SIDE_EFFECTS (instance_ptr))
- {
- /* This action is needed because the instance is needed
- for providing the base of the virtual function table.
- Without using a SAVE_EXPR, the function we are building
- may be called twice, or side effects on the instance
- variable (such as a post-increment), may happen twice. */
- instance_ptr = save_expr (instance_ptr);
- instance = build_indirect_ref (instance_ptr, NULL);
- }
- else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
- {
- /* This happens when called for operator new (). */
- instance = build_indirect_ref (instance, NULL);
- }
-
- need_vtbl = maybe_needed;
- }
- }
-
- if (TYPE_SIZE (basetype) == 0)
- {
- /* This is worth complaining about, I think. */
- error_with_aggr_type (basetype, "cannot lookup method in incomplete type `%s'");
- return error_mark_node;
- }
-
- save_basetype = basetype;
-
-#if 0
- if (all_virtual == 1
- && (! strncmp (IDENTIFIER_POINTER (name), OPERATOR_METHOD_FORMAT,
- OPERATOR_METHOD_LENGTH)
- || instance_ptr == NULL_TREE
- || (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype) == 0)))
- all_virtual = 0;
-#endif
-
- last = NULL_TREE;
- for (parmtypes = NULL_TREE, parm = parms; parm; parm = TREE_CHAIN (parm))
- {
- tree t = TREE_TYPE (TREE_VALUE (parm));
- if (TREE_CODE (t) == OFFSET_TYPE)
- {
- /* Convert OFFSET_TYPE entities to their normal selves. */
- TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
- if (TREE_CODE (t) == ARRAY_TYPE)
- {
- /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
- This eliminates needless calls to `compute_conversion_costs'. */
- TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
- if (t == error_mark_node)
- return error_mark_node;
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
- }
-
- if (instance)
- {
- constp = TREE_READONLY (instance);
- volatilep = TREE_THIS_VOLATILE (instance);
- parms = tree_cons (NULL_TREE, instance_ptr, parms);
- }
- else
- {
- /* Raw constructors are always in charge. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)
- && ! (flags & LOOKUP_HAS_IN_CHARGE))
- {
- flags |= LOOKUP_HAS_IN_CHARGE;
- parms = tree_cons (NULL_TREE, integer_one_node, parms);
- parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
- }
-
- if (flag_this_is_variable > 0)
- {
- constp = 0;
- volatilep = 0;
- parms = tree_cons (NULL_TREE, build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node), parms);
- }
- else
- {
- constp = 0;
- volatilep = 0;
- instance_ptr = build_new (NULL_TREE, basetype, void_type_node, 0);
- if (instance_ptr == error_mark_node)
- return error_mark_node;
- instance_ptr = save_expr (instance_ptr);
- TREE_CALLS_NEW (instance_ptr) = 1;
- instance = build_indirect_ref (instance_ptr, NULL);
-
- /* If it's a default argument initialized from a ctor, what we get
- from instance_ptr will match the arglist for the FUNCTION_DECL
- of the constructor. */
- if (parms && TREE_CODE (TREE_VALUE (parms)) == CALL_EXPR
- && TREE_OPERAND (TREE_VALUE (parms), 1)
- && TREE_CALLS_NEW (TREE_VALUE (TREE_OPERAND (TREE_VALUE (parms), 1))))
- parms = build_tree_list (NULL_TREE, instance_ptr);
- else
- parms = tree_cons (NULL_TREE, instance_ptr, parms);
- }
- }
- parmtypes = tree_cons (NULL_TREE,
- build_pointer_type (build_type_variant (basetype, constp, volatilep)),
- parmtypes);
- if (last == NULL_TREE)
- last = parmtypes;
-
- /* Look up function name in the structure type definition. */
-
- if ((IDENTIFIER_HAS_TYPE_VALUE (name)
- && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name)))
- || name == constructor_name (basetype))
- {
- tree tmp = NULL_TREE;
- if (IDENTIFIER_TYPE_VALUE (name) == basetype
- || name == constructor_name (basetype))
- tmp = TYPE_BINFO (basetype);
- else
- tmp = get_binfo (IDENTIFIER_TYPE_VALUE (name), basetype, 0);
-
- if (tmp != NULL_TREE)
- {
- name_kind = "constructor";
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)
- && ! (flags & LOOKUP_HAS_IN_CHARGE))
- {
- /* Constructors called for initialization
- only are never in charge. */
- tree tmplist;
-
- flags |= LOOKUP_HAS_IN_CHARGE;
- tmplist = tree_cons (NULL_TREE, integer_zero_node,
- TREE_CHAIN (parms));
- TREE_CHAIN (parms) = tmplist;
- tmplist = tree_cons (NULL_TREE, integer_type_node, TREE_CHAIN (parmtypes));
- TREE_CHAIN (parmtypes) = tmplist;
- }
- basetype = BINFO_TYPE (tmp);
- }
- else
- name_kind = "method";
- }
- else name_kind = "method";
-
- if (basetype_path == NULL_TREE)
- basetype_path = TYPE_BINFO (basetype);
- result = lookup_fnfields (basetype_path, name,
- (flags & LOOKUP_COMPLAIN));
- if (result == error_mark_node)
- return error_mark_node;
-
-
- /* Now, go look for this method name. We do not find destructors here.
-
- Putting `void_list_node' on the end of the parmtypes
- fakes out `build_decl_overload' into doing the right thing. */
- TREE_CHAIN (last) = void_list_node;
- method_name = build_decl_overload (name, parmtypes,
- 1 + (name == constructor_name (save_basetype)));
- TREE_CHAIN (last) = NULL_TREE;
-
- for (pass = 0; pass < 2; pass++)
- {
- struct candidate *candidates;
- struct candidate *cp;
- int len;
- unsigned best = 1;
-
- /* This increments every time we go up the type hierarchy.
- The idea is to prefer a function of the derived class if possible. */
- int b_or_d = 0;
-
- baselink = result;
-
- if (pass > 0)
- {
- candidates
- = (struct candidate *) alloca ((ever_seen+1)
- * sizeof (struct candidate));
- cp = candidates;
- len = list_length (parms);
-
- /* First see if a global function has a shot at it. */
- if (flags & LOOKUP_GLOBAL)
- {
- tree friend_parms;
- tree parm = TREE_VALUE (parms);
-
- if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)
- friend_parms = parms;
- else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
- {
- tree new_type;
- parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
- new_type = build_reference_type (TREE_TYPE (parm));
- /* It is possible that this should go down a layer. */
- new_type = build_type_variant (new_type,
- TREE_READONLY (parm),
- TREE_THIS_VOLATILE (parm));
- parm = convert (new_type, parm);
- friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
- }
- else
- my_friendly_abort (167);
-
- cp->harshness
- = (unsigned short *)alloca ((len+1) * sizeof (short));
- result = build_overload_call (name, friend_parms, 0, cp);
- /* If it turns out to be the one we were actually looking for
- (it was probably a friend function), the return the
- good result. */
- if (TREE_CODE (result) == CALL_EXPR)
- return result;
-
- while (cp->evil == 0)
- {
- /* non-standard uses: set the field to 0 to indicate
- we are using a non-member function. */
- cp->u.field = 0;
- if (cp->harshness[len] == 0
- && cp->harshness[len] == 0
- && cp->user == 0 && cp->b_or_d == 0
- && cp->easy < best)
- best = cp->easy;
- cp += 1;
- }
- }
- }
-
- while (baselink)
- {
- /* We have a hit (of sorts). If the parameter list is
- "error_mark_node", or some variant thereof, it won't
- match any methods. Since we have verified that the is
- some method vaguely matching this one (in name at least),
- silently return.
-
- Don't stop for friends, however. */
- tree basetypes = TREE_PURPOSE (baselink);
-
- function = TREE_VALUE (baselink);
- if (TREE_CODE (basetypes) == TREE_LIST)
- basetypes = TREE_VALUE (basetypes);
- basetype = BINFO_TYPE (basetypes);
-
- /* Cast the instance variable to the appropriate type. */
- TREE_VALUE (parmtypes) = TYPE_POINTER_TO (basetype);
-
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
- function = DECL_CHAIN (function);
-
- for (; function; function = DECL_CHAIN (function))
- {
-#ifdef GATHER_STATISTICS
- n_inner_fields_searched++;
-#endif
- ever_seen++;
-
- /* Not looking for friends here. */
- if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE
- && ! DECL_STATIC_FUNCTION_P (function))
- continue;
-
- if (pass == 0
- && DECL_ASSEMBLER_NAME (function) == method_name)
- {
- if (flags & LOOKUP_PROTECT)
- {
- visibility = compute_visibility (basetypes, function);
- if (visibility == visibility_protected
- && flags & LOOKUP_PROTECTED_OK)
- visibility = visibility_public;
- }
-
- if ((flags & LOOKUP_PROTECT) == 0
- || visibility == visibility_public)
- goto found_and_ok;
- else if (visibility == visibility_private)
- saw_private = function;
- else if (visibility == visibility_protected)
- saw_protected = function;
- /* If we fail on the exact match, we have
- an immediate failure. */
- goto found;
- }
- if (pass > 0)
- {
- tree these_parms = parms;
-
-#ifdef GATHER_STATISTICS
- n_inner_fields_searched++;
-#endif
- cp->harshness
- = (unsigned short *)alloca ((len+1) * sizeof (short));
- if (DECL_STATIC_FUNCTION_P (function))
- these_parms = TREE_CHAIN (these_parms);
- compute_conversion_costs (function, these_parms, cp, len);
- cp->b_or_d += b_or_d;
- if (cp->evil == 0)
- {
- cp->u.field = function;
- cp->function = function;
- if (flags & LOOKUP_PROTECT)
- {
- enum visibility_type this_v;
- this_v = compute_visibility (basetypes, function);
- if (this_v == visibility_protected
- && (flags & LOOKUP_PROTECTED_OK))
- this_v = visibility_public;
- if (this_v != visibility_public)
- {
- if (this_v == visibility_private)
- saw_private = function;
- else
- saw_protected = function;
- continue;
- }
- }
-
- /* No "two-level" conversions. */
- if (flags & LOOKUP_NO_CONVERSION && cp->user != 0)
- continue;
-
- /* If we used default parameters, we must
- check to see whether anyone else might
- use them also, and report a possible
- ambiguity. */
- if (! TYPE_USES_MULTIPLE_INHERITANCE (save_basetype)
- && cp->harshness[len] == 0
- && CONST_HARSHNESS (cp->harshness[0]) == 0
- && cp->user == 0 && cp->b_or_d == 0
- && cp->easy < best)
- {
- if (! DECL_STATIC_FUNCTION_P (function))
- TREE_VALUE (parms) = cp->arg;
- if (best == 1)
- goto found_and_maybe_warn;
- }
- cp++;
- }
- }
- }
- /* Now we have run through one link's member functions.
- arrange to head-insert this link's links. */
- baselink = next_baselink (baselink);
- b_or_d += 1;
- }
- if (pass == 0)
- {
- /* No exact match could be found. Now try to find match
- using default conversions. */
- if ((flags & LOOKUP_GLOBAL) && IDENTIFIER_GLOBAL_VALUE (name))
- if (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == FUNCTION_DECL)
- ever_seen += 1;
- else if (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TREE_LIST)
- ever_seen += list_length (IDENTIFIER_GLOBAL_VALUE (name));
-
- if (ever_seen == 0)
- {
- if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
- == LOOKUP_SPECULATIVELY)
- return NULL_TREE;
- if (flags & LOOKUP_GLOBAL)
- error ("no global or non-hidden member function `%s' defined", err_name);
- else
- error_with_aggr_type (save_basetype, "no non-hidden member function `%s::%s' defined", err_name);
- return error_mark_node;
- }
- continue;
- }
-
- if (cp - candidates != 0)
- {
- /* Rank from worst to best. Then cp will point to best one.
- Private fields have their bits flipped. For unsigned
- numbers, this should make them look very large.
- If the best alternate has a (signed) negative value,
- then all we ever saw were private members. */
- if (cp - candidates > 1)
- {
- cp = ideal_candidate (save_basetype, candidates,
- cp - candidates, parms, len);
- if (cp == (struct candidate *)0)
- {
- error ("ambiguous type conversion requested for %s `%s'",
- name_kind, err_name);
- return error_mark_node;
- }
- if (cp->evil)
- return error_mark_node;
- }
- else if (cp[-1].evil == 2)
- {
- error ("ambiguous type conversion requested for %s `%s'",
- name_kind, err_name);
- return error_mark_node;
- }
- else cp--;
-
- /* The global function was the best, so use it. */
- if (cp->u.field == 0)
- {
- /* We must convert the instance pointer into a reference type.
- Global overloaded functions can only either take
- aggregate objects (which come for free from references)
- or reference data types anyway. */
- TREE_VALUE (parms) = copy_node (instance_ptr);
- TREE_TYPE (TREE_VALUE (parms)) = build_reference_type (TREE_TYPE (TREE_TYPE (instance_ptr)));
- return build_function_call (cp->function, parms);
- }
-
- function = cp->function;
- if (! DECL_STATIC_FUNCTION_P (function))
- TREE_VALUE (parms) = cp->arg;
- goto found_and_maybe_warn;
- }
-
- if ((flags & ~LOOKUP_GLOBAL) & (LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY))
- {
- char *tag_name, *buf;
-
- if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
- == LOOKUP_SPECULATIVELY)
- return NULL_TREE;
-
- if (DECL_STATIC_FUNCTION_P (cp->function))
- parms = TREE_CHAIN (parms);
- if (ever_seen)
- {
- if (((HOST_WIDE_INT)saw_protected|(HOST_WIDE_INT)saw_private) == 0)
- {
- if (flags & LOOKUP_SPECULATIVELY)
- return NULL_TREE;
- if (static_call_context && TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
- error_with_aggr_type (TREE_TYPE (TREE_TYPE (instance_ptr)),
- "object missing in call to `%s::%s'",
- err_name);
- else
- report_type_mismatch (cp, parms, name_kind, err_name);
- }
- else
- {
- char buf[80];
- char *msg;
- tree seen = saw_private;
-
- if (saw_private)
- {
- if (saw_protected)
- msg = "%s `%%s' (and the like) are private or protected";
- else
- msg = "the %s `%%s' is private";
- }
- else
- {
- msg = "the %s `%%s' is protected";
- seen = saw_protected;
- }
- sprintf (buf, msg, name_kind);
- error_with_decl (seen, buf);
- error ("within this context");
- }
- return error_mark_node;
- }
-
- if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
- == LOOKUP_COMPLAIN)
- {
- if (TREE_CODE (save_basetype) == RECORD_TYPE)
- tag_name = "structure";
- else
- tag_name = "union";
-
- buf = (char *)alloca (30 + strlen (err_name));
- strcpy (buf, "%s has no method named `%s'");
- error (buf, tag_name, err_name);
- return error_mark_node;
- }
- return NULL_TREE;
- }
- continue;
-
- found_and_maybe_warn:
- if (CONST_HARSHNESS (cp->harshness[0]))
- {
- if (flags & LOOKUP_COMPLAIN)
- {
- error_with_decl (cp->function, "non-const member function `%s'");
- error ("called for const object at this point in file");
- }
- /* Not good enough for a match. */
- else
- return error_mark_node;
- }
- goto found_and_ok;
- }
- /* Silently return error_mark_node. */
- return error_mark_node;
-
- found:
- if (visibility == visibility_private)
- {
- if (flags & LOOKUP_COMPLAIN)
- {
- error_with_file_and_line (DECL_SOURCE_FILE (function),
- DECL_SOURCE_LINE (function),
- TREE_PRIVATE (function)
- ? "%s `%s' is private"
- : "%s `%s' is from private base class",
- name_kind,
- lang_printable_name (function));
- error ("within this context");
- }
- return error_mark_node;
- }
- else if (visibility == visibility_protected)
- {
- if (flags & LOOKUP_COMPLAIN)
- {
- error_with_file_and_line (DECL_SOURCE_FILE (function),
- DECL_SOURCE_LINE (function),
- TREE_PROTECTED (function)
- ? "%s `%s' is protected"
- : "%s `%s' has protected visibility from this point",
- name_kind,
- lang_printable_name (function));
- error ("within this context");
- }
- return error_mark_node;
- }
- my_friendly_abort (1);
-
- found_and_ok:
-
- /* From here on down, BASETYPE is the type that INSTANCE_PTR's
- type (if it exists) is a pointer to. */
- function = DECL_MAIN_VARIANT (function);
- /* Declare external function if necessary. */
- assemble_external (function);
-
- fntype = TREE_TYPE (function);
- if (TREE_CODE (fntype) == POINTER_TYPE)
- fntype = TREE_TYPE (fntype);
- basetype = DECL_CLASS_CONTEXT (function);
-
- /* If we are referencing a virtual function from an object
- of effectively static type, then there is no need
- to go through the virtual function table. */
- if (need_vtbl == maybe_needed)
- {
- int fixed_type = resolves_to_fixed_type_p (instance, 0);
-
- if (all_virtual == 1
- && DECL_VINDEX (function)
- && may_be_remote (basetype))
- need_vtbl = needed;
- else if (DECL_VINDEX (function))
- need_vtbl = fixed_type ? unneeded : needed;
- else
- need_vtbl = not_needed;
- }
-
- if (TREE_CODE (fntype) == METHOD_TYPE && static_call_context
- && !DECL_CONSTRUCTOR_P (function))
- {
- /* Let's be nice to the user for now, and give reasonable
- default behavior. */
- instance_ptr = current_class_decl;
- if (instance_ptr)
- {
- if (basetype != current_class_type)
- {
- tree binfo = get_binfo (basetype, current_class_type, 1);
- if (binfo == NULL_TREE)
- {
- error_not_base_type (function, current_class_type);
- return error_mark_node;
- }
- else if (basetype == error_mark_node)
- return error_mark_node;
- }
- }
- else if (! TREE_STATIC (function))
- {
- error_with_aggr_type (basetype, "cannot call member function `%s::%s' without object",
- err_name);
- return error_mark_node;
- }
- }
-
- value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
-
- if (TYPE_SIZE (value_type) == 0)
- {
- if (flags & LOOKUP_COMPLAIN)
- incomplete_type_error (0, value_type);
- return error_mark_node;
- }
-
- /* We do not pass FUNCTION into `convert_arguments', because by
- now everything should be ok. If not, then we have a serious error. */
- if (DECL_STATIC_FUNCTION_P (function))
- parms = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
- TREE_CHAIN (parms), NULL_TREE, LOOKUP_NORMAL);
- else if (need_vtbl == unneeded)
- {
- int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL;
- basetype = TREE_TYPE (instance);
- if (TYPE_METHOD_BASETYPE (TREE_TYPE (function)) != TYPE_MAIN_VARIANT (basetype)
- && TYPE_USES_COMPLEX_INHERITANCE (basetype))
- {
- basetype = DECL_CLASS_CONTEXT (function);
- instance_ptr = convert_pointer_to (basetype, instance_ptr);
- instance = build_indirect_ref (instance_ptr, NULL);
- }
- parms = tree_cons (NULL_TREE, instance_ptr,
- convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), NULL_TREE, sub_flags));
- }
- else
- {
- if ((flags & LOOKUP_NONVIRTUAL) == 0)
- basetype = DECL_CONTEXT (function);
-
- /* First parm could be integer_zerop with casts like
- ((Object*)0)->Object::IsA() */
- if (!integer_zerop (TREE_VALUE (parms)))
- {
- instance_ptr = convert_pointer_to (build_type_variant (basetype, constp, volatilep),
- TREE_VALUE (parms));
- if (TREE_CODE (instance_ptr) == COND_EXPR)
- {
- instance_ptr = save_expr (instance_ptr);
- instance = build_indirect_ref (instance_ptr, NULL);
- }
- else if (TREE_CODE (instance_ptr) == NOP_EXPR
- && TREE_CODE (TREE_OPERAND (instance_ptr, 0)) == ADDR_EXPR
- && TREE_OPERAND (TREE_OPERAND (instance_ptr, 0), 0) == instance)
- ;
- /* The call to `convert_pointer_to' may return error_mark_node. */
- else if (TREE_CODE (instance_ptr) == ERROR_MARK)
- return instance_ptr;
- else if (instance == NULL_TREE
- || TREE_CODE (instance) != INDIRECT_REF
- || TREE_OPERAND (instance, 0) != instance_ptr)
- instance = build_indirect_ref (instance_ptr, NULL);
- }
- parms = tree_cons (NULL_TREE, instance_ptr,
- convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), NULL_TREE, LOOKUP_NORMAL));
- }
-
-#if 0
- /* Constructors do not overload method calls. */
- else if (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype)
- && name != TYPE_IDENTIFIER (basetype)
- && (TREE_CODE (function) != FUNCTION_DECL
- || strncmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)),
- OPERATOR_METHOD_FORMAT,
- OPERATOR_METHOD_LENGTH))
-#if 0
- && (may_be_remote (basetype)
- || (C_C_D ? TREE_TYPE (instance) != current_class_type : 1))
-#else
- /* This change by Larry Ketcham. */
- && (may_be_remote (basetype) || instance != C_C_D)
-#endif
- )
- {
- tree fn_as_int;
-
- parms = TREE_CHAIN (parms);
-
- if (!all_virtual && TREE_CODE (function) == FUNCTION_DECL)
- fn_as_int = build_unary_op (ADDR_EXPR, function, 0);
- else
- fn_as_int = convert (TREE_TYPE (default_conversion (function)), DECL_VINDEX (function));
- if (all_virtual == 1)
- fn_as_int = convert (integer_type_node, fn_as_int);
-
- result = build_opfncall (METHOD_CALL_EXPR, LOOKUP_NORMAL, instance, fn_as_int, parms);
-
- if (result == NULL_TREE)
- {
- compiler_error ("could not overload `operator->()(...)'");
- return error_mark_node;
- }
- else if (result == error_mark_node)
- return error_mark_node;
-
-#if 0
- /* Do this if we want the result of operator->() to inherit
- the type of the function it is subbing for. */
- TREE_TYPE (result) = value_type;
-#endif
-
- return result;
- }
-#endif
-
- if (need_vtbl == needed)
- {
- function = build_vfn_ref (&TREE_VALUE (parms), instance, DECL_VINDEX (function));
- TREE_TYPE (function) = build_pointer_type (fntype);
- }
-
- if (TREE_CODE (function) == FUNCTION_DECL)
- GNU_xref_call (current_function_decl,
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)));
-
- if (TREE_CODE (function) == FUNCTION_DECL)
- {
- if (DECL_INLINE (function))
- function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
- else
- {
- assemble_external (function);
- TREE_USED (function) = 1;
- function = default_conversion (function);
- }
- }
- else
- function = default_conversion (function);
-
- result =
- build_nt (CALL_EXPR, function, parms, NULL_TREE);
-
- TREE_TYPE (result) = value_type;
- TREE_SIDE_EFFECTS (result) = 1;
- TREE_RAISES (result)
- = TYPE_RAISES_EXCEPTIONS (fntype) || (parms && TREE_RAISES (parms));
- return result;
-}
-
-/* Similar to `build_method_call', but for overloaded non-member functions.
- The name of this function comes through NAME. The name depends
- on PARMS.
-
- Note that this function must handle simple `C' promotions,
- as well as variable numbers of arguments (...), and
- default arguments to boot.
-
- If the overloading is successful, we return a tree node which
- contains the call to the function.
-
- If overloading produces candidates which are probable, but not definite,
- we hold these candidates. If FINAL_CP is non-zero, then we are free
- to assume that final_cp points to enough storage for all candidates that
- this function might generate. The `harshness' array is preallocated for
- the first candidate, but not for subsequent ones.
-
- Note that the DECL_RTL of FUNCTION must be made to agree with this
- function's new name. */
-
-tree
-build_overload_call_real (fnname, parms, complain, final_cp, buildxxx)
- tree fnname, parms;
- int complain;
- struct candidate *final_cp;
- int buildxxx;
-{
- /* must check for overloading here */
- tree overload_name, functions, function, parm;
- tree parmtypes = NULL_TREE, last = NULL_TREE;
- register tree outer;
- int length;
- int parmlength = list_length (parms);
-
- struct candidate *candidates, *cp;
-
- if (final_cp)
- {
- final_cp[0].evil = 0;
- final_cp[0].user = 0;
- final_cp[0].b_or_d = 0;
- final_cp[0].easy = 0;
- final_cp[0].function = 0;
- /* end marker. */
- final_cp[1].evil = 1;
- }
-
- for (parm = parms; parm; parm = TREE_CHAIN (parm))
- {
- register tree t = TREE_TYPE (TREE_VALUE (parm));
-
- if (t == error_mark_node)
- {
- if (final_cp)
- final_cp->evil = 1;
- return error_mark_node;
- }
- if (TREE_CODE (t) == ARRAY_TYPE || TREE_CODE (t) == OFFSET_TYPE)
- {
- /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
- Also convert OFFSET_TYPE entities to their normal selves.
- This eliminates needless calls to `compute_conversion_costs'. */
- TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
- }
- if (last)
- TREE_CHAIN (last) = void_list_node;
- else
- parmtypes = void_list_node;
- overload_name = build_decl_overload (fnname, parmtypes, 0);
-
- /* Now check to see whether or not we can win.
- Note that if we are called from `build_method_call',
- then we cannot have a mis-match, because we would have
- already found such a winning case. */
-
- if (IDENTIFIER_GLOBAL_VALUE (overload_name))
- if (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (overload_name)) != TREE_LIST)
- return build_function_call (DECL_MAIN_VARIANT (IDENTIFIER_GLOBAL_VALUE (overload_name)), parms);
-
- functions = IDENTIFIER_GLOBAL_VALUE (fnname);
-
- if (functions == NULL_TREE)
- {
- if (complain)
- error ("only member functions apply");
- if (final_cp)
- final_cp->evil = 1;
- return error_mark_node;
- }
-
- if (TREE_CODE (functions) == FUNCTION_DECL)
- {
- functions = DECL_MAIN_VARIANT (functions);
- if (final_cp)
- {
- /* We are just curious whether this is a viable alternative or not. */
- compute_conversion_costs (functions, parms, final_cp, parmlength);
- return functions;
- }
- else
- return build_function_call (functions, parms);
- }
-
- if (TREE_VALUE (functions) == NULL_TREE)
- {
- if (complain)
- error ("function `%s' declared overloaded, but no instances of that function declared",
- IDENTIFIER_POINTER (TREE_PURPOSE (functions)));
- if (final_cp)
- final_cp->evil = 1;
- return error_mark_node;
- }
-
- if (TREE_CODE (TREE_VALUE (functions)) == TREE_LIST)
- {
- register tree outer;
- length = 0;
-
- /* The list-of-lists should only occur for class things. */
- my_friendly_assert (functions == IDENTIFIER_CLASS_VALUE (fnname), 168);
-
- for (outer = functions; outer; outer = TREE_CHAIN (outer))
- {
- /* member functions. */
- length += decl_list_length (TREE_VALUE (TREE_VALUE (outer)));
- /* friend functions. */
- length += list_length (TREE_TYPE (TREE_VALUE (outer)));
- }
- }
- else
- {
- length = list_length (functions);
- }
-
- if (final_cp)
- candidates = final_cp;
- else
- candidates = (struct candidate *)alloca ((length+1) * sizeof (struct candidate));
-
- cp = candidates;
-
- my_friendly_assert (TREE_CODE (TREE_VALUE (functions)) != TREE_LIST, 169);
- /* OUTER is the list of FUNCTION_DECLS, in a TREE_LIST. */
-
- for (outer = functions; outer; outer = TREE_CHAIN (outer))
- {
- int template_cost = 0;
- function = TREE_VALUE (outer);
- if (TREE_CODE (function) != FUNCTION_DECL
- && ! (TREE_CODE (function) == TEMPLATE_DECL
- && ! DECL_TEMPLATE_IS_CLASS (function)
- && TREE_CODE (DECL_TEMPLATE_RESULT (function)) == FUNCTION_DECL))
- {
- enum tree_code code = TREE_CODE (function);
- if (code == TEMPLATE_DECL)
- code = TREE_CODE (DECL_TEMPLATE_RESULT (function));
- if (code == CONST_DECL)
- error_with_decl (function, "enumeral value `%s' conflicts with function of same name");
- else if (code == VAR_DECL)
- if (TREE_STATIC (function))
- error_with_decl (function, "variable `%s' conflicts with function of same name");
- else
- error_with_decl (function, "constant field `%s' conflicts with function of same name");
- else if (code == TYPE_DECL)
- continue;
- else my_friendly_abort (2);
- error ("at this point in file");
- continue;
- }
- if (TREE_CODE (function) == TEMPLATE_DECL)
- {
- int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (function));
- tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
- int i;
-
- i = type_unification (DECL_TEMPLATE_PARMS (function), targs,
- TYPE_ARG_TYPES (TREE_TYPE (function)),
- parms, &template_cost);
- if (i == 0)
- function = instantiate_template (function, targs);
- }
- if (TREE_CODE (function) == TEMPLATE_DECL)
- /* Unconverted template -- failed match. */
- cp->evil = 1, cp->function = function, cp->u.bad_arg = -4;
- else
- {
- function = DECL_MAIN_VARIANT (function);
-
- /* Can't use alloca here, since result might be
- passed to calling function. */
- cp->harshness
- = (unsigned short *)oballoc ((parmlength+1) * sizeof (short));
- compute_conversion_costs (function, parms, cp, parmlength);
- /* Should really add another field... */
- cp->easy = cp->easy * 128 + template_cost;
- if (cp[0].evil == 0)
- {
- cp[1].evil = 1;
- if (final_cp
- && cp[0].user == 0 && cp[0].b_or_d == 0
- && template_cost == 0
- && cp[0].easy <= 1)
- {
- final_cp[0].easy = cp[0].easy;
- return function;
- }
- cp++;
- }
- }
- }
-
- if (cp - candidates)
- {
- tree rval = error_mark_node;
-
- /* Leave marker. */
- cp[0].evil = 1;
- if (cp - candidates > 1)
- {
- struct candidate *best_cp
- = ideal_candidate (NULL_TREE, candidates,
- cp - candidates, parms, parmlength);
- if (best_cp == (struct candidate *)0)
- {
- if (complain)
- error ("call of overloaded `%s' is ambiguous", IDENTIFIER_POINTER (fnname));
- return error_mark_node;
- }
- else
- rval = best_cp->function;
- }
- else
- {
- cp -= 1;
- if (cp->evil > 1)
- {
- if (complain)
- error ("type conversion ambiguous");
- }
- else
- rval = cp->function;
- }
-
- if (final_cp)
- return rval;
-
- return buildxxx ? build_function_call_maybe (rval, parms)
- : build_function_call (rval, parms);
- }
- else if (complain)
- {
- tree name;
- char *err_name;
-
- /* Initialize name for error reporting. */
- if (TREE_CODE (functions) == TREE_LIST)
- name = TREE_PURPOSE (functions);
- else if (TREE_CODE (functions) == ADDR_EXPR)
- /* Since the implicit `operator new' and `operator delete' functions
- are set up to have IDENTIFIER_GLOBAL_VALUEs that are unary ADDR_EXPRs
- by default_conversion(), we must compensate for that here by
- using the name of the ADDR_EXPR's operand. */
- name = DECL_NAME (TREE_OPERAND (functions, 0));
- else
- name = DECL_NAME (functions);
-
- if (IDENTIFIER_OPNAME_P (name))
- {
- char *opname = operator_name_string (name);
- err_name = (char *)alloca (strlen (opname) + 12);
- sprintf (err_name, "operator %s", opname);
- }
- else
- err_name = IDENTIFIER_POINTER (name);
-
- report_type_mismatch (cp, parms, "function", err_name);
- }
- return error_mark_node;
-}
-
-tree
-build_overload_call (fnname, parms, complain, final_cp)
- tree fnname, parms;
- int complain;
- struct candidate *final_cp;
-{
- return build_overload_call_real (fnname, parms, complain, final_cp, 0);
-}
-
-tree
-build_overload_call_maybe (fnname, parms, complain, final_cp)
- tree fnname, parms;
- int complain;
- struct candidate *final_cp;
-{
- return build_overload_call_real (fnname, parms, complain, final_cp, 1);
-}
diff --git a/gnu/gcc2/cc1plus/cp-class.c b/gnu/gcc2/cc1plus/cp-class.c
deleted file mode 100644
index 49e8581dd362..000000000000
--- a/gnu/gcc2/cc1plus/cp-class.c
+++ /dev/null
@@ -1,4274 +0,0 @@
-/* Functions related to building classes and their related objects.
- Copyright (C) 1987, 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. */
-
-
-/* High-level class interface. */
-
-#include "config.h"
-#include "tree.h"
-#include <stdio.h>
-#include "cp-tree.h"
-#include "flags.h"
-
-#ifdef DEBUG_CP_BINDING_LEVELS
-#include "cp-decl.h"
-#endif
-
-#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-extern struct obstack permanent_obstack;
-
-/* Way of stacking class types. */
-static tree *current_class_base, *current_class_stack;
-static int current_class_stacksize;
-int current_class_depth;
-
-struct class_level
-{
- /* The previous class level. */
- struct class_level *level_chain;
-
- /* The class instance variable, as a PARM_DECL. */
- tree decl;
- /* The class instance variable, as an object. */
- tree object;
- /* The virtual function table pointer
- for the class instance variable. */
- tree vtable_decl;
-
- /* Name of the current class. */
- tree name;
- /* Type of the current class. */
- tree type;
-
- /* Flags for this class level. */
- int this_is_variable;
- int memoized_lookups;
- int save_memoized;
- int unused;
-};
-
-tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */
-tree current_vtable_decl;
-
-/* The following two can be derived from the previous one */
-tree current_class_name; /* IDENTIFIER_NODE: name of current class */
-tree current_class_type; /* _TYPE: the type of the current class */
-static tree prev_class_type; /* _TYPE: the previous type that was a class */
-
-static tree get_vfield_name PROTO((tree));
-tree the_null_vtable_entry;
-
-/* Way of stacking language names. */
-tree *current_lang_base, *current_lang_stack;
-static int current_lang_stacksize;
-
-/* Names of languages we recognize. */
-tree lang_name_c, lang_name_cplusplus;
-tree current_lang_name;
-
-/* When layout out an aggregate type, the size of the
- basetypes (virtual and non-virtual) is passed to layout_record
- via this node. */
-static tree base_layout_decl;
-
-/* Variables shared between cp-class.c and cp-call.c. */
-
-int n_vtables = 0;
-int n_vtable_entries = 0;
-int n_vtable_searches = 0;
-int n_vtable_elems = 0;
-int n_convert_harshness = 0;
-int n_compute_conversion_costs = 0;
-int n_build_method_call = 0;
-int n_inner_fields_searched = 0;
-
-/* Virtual baseclass things. */
-tree
-build_vbase_pointer (exp, type)
- tree exp, type;
-{
- char *name;
-
- name = (char *) alloca (TYPE_NAME_LENGTH (type) + sizeof (VBASE_NAME) + 1);
- sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (type));
- return build_component_ref (exp, get_identifier (name), 0, 0);
-}
-
-/* Build multi-level access to EXPR using hierarchy path PATH.
- CODE is PLUS_EXPR if we are going with the grain,
- and MINUS_EXPR if we are not (in which case, we cannot traverse
- virtual baseclass links).
-
- TYPE is the type we want this path to have on exit.
-
- ALIAS_THIS is non-zero if EXPR in an expression involving `this'. */
-tree
-build_vbase_path (code, type, expr, path, alias_this)
- enum tree_code code;
- tree type, expr, path;
- int alias_this;
-{
- register int changed = 0;
- tree last = NULL_TREE, last_virtual = NULL_TREE;
- int nonnull = 0;
- int fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
- tree null_expr = 0, nonnull_expr;
- tree basetype;
- tree offset = integer_zero_node;
-
- if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
- expr = save_expr (expr);
- nonnull_expr = expr;
-
- if (BINFO_INHERITANCE_CHAIN (path))
- {
- tree reverse_path = NULL_TREE;
-
- while (path)
- {
- tree r = copy_node (path);
- BINFO_INHERITANCE_CHAIN (r) = reverse_path;
- reverse_path = r;
- path = BINFO_INHERITANCE_CHAIN (path);
- }
- path = reverse_path;
- }
-
- basetype = BINFO_TYPE (path);
-
- while (path)
- {
- if (TREE_VIA_VIRTUAL (path))
- {
- last_virtual = BINFO_TYPE (path);
- if (code == PLUS_EXPR)
- {
- changed = ! fixed_type_p;
-
- if (changed)
- {
- extern int flag_assume_nonnull_objects;
- tree ind;
-
- if (last)
- nonnull_expr = convert_pointer_to (last, nonnull_expr);
- ind = build_indirect_ref (nonnull_expr, NULL);
- nonnull_expr = build_vbase_pointer (ind, last_virtual);
- if (nonnull == 0 && !flag_assume_nonnull_objects
- && null_expr == NULL_TREE)
- {
- null_expr = build1 (NOP_EXPR, TYPE_POINTER_TO (last_virtual), integer_zero_node);
- expr = build (COND_EXPR, TYPE_POINTER_TO (last_virtual),
- build (EQ_EXPR, integer_type_node, expr,
- integer_zero_node),
- null_expr, nonnull_expr);
- }
- }
- /* else we'll figure out the offset below. */
-
- /* Happens in the case of parse errors. */
- if (nonnull_expr == error_mark_node)
- return error_mark_node;
- }
- else
- {
- error_with_aggr_type (last_virtual, "cannot cast up from virtual baseclass `%s'");
- return error_mark_node;
- }
- }
- last = path;
- path = BINFO_INHERITANCE_CHAIN (path);
- }
- /* LAST is now the last basetype assoc on the path. */
-
- /* A pointer to a virtual base member of a non-null object
- is non-null. Therefore, we only need to test for zeroness once.
- Make EXPR the canonical expression to deal with here. */
- if (null_expr)
- {
- TREE_OPERAND (expr, 2) = nonnull_expr;
- TREE_TYPE (TREE_OPERAND (expr, 1)) = TREE_TYPE (nonnull_expr);
- }
- else
- expr = nonnull_expr;
-
- /* If we go through any virtual base pointers, make sure that
- casts to BASETYPE from the last virtual base class use
- the right value for BASETYPE. */
- if (changed)
- {
- tree intype = TREE_TYPE (TREE_TYPE (expr));
- if (TYPE_MAIN_VARIANT (intype) == BINFO_TYPE (last))
- basetype = intype;
- else
- {
- tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (intype), 0);
- basetype = last;
- offset = BINFO_OFFSET (binfo);
- }
- }
- else
- {
- if (last_virtual)
- {
- offset = BINFO_OFFSET (binfo_member (last_virtual,
- CLASSTYPE_VBASECLASSES (basetype)));
- offset = size_binop (PLUS_EXPR, offset, BINFO_OFFSET (last));
- }
- else
- offset = BINFO_OFFSET (last);
-
-#if 0
- /* why unconditionally set this? (mrs) see deja-gnu/g++.mike/net15.C
- for a test case. */
- code = PLUS_EXPR;
-#endif
- }
-
- if (TREE_INT_CST_LOW (offset))
- {
- /* For multiple inheritance: if `this' can be set by any
- function, then it could be 0 on entry to any function.
- Preserve such zeroness here. Otherwise, only in the
- case of constructors need we worry, and in those cases,
- it will be zero, or initialized to some legal value to
- which we may add. */
- if (nonnull == 0 && (alias_this == 0 || flag_this_is_variable > 0))
- {
- if (null_expr)
- TREE_TYPE (null_expr) = type;
- else
- null_expr = build1 (NOP_EXPR, type, integer_zero_node);
- if (TREE_SIDE_EFFECTS (expr))
- expr = save_expr (expr);
-
- return build (COND_EXPR, type,
- build (EQ_EXPR, integer_type_node, expr, integer_zero_node),
- null_expr,
- build (code, type, expr, offset));
- }
- else return build (code, type, expr, offset);
- }
-
- /* Cannot change the TREE_TYPE of a NOP_EXPR here, since it may
- be used multiple times in initialization of multiple inheritance. */
- if (null_expr)
- {
- TREE_TYPE (expr) = type;
- return expr;
- }
- else
- return build1 (NOP_EXPR, type, expr);
-}
-
-/* Virtual function things. */
-
-/* Virtual functions to be dealt with after laying out our
- base classes. Usually this is used only when classes have virtual
- baseclasses, but it can happen also when classes have non-virtual
- baseclasses if the derived class overrides baseclass functions
- at different offsets. */
-static tree pending_hard_virtuals;
-static int doing_hard_virtuals;
-
-/* The names of the entries in the virtual table structure. */
-static tree delta_name, pfn_name;
-
-/* XXX This is set but never used. (bpk) */
-#if 0
-/* Temporary binfo list to memoize lookups of the left-most non-virtual
- baseclass B in a lattice topped by T. B can appear multiple times
- in the lattice.
- TREE_PURPOSE is B's TYPE_MAIN_VARIANT.
- TREE_VALUE is the path by which B is reached from T.
- TREE_TYPE is B's real type.
-
- If TREE_TYPE is NULL_TREE, it means that B was reached via
- a virtual baseclass.
- N.B.: This list consists of nodes on the temporary obstack. */
-static tree leftmost_baseclasses;
-#endif
-
-/* Build an entry in the virtual function table.
- DELTA is the offset for the `this' pointer.
- PFN is an ADDR_EXPR containing a pointer to the virtual function.
- Note that the index (DELTA2) in the virtual function table
- is always 0. */
-tree
-build_vtable_entry (delta, pfn)
- tree delta, pfn;
-{
- tree elems = tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, integer_zero_node,
- build_tree_list (NULL_TREE, pfn)));
- tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
-
- /* DELTA is constructed by `size_int', which means it may be an
- unsigned quantity on some platforms. Therefore, we cannot use
- `int_fits_type_p', because when DELTA is really negative,
- `force_fit_type' will make it look like a very large number. */
-
- if ((TREE_INT_CST_LOW (TYPE_MAX_VALUE (short_integer_type_node))
- < TREE_INT_CST_LOW (delta))
- || (TREE_INT_CST_LOW (delta)
- < TREE_INT_CST_LOW (TYPE_MIN_VALUE (short_integer_type_node))))
- sorry ("object size exceeds built-in limit for virtual function table implementation");
-
- TREE_CONSTANT (entry) = 1;
- TREE_STATIC (entry) = 1;
- TREE_READONLY (entry) = 1;
-
-#ifdef GATHER_STATISTICS
- n_vtable_entries += 1;
-#endif
-
- return entry;
-}
-
-/* Given an object INSTANCE, return an expression which yields
- the virtual function corresponding to INDEX. There are many special
- cases for INSTANCE which we take care of here, mainly to avoid
- creating extra tree nodes when we don't have to. */
-tree
-build_vfn_ref (ptr_to_instptr, instance, index)
- tree *ptr_to_instptr, instance;
- tree index;
-{
- extern int building_cleanup;
- tree vtbl, aref;
- tree basetype = TREE_TYPE (instance);
-
- if (TREE_CODE (basetype) == REFERENCE_TYPE)
- basetype = TREE_TYPE (basetype);
-
- if (instance == C_C_D)
- {
- if (current_vtable_decl == NULL_TREE
- || current_vtable_decl == error_mark_node
- || !UNIQUELY_DERIVED_FROM_P (DECL_FCONTEXT (CLASSTYPE_VFIELD (current_class_type)), basetype))
- vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), NULL);
- else
- vtbl = current_vtable_decl;
- }
- else
- {
- if (optimize)
- {
- /* Try to figure out what a reference refers to, and
- access its virtual function table directly. */
- tree ref = NULL_TREE;
-
- if (TREE_CODE (instance) == INDIRECT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (instance, 0))) == REFERENCE_TYPE)
- ref = TREE_OPERAND (instance, 0);
- else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- ref = instance;
-
- if (ref && TREE_CODE (ref) == VAR_DECL
- && DECL_INITIAL (ref))
- {
- tree init = DECL_INITIAL (ref);
-
- while (TREE_CODE (init) == NOP_EXPR
- || TREE_CODE (init) == NON_LVALUE_EXPR)
- init = TREE_OPERAND (init, 0);
- if (TREE_CODE (init) == ADDR_EXPR)
- {
- init = TREE_OPERAND (init, 0);
- if (IS_AGGR_TYPE (TREE_TYPE (init))
- && (TREE_CODE (init) == PARM_DECL
- || TREE_CODE (init) == VAR_DECL))
- instance = init;
- }
- }
- }
-
- if (IS_AGGR_TYPE (TREE_TYPE (instance))
- && (TREE_CODE (instance) == RESULT_DECL
- || TREE_CODE (instance) == PARM_DECL
- || TREE_CODE (instance) == VAR_DECL))
- vtbl = TYPE_BINFO_VTABLE (basetype);
- else
- vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
- NULL);
- }
- assemble_external (vtbl);
- aref = build_array_ref (vtbl, index);
- if (!building_cleanup && TREE_CODE (aref) == INDIRECT_REF)
- TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
-
- *ptr_to_instptr = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
- *ptr_to_instptr,
- convert (integer_type_node, build_component_ref (aref, delta_name, 0, 0)));
- return build_component_ref (aref, pfn_name, 0, 0);
-}
-
-/* Set TREE_PUBLIC and/or TREE_EXTERN on the vtable DECL,
- based on TYPE and other static flags.
-
- Note that anything public is tagged TREE_PUBLIC, whether
- it's public in this file or in another one. */
-
-static void
-import_export_vtable (decl, type)
- tree decl, type;
-{
- if (write_virtuals >= 2)
- {
- if (CLASSTYPE_INTERFACE_UNKNOWN (type) == 0)
- {
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
- }
- }
- else if (write_virtuals != 0)
- {
- TREE_PUBLIC (decl) = 1;
- if (write_virtuals < 0)
- DECL_EXTERNAL (decl) = 1;
- }
-}
-
-/* Return the name of the virtual function table (as an IDENTIFIER_NODE)
- for the given TYPE. */
-static tree
-get_vtable_name (type)
- tree type;
-{
- tree type_id = build_typename_overload (type);
- char *buf = (char *)alloca (sizeof (VTABLE_NAME_FORMAT)
- + IDENTIFIER_LENGTH (type_id) + 2);
- char *ptr = IDENTIFIER_POINTER (type_id);
- int i;
- for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
- while (ptr[i] >= '0' && ptr[i] <= '9')
- i += 1;
- sprintf (buf, VTABLE_NAME_FORMAT, ptr+i);
- return get_identifier (buf);
-}
-
-/* Build a virtual function for type TYPE.
- If BINFO is non-NULL, build the vtable starting with the initial
- approximation that it is the same as the one which is the head of
- the association list. */
-static tree
-build_vtable (binfo, type)
- tree binfo, type;
-{
- tree name = get_vtable_name (type);
- tree virtuals, decl;
-
- if (binfo)
- {
- virtuals = copy_list (BINFO_VIRTUALS (binfo));
- decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));
- }
- else
- {
- virtuals = NULL_TREE;
- decl = build_decl (VAR_DECL, name, void_type_node);
- }
-
-#ifdef GATHER_STATISTICS
- n_vtables += 1;
- n_vtable_elems += list_length (virtuals);
-#endif
-
- /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
- import_export_vtable (decl, type);
-
- IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl);
- /* Initialize the association list for this type, based
- on our first approximation. */
- TYPE_BINFO_VTABLE (type) = decl;
- TYPE_BINFO_VIRTUALS (type) = virtuals;
-
- TREE_STATIC (decl) = 1;
- DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
- DECL_ALIGN (decl));
-
- if (binfo && write_virtuals >= 0)
- DECL_VIRTUAL_P (decl) = 1;
-#if 0
- /* Remember which class this vtable is really for. */
- if (binfo)
- DECL_VPARENT (decl) = BINFO_TYPE (binfo);
- else
- DECL_VPARENT (decl) = type;
-#endif
- DECL_CONTEXT (decl) = type;
-
- binfo = TYPE_BINFO (type);
- SET_BINFO_VTABLE_PATH_MARKED (binfo);
- SET_BINFO_NEW_VTABLE_MARKED (binfo);
- return decl;
-}
-
-/* Give TYPE a new virtual function table which is initialized
- with a skeleton-copy of its original initialization. The only
- entry that changes is the `delta' entry, so we can really
- share a lot of structure.
-
- FOR_TYPE is the derived type which caused this table to
- be needed.
-
- BINFO is the type association which provided TYPE for FOR_TYPE.
-
- The way we update BASE_BINFO's vtable information is just to change the
- association information in FOR_TYPE's association list. */
-static void
-prepare_fresh_vtable (binfo, base_binfo, for_type)
- tree binfo, base_binfo, for_type;
-{
- tree basetype = BINFO_TYPE (binfo);
- tree orig_decl = BINFO_VTABLE (binfo);
- tree name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type);
- tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
- tree path;
- int result;
-
- /* Remember which class this vtable is really for. */
-#if 0
- DECL_VPARENT (new_decl) = BINFO_TYPE (base_binfo);
-#endif
- DECL_CONTEXT (new_decl) = for_type;
-
- TREE_STATIC (new_decl) = 1;
- BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl);
- DECL_VIRTUAL_P (new_decl) = 1;
- DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);
-
- /* Make fresh virtual list, so we can smash it later. */
- BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
- /* Install the value for `headof' if that's what we're doing. */
- if (flag_dossier)
- TREE_VALUE (TREE_CHAIN (BINFO_VIRTUALS (binfo)))
- = build_vtable_entry (size_binop (MINUS_EXPR, integer_zero_node, BINFO_OFFSET (binfo)),
- FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (BINFO_VIRTUALS (binfo)))));
-
-#ifdef GATHER_STATISTICS
- n_vtables += 1;
- n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));
-#endif
-
- /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
- import_export_vtable (new_decl, for_type);
-
- if (TREE_VIA_VIRTUAL (binfo))
- my_friendly_assert (binfo == binfo_member (BINFO_TYPE (binfo),
- CLASSTYPE_VBASECLASSES (current_class_type)),
- 170);
- SET_BINFO_NEW_VTABLE_MARKED (binfo);
- SET_BINFO_VTABLE_PATH_MARKED (binfo);
-
- /* Mark all types between FOR_TYPE and TYPE as having been
- touched, so that if we change virtual function table entries,
- new vtables will be initialized. We may reach the virtual
- baseclass via ambiguous intervening baseclasses. This
- loop makes sure we get through to the actual baseclass we marked.
-
- Also, update the vtable entries to reflect the overrides
- of the top-most class (short of the top type). */
-
- do
- {
- result = get_base_distance (basetype, for_type, 0, &path);
- for_type = path;
- while (path)
- {
- tree path_binfo = path;
- tree path_type = BINFO_TYPE (path);
-
- if (TREE_VIA_VIRTUAL (path))
- path_binfo = binfo_member (path_type,
- CLASSTYPE_VBASECLASSES (current_class_type));
-
- SET_BINFO_VTABLE_PATH_MARKED (path_binfo);
- if (BINFO_INHERITANCE_CHAIN (path)
- && CLASSTYPE_VFIELD (path_type) != NULL_TREE
- && (DECL_NAME (CLASSTYPE_VFIELD (BINFO_TYPE (binfo)))
- == DECL_NAME (CLASSTYPE_VFIELD (path_type)))
- /* This is the baseclass just before the original FOR_TYPE. */
- && BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (path)) == NULL_TREE)
- {
- tree old_virtuals = TREE_CHAIN (BINFO_VIRTUALS (binfo));
- tree new_virtuals = TREE_CHAIN (BINFO_VIRTUALS (path_binfo));
- if (flag_dossier)
- {
- old_virtuals = TREE_CHAIN (old_virtuals);
- new_virtuals = TREE_CHAIN (new_virtuals);
- }
- while (old_virtuals)
- {
- TREE_VALUE (old_virtuals) = TREE_VALUE (new_virtuals);
- old_virtuals = TREE_CHAIN (old_virtuals);
- new_virtuals = TREE_CHAIN (new_virtuals);
- }
- }
- path = BINFO_INHERITANCE_CHAIN (path);
- }
- }
- while (result == -2);
-}
-
-/* Access the virtual function table entry that logically
- contains BASE_FNDECL. VIRTUALS is the virtual function table's
- initializer. */
-static tree
-get_vtable_entry (virtuals, base_fndecl)
- tree virtuals, base_fndecl;
-{
- unsigned HOST_WIDE_INT i = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
-#ifdef VTABLE_USES_MASK
- && 0
-#endif
- ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
- & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1))
- : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)));
-
-#ifdef GATHER_STATISTICS
- n_vtable_searches += i;
-#endif
-
- while (i > 0)
- {
- virtuals = TREE_CHAIN (virtuals);
- i -= 1;
- }
- return virtuals;
-}
-
-/* Put new entry ENTRY into virtual function table initializer
- VIRTUALS. The virtual function table is for type CONTEXT.
-
- Also update DECL_VINDEX (FNDECL). */
-
-static void
-modify_vtable_entry (old_entry_in_list, new_entry, fndecl, context)
- tree old_entry_in_list, new_entry, fndecl, context;
-{
- tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list));
- tree vindex;
-
- /* We can't put in the really right offset information
- here, since we have not yet laid out the class to
- take into account virtual base classes. */
- TREE_VALUE (old_entry_in_list) = new_entry;
- vindex = DECL_VINDEX (TREE_OPERAND (base_pfn, 0));
- if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
- DECL_VINDEX (fndecl) = vindex;
- else
- {
- if (! tree_int_cst_equal (DECL_VINDEX (fndecl), vindex))
- {
- tree elts = CONSTRUCTOR_ELTS (new_entry);
- tree vfield = CLASSTYPE_VFIELD (context);
-
- if (! doing_hard_virtuals)
- {
- pending_hard_virtuals
- = tree_cons (fndecl, FNADDR_FROM_VTABLE_ENTRY (new_entry),
- pending_hard_virtuals);
- TREE_TYPE (pending_hard_virtuals) = TREE_OPERAND (base_pfn, 0);
- return;
- }
-
-#if 0
- my_friendly_abort (3);
-
- /* Compute the relative offset of vtable we are really looking for. */
- TREE_VALUE (elts) = size_binop (PLUS_EXPR,
- size_int (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (vfield))
-/* ??? This may be wrong. */
- / BITS_PER_UNIT),
- TREE_VALUE (elts));
- /* Say what index to use when we use that vtable. */
-#ifndef VTABLE_USES_MASK
- vindex = build_int_2 (TREE_INT_CST_LOW (vindex)
- & ~((unsigned HOST_WIDE_INT) 1
- << (BITS_PER_WORD -1)), 0);
-#endif
- TREE_VALUE (TREE_CHAIN (elts)) = vindex;
-#endif
- }
- }
-}
-
-/* Check to ensure that the virtual function table slot in VFIELD,
- found by DECL_VINDEX of the BASE_FNDECL is in fact from a parent
- virtual function table that is the same parent as for the
- BASE_FNDECL given to us. */
-
-static int
-related_vslot (base_fndecl, vfields, type)
- tree base_fndecl, vfields, type;
-{
- tree base_context = TYPE_MAIN_VARIANT (DECL_CONTEXT (base_fndecl));
- tree base;
- tree path;
- int distance;
-
- if (TREE_CODE (vfields) != TREE_LIST)
- abort ();
- base = VF_NORMAL_VALUE (vfields);
- if (base == NULL_TREE)
- base = VF_BASETYPE_VALUE (vfields);
-
- /* The simple right way to do this is to ensure that the context of
- the base virtual function is found along the leftmost path
- between the most derived type associated with the vfield and the
- current type. */
- distance = get_base_distance (base, type, 0, &path);
- if (distance == -1)
- abort ();
- while (path)
- {
- if (BINFO_TYPE (path) == base_context)
- return 1;
- path = BINFO_INHERITANCE_CHAIN (path);
- }
-
- /* given:
- Rr
- / \
- Mm Hh
- \ /
- P
-
- make sure we fill in P's vtable for H with overrides of r,
- but be cautious of virtual base classes. */
- /* Combine the two below after debugging. */
- if (get_base_distance (base_context, base, 0, &path) != -1)
- {
- while (path)
- {
- if (TREE_VIA_VIRTUAL (path))
- return 0;
- path = BINFO_INHERITANCE_CHAIN (path);
- }
- return 1;
- }
- return 0;
-}
-
-/* Modify virtual function tables in lattice topped by T to
- place FNDECL in tables which previously held BASE_FNDECL.
- PFN is just FNDECL wrapped in an ADDR_EXPR, so that it
- is suitable for placement directly into an initializer.
-
- All distinct virtual function tables that this type uses
- must be updated. */
-static void
-modify_vtable_entries (t, fndecl, base_fndecl, pfn)
- tree t;
- tree fndecl, base_fndecl, pfn;
-{
- tree base_offset, offset;
- tree base_context = DECL_CLASS_CONTEXT (base_fndecl);
- tree context = DECL_CLASS_CONTEXT (fndecl);
- tree vfield = CLASSTYPE_VFIELD (t);
- tree vfields, vbases;
-
- DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);
-
- offset = integer_zero_node;
- if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
- {
- offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
- if (offset == NULL_TREE)
- {
- tree binfo = binfo_value (context, t);
- offset = BINFO_OFFSET (binfo);
- }
- }
-
- /* For each layer of base class (i.e., the first base class, and each
- virtual base class from that one), modify the virtual function table
- of the derived class to contain the new virtual function.
- A class has as many vfields as it has virtual base classes (total). */
- for (vfields = CLASSTYPE_VFIELDS (t); vfields; vfields = TREE_CHAIN (vfields))
- {
- int normal = 1;
- tree binfo, this_offset;
- tree base, path;
-
-/* This can go away when the new searching strategy as a little mileage on it. */
-#define NEW_SEARCH 1
-#if NEW_SEARCH
- if (!related_vslot (base_fndecl, vfields, t))
- continue;
-#endif
-
- /* Find the right base class for this derived class, call it BASE. */
- base = VF_BASETYPE_VALUE (vfields);
-
-#if NEW_SEARCH == 0
- if (base != base_context)
- {
- /* If BASE_FNDECL is not contained in the vtable accessed by
- the vslot, don't try to modify the vtable.
-
- Virtual functions from virtual baseclasses are not in derived
- virtual function tables. This is an implementation decision;
- it keeps there from being a combinatorial explosion in the
- number of different vtables which must be maintained. */
-
- /* In this case, we need to know whether BASE is derived
- from BASE_CONTEXT in any case, even the case where the
- derivation is ambiguous. */
- int distance = get_base_distance (base, base_context, 0, (tree *)0);
- if (distance < 0 && distance != -2)
- continue;
-
- /* BASE_FNDECL is defined in a class derived from
- the base class owning this VFIELD. */
- }
-#endif
-
- /* Get the path starting from the deepest base class CONTEXT
- of T (i.e., first defn of BASE_FNDECL). */
- get_base_distance (base_context, t, 0, &path);
-
- /* Get our best approximation of what to use for constructing
- the virtual function table for T. */
- do
- {
- /* Walk from base toward derived, stopping at the
- most derived baseclass that matters. That baseclass
- is exactly the one which provides the vtable along
- the VFIELD spine, but no more. */
- if (TREE_VIA_VIRTUAL (path))
- {
- base = path;
- binfo = binfo_member (BINFO_TYPE (base), CLASSTYPE_VBASECLASSES (t));
- break;
- }
- if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE
- || (BINFO_TYPE (BINFO_BASETYPE (BINFO_INHERITANCE_CHAIN (path), 0))
- != BINFO_TYPE (path))
- || BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (path)) == NULL_TREE)
- {
- base = path;
- binfo = base;
- break;
- }
- path = BINFO_INHERITANCE_CHAIN (path);
- }
- while (1);
-
- /* Find the right offset for the this pointer based on the base
- class we just found. */
- base_offset = BINFO_OFFSET (binfo);
- this_offset = size_binop (MINUS_EXPR, offset, base_offset);
-
- /* Make sure we can modify the derived association with immunity. */
- if (TREE_USED (TYPE_BINFO (t)))
- TYPE_BINFO (t) = copy_binfo (TYPE_BINFO (t));
-
- /* We call this case NORMAL iff this virtual function table
- pointer field has its storage reserved in this class.
- This is normally the case without virtual baseclasses
- or off-center multiple baseclasses. */
- normal = (vfield != NULL_TREE
- && VF_BASETYPE_VALUE (vfields) == DECL_FCONTEXT (vfield)
- && (VF_BINFO_VALUE (vfields) == NULL_TREE
- || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))));
-
- if (normal && VF_BINFO_VALUE (vfields))
- /* Everything looks normal so far...check that we are really
- working from VFIELD's basetype, and not some other appearance
- of that basetype in the lattice. */
- normal = (VF_BINFO_VALUE (vfields)
- == get_binfo (VF_BASETYPE_VALUE (vfields), t, 0));
-
- if (normal)
- {
- /* In this case, it is *type*'s vtable we are modifying.
- We start with the approximation that it's vtable is that
- of the immediate base class. */
- base_context = t;
- binfo = TYPE_BINFO (t);
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
- }
- else
- {
- /* This is our very own copy of `basetype' to play with.
- Later, we will fill in all the virtual functions
- that override the virtual functions in these base classes
- which are not defined by the current type. */
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- prepare_fresh_vtable (binfo, base, t);
- }
-
- modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl),
- build_vtable_entry (this_offset, pfn),
- fndecl, base_context);
- }
- for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
- {
- tree this_offset;
- tree base, path;
-
- if (! BINFO_VTABLE (vbases))
- /* There are only two ways that a type can fail to have
- virtual functions: neither it nor any of its base
- types define virtual functions (in which case
- no updating need be done), or virtual functions
- accessible to it come from virtual base classes
- (in which case we have or will get them modified
- in other passes of this loop). */
- continue;
-
- base = BINFO_TYPE (vbases);
- path = NULL_TREE;
-
- if (base != base_context
- && get_base_distance (base_context, base, 0, &path) == -1)
- continue;
-
- if (path)
- this_offset = size_binop (MINUS_EXPR, offset, BINFO_OFFSET (path));
- else
- this_offset = offset;
-
- /* Doesn't matter if not actually from this virtual base class,
- but shouldn't come from deeper virtual baseclasses. The enclosing
- loop should take care of such baseclasses. */
- while (path)
- {
- if (TREE_VIA_VIRTUAL (path))
- goto skip;
- path = BINFO_INHERITANCE_CHAIN (path);
- }
-
- base_offset = BINFO_OFFSET (vbases);
- this_offset = size_binop (MINUS_EXPR, this_offset, base_offset);
-
- /* Make sure we can modify the derived association with immunity. */
- if (TREE_USED (TYPE_BINFO (t)))
- TYPE_BINFO (t) = copy_binfo (TYPE_BINFO (t));
-
- /* This is our very own copy of `basetype' to play with. */
- if (! BINFO_NEW_VTABLE_MARKED (vbases))
- {
- tree context_binfo = binfo_value (base_context, base);
- prepare_fresh_vtable (vbases, context_binfo, t);
- }
- modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (vbases), base_fndecl),
- build_vtable_entry (this_offset, pfn),
- fndecl, base_context);
- skip: {}
- }
-}
-
-static tree
-add_virtual_function (pending_virtuals, has_virtual, x, t)
- tree pending_virtuals;
- int *has_virtual;
- tree x;
- tree t; /* Structure type. */
-{
- int debug_vbase = 1;
-
- /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
- convert to void *. Make such a conversion here. */
- tree vfn = build1 (ADDR_EXPR, ptr_type_node, x);
- TREE_CONSTANT (vfn) = 1;
-
- /* current_class_type may be NULL_TREE in case of error. */
- if (current_class_type)
- TREE_ADDRESSABLE (x) = CLASSTYPE_VTABLE_NEEDS_WRITING (current_class_type);
-
- /* If the virtual function is a redefinition of a prior one,
- figure out in which base class the new definition goes,
- and if necessary, make a fresh virtual function table
- to hold that entry. */
- if (DECL_VINDEX (x) == error_mark_node)
- {
- tree entry = build_vtable_entry (integer_zero_node, vfn);
-
- if (flag_dossier && *has_virtual == 0)
- {
- /* CLASSTYPE_DOSSIER is only used as a Boolean (NULL or not). */
- CLASSTYPE_DOSSIER (t) = integer_one_node;
- *has_virtual = 1;
- }
-
- /* Build a new INT_CST for this DECL_VINDEX. */
-#ifdef VTABLE_USES_MASK
- SET_DECL_VINDEX (x, build_int_2 (++(*has_virtual), 0));
-#else
- {
- static tree index_table[256];
- tree index;
- int i = ++(*has_virtual);
-
- if (i >= 256 || index_table[i] == 0)
- {
- index = build_int_2 (((unsigned HOST_WIDE_INT) 1
- << (BITS_PER_WORD - 1)) | i, ~0);
- if (i < 256)
- index_table[i] = index;
- }
- else
- index = index_table[i];
-
- DECL_VINDEX (x) = index;
- }
-#endif
- pending_virtuals = tree_cons (DECL_VINDEX (x), entry, pending_virtuals);
- }
- /* Happens if declared twice in class or we're not in a class definition.
- We will give error later or we've already given it. */
- else if (TREE_CODE (DECL_VINDEX (x)) == INTEGER_CST
- || current_class_type == NULL_TREE)
- return pending_virtuals;
- else if (debug_vbase && TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- {
- /* Need an entry in some other virtual function table.
- Deal with this after we have laid out our virtual base classes. */
- pending_hard_virtuals = temp_tree_cons (x, vfn, pending_hard_virtuals);
- }
- else
- {
- /* Need an entry in some other virtual function table.
- We can do this now. */
- tree base_fndecl_list = DECL_VINDEX (x), base_fndecls, prev = 0;
- tree vtable_context = DECL_FCONTEXT (CLASSTYPE_VFIELD (current_class_type));
- tree true_base_fndecl = 0;
-
- /* First assign DECL_VINDEX from the base vfn with which
- we share our vtable. */
- base_fndecls = base_fndecl_list;
- while (base_fndecls)
- {
- if (TREE_CHAIN (base_fndecls) == NULL_TREE
- || DECL_FCONTEXT (CLASSTYPE_VFIELD (DECL_CLASS_CONTEXT (TREE_VALUE (base_fndecls)))) == vtable_context)
- {
- true_base_fndecl = TREE_VALUE (base_fndecls);
- modify_vtable_entries (current_class_type, x,
- true_base_fndecl, vfn);
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (base_fndecls);
- else
- base_fndecl_list = prev;
- break;
- }
- prev = base_fndecls;
- base_fndecls = TREE_CHAIN (base_fndecls);
- }
-
- /* Now fill in the rest of the vtables. */
- base_fndecls = base_fndecl_list;
- while (base_fndecls)
- {
- /* If we haven't found one we like, first one wins. */
- if (true_base_fndecl == 0)
- true_base_fndecl = TREE_VALUE (base_fndecls);
-
- modify_vtable_entries (current_class_type, x,
- TREE_VALUE (base_fndecls), vfn);
- base_fndecls = TREE_CHAIN (base_fndecls);
- }
-
- DECL_CONTEXT (x) = DECL_CONTEXT (true_base_fndecl);
- }
- return pending_virtuals;
-}
-
-/* Obstack on which to build the vector of class methods. */
-struct obstack class_obstack;
-extern struct obstack *current_obstack;
-
-/* Add method METHOD to class TYPE. This is used when a method
- has been defined which did not initially appear in the class definition,
- and helps cut down on spurious error messages.
-
- FIELDS is the entry in the METHOD_VEC vector entry of the class type where
- the method should be added. */
-void
-add_method (type, fields, method)
- tree type, *fields, method;
-{
- /* We must make a copy of METHOD here, since we must be sure that
- we have exclusive title to this method's DECL_CHAIN. */
- tree decl;
-
- push_obstacks (&permanent_obstack, &permanent_obstack);
- {
- decl = copy_node (method);
- if (DECL_RTL (decl) == 0
- && (!processing_template_decl
- || !uses_template_parms (decl)))
- {
- make_function_rtl (decl);
- DECL_RTL (method) = DECL_RTL (decl);
- }
- }
-
- if (fields && *fields)
- {
- /* Take care not to hide destructor. */
- DECL_CHAIN (decl) = DECL_CHAIN (*fields);
- DECL_CHAIN (*fields) = decl;
- }
- else if (CLASSTYPE_METHOD_VEC (type) == 0)
- {
- tree method_vec = make_node (TREE_VEC);
- if (TYPE_IDENTIFIER (type) == DECL_NAME (decl))
- {
- TREE_VEC_ELT (method_vec, 0) = decl;
- TREE_VEC_LENGTH (method_vec) = 1;
- }
- else
- {
- /* ??? Is it possible for there to have been enough room in the
- current chunk for the tree_vec structure but not a tree_vec
- plus a tree*? Will this work in that case? */
- obstack_free (current_obstack, method_vec);
- obstack_blank (current_obstack, sizeof (struct tree_vec) + sizeof (tree *));
- TREE_VEC_ELT (method_vec, 1) = decl;
- TREE_VEC_LENGTH (method_vec) = 2;
- obstack_finish (current_obstack);
- }
- CLASSTYPE_METHOD_VEC (type) = method_vec;
- }
- else
- {
- tree method_vec = CLASSTYPE_METHOD_VEC (type);
- int len = TREE_VEC_LENGTH (method_vec);
-
- /* Adding a new ctor or dtor. This is easy because our
- METHOD_VEC always has a slot for such entries. */
- if (TYPE_IDENTIFIER (type) == DECL_NAME (decl))
- {
- /* TREE_VEC_ELT (method_vec, 0) = decl; */
- if (decl != TREE_VEC_ELT (method_vec, 0))
- {
- DECL_CHAIN (decl) = TREE_VEC_ELT (method_vec, 0);
- TREE_VEC_ELT (method_vec, 0) = decl;
- }
- }
- else
- {
- /* This is trickier. We try to extend the TREE_VEC in-place,
- but if that does not work, we copy all its data to a new
- TREE_VEC that's large enough. */
- struct obstack *ob = &class_obstack;
- tree *end = (tree *)obstack_next_free (ob);
-
- if (end != TREE_VEC_END (method_vec))
- {
- ob = current_obstack;
- TREE_VEC_LENGTH (method_vec) += 1;
- TREE_VEC_ELT (method_vec, len) = NULL_TREE;
- method_vec = copy_node (method_vec);
- TREE_VEC_LENGTH (method_vec) -= 1;
- }
- else
- {
- tree tmp_vec = (tree) obstack_base (ob);
- if (obstack_room (ob) < sizeof (tree))
- {
- obstack_blank (ob, sizeof (struct tree_common)
- + tree_code_length[(int) TREE_VEC]
- * sizeof (char *)
- + len * sizeof (tree));
- tmp_vec = (tree) obstack_base (ob);
- bcopy (method_vec, tmp_vec,
- (sizeof (struct tree_common)
- + tree_code_length[(int) TREE_VEC] * sizeof (char *)
- + (len-1) * sizeof (tree)));
- method_vec = tmp_vec;
- }
- else
- obstack_blank (ob, sizeof (tree));
- }
-
- obstack_finish (ob);
- TREE_VEC_ELT (method_vec, len) = decl;
- TREE_VEC_LENGTH (method_vec) = len + 1;
- CLASSTYPE_METHOD_VEC (type) = method_vec;
-
- if (TYPE_BINFO_BASETYPES (type) && CLASSTYPE_BASELINK_VEC (type))
- {
- /* ??? May be better to know whether these can be extended? */
- tree baselink_vec = CLASSTYPE_BASELINK_VEC (type);
-
- TREE_VEC_LENGTH (baselink_vec) += 1;
- CLASSTYPE_BASELINK_VEC (type) = copy_node (baselink_vec);
- TREE_VEC_LENGTH (baselink_vec) -= 1;
-
- TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), len) = 0;
- }
- }
- }
- DECL_CONTEXT (decl) = type;
- DECL_CLASS_CONTEXT (decl) = type;
-
- pop_obstacks ();
-}
-
-/* Subroutines of finish_struct. */
-
-/* Look through the list of fields for this struct, deleting
- duplicates as we go. This must be recursive to handle
- anonymous unions.
-
- FIELD is the field which may not appear anywhere in FIELDS.
- FIELD_PTR, if non-null, is the starting point at which
- chained deletions may take place.
- The value returned is the first acceptable entry found
- in FIELDS.
-
- Note that anonymous fields which are not of UNION_TYPE are
- not duplicates, they are just anonymous fields. This happens
- when we have unnamed bitfields, for example. */
-static tree
-delete_duplicate_fields_1 (field, field_ptr, fields)
- tree field, *field_ptr, fields;
-{
- tree x;
- tree prev = field_ptr ? *field_ptr : 0;
- if (DECL_NAME (field) == 0)
- {
- if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE)
- return fields;
-
- for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x))
- fields = delete_duplicate_fields_1 (x, field_ptr, fields);
- if (prev)
- TREE_CHAIN (prev) = fields;
- return fields;
- }
- else
- {
- for (x = fields; x; prev = x, x = TREE_CHAIN (x))
- {
- if (DECL_NAME (x) == 0)
- {
- if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE)
- continue;
- TYPE_FIELDS (TREE_TYPE (x))
- = delete_duplicate_fields_1 (field, (tree *)0, TYPE_FIELDS (TREE_TYPE (x)));
- if (TYPE_FIELDS (TREE_TYPE (x)) == 0)
- {
- if (prev == 0)
- fields = TREE_CHAIN (fields);
- else
- TREE_CHAIN (prev) = TREE_CHAIN (x);
- }
- }
- else
- {
- if (DECL_NAME (field) == DECL_NAME (x))
- {
- if (TREE_CODE (field) == CONST_DECL
- && TREE_CODE (x) == CONST_DECL)
- error_with_decl (x, "duplicate enum value `%s'");
- else if (TREE_CODE (field) == CONST_DECL
- || TREE_CODE (x) == CONST_DECL)
- error_with_decl (x, "duplicate field `%s' (as enum and non-enum)");
- else if (TREE_CODE (field) == TYPE_DECL
- && TREE_CODE (x) == TYPE_DECL)
- error_with_decl (x, "duplicate class scope type `%s'");
- else if (TREE_CODE (field) == TYPE_DECL
- || TREE_CODE (x) == TYPE_DECL)
- error_with_decl (x, "duplicate field `%s' (as type and non-type)");
- else
- error_with_decl (x, "duplicate member `%s'");
- if (prev == 0)
- fields = TREE_CHAIN (fields);
- else
- TREE_CHAIN (prev) = TREE_CHAIN (x);
- }
- }
- }
- }
- return fields;
-}
-
-static void
-delete_duplicate_fields (fields)
- tree fields;
-{
- tree x;
- for (x = fields; x && TREE_CHAIN (x); x = TREE_CHAIN (x))
- TREE_CHAIN (x) = delete_duplicate_fields_1 (x, &x, TREE_CHAIN (x));
-}
-
-/* Change the visibility of T::FDECL to VISIBILITY.
- Return 1 if change was legit, otherwise return 0. */
-static int
-alter_visibility (t, fdecl, visibility)
- tree t;
- tree fdecl;
- enum visibility_type visibility;
-{
- tree elem = purpose_member (t, DECL_VISIBILITY (fdecl));
- if (elem && TREE_VALUE (elem) != (tree)visibility)
- {
- if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL)
- {
- error_with_decl (TREE_TYPE (fdecl), "conflicting visibility specifications for method `%s', ignored");
- }
- else error ("conflicting visibility specifications for field `%s', ignored", IDENTIFIER_POINTER (DECL_NAME (fdecl)));
- }
- else if (TREE_PRIVATE (fdecl) && visibility != visibility_private)
- error_with_decl (fdecl, "cannot make private `%s' non-private");
- else if (TREE_PROTECTED (fdecl) && visibility == visibility_public)
- error_with_decl (fdecl, "cannot make protected `%s' public");
- /* ARM 11.3: an access declaration may not be used to restrict access
- to a member that is accessible in the base class. */
- else if (TREE_PUBLIC (fdecl)
- && (visibility == visibility_private
- || visibility == visibility_protected))
- error_with_decl (fdecl, "cannot reduce visibility of public member `%s'");
- else if (elem == NULL_TREE)
- {
- DECL_VISIBILITY (fdecl) = tree_cons (t, (tree)visibility,
- DECL_VISIBILITY (fdecl));
- return 1;
- }
- return 0;
-}
-
-static tree
-get_vfield_offset (binfo)
- tree binfo;
-{
- return size_binop (PLUS_EXPR,
- DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
- BINFO_OFFSET (binfo));
-}
-
-/* If FOR_TYPE needs to reinitialize virtual function table pointers
- for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.
- Returns BASE_INIT_LIST appropriately modified. */
-
-static tree
-maybe_fixup_vptrs (for_type, binfo, base_init_list)
- tree for_type, binfo, base_init_list;
-{
- /* Now reinitialize any slots that don't fall under our virtual
- function table pointer. */
- tree vfields = CLASSTYPE_VFIELDS (BINFO_TYPE (binfo));
- while (vfields)
- {
- tree base_binfo = get_binfo (VF_BASETYPE_VALUE (vfields), for_type, 0);
- if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (VF_BASETYPE_VALUE (vfields)))
- {
- tree base_offset = get_vfield_offset (base_binfo);
- if (! tree_int_cst_equal (base_offset, get_vfield_offset (TYPE_BINFO (for_type)))
- && ! tree_int_cst_equal (base_offset, get_vfield_offset (binfo)))
- base_init_list = tree_cons (error_mark_node, base_binfo,
- base_init_list);
- }
- vfields = TREE_CHAIN (vfields);
- }
- return base_init_list;
-}
-
-/* If TYPE does not have a constructor, then the compiler must
- manually deal with all of the initialization this type requires.
-
- If a base initializer exists only to fill in the virtual function
- table pointer, then we mark that fact with the TREE_VIRTUAL bit.
- This way, we avoid multiple initializations of the same field by
- each virtual function table up the class hierarchy.
-
- Virtual base class pointers are not initialized here. They are
- initialized only at the "top level" of object creation. If we
- initialized them here, we would have to skip a lot of work. */
-
-static void
-build_class_init_list (type)
- tree type;
-{
- tree base_init_list = NULL_TREE;
- tree member_init_list = NULL_TREE;
-
- /* Since we build member_init_list and base_init_list using
- tree_cons, backwards fields the all through work. */
- tree x;
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (x = TYPE_FIELDS (type); x; x = TREE_CHAIN (x))
- {
- if (TREE_CODE (x) != FIELD_DECL)
- continue;
-
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (x))
- || DECL_INITIAL (x) != NULL_TREE)
- member_init_list = tree_cons (x, type, member_init_list);
- }
- member_init_list = nreverse (member_init_list);
-
- /* We will end up doing this last. Need special marker
- to avoid infinite regress. */
- if (TYPE_VIRTUAL_P (type))
- {
- base_init_list = build_tree_list (error_mark_node, TYPE_BINFO (type));
- if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (type) == 0)
- TREE_VALUE (base_init_list) = NULL_TREE;
- TREE_ADDRESSABLE (base_init_list) = 1;
- }
-
- /* Each base class which needs to have initialization
- of some kind gets to make such requests known here. */
- for (i = n_baseclasses-1; i >= 0; i--)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree blist;
-
- /* Don't initialize virtual baseclasses this way. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (base_binfo)))
- {
- /* ...and the last shall come first... */
- base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list);
- base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list);
- continue;
- }
-
- if ((blist = CLASSTYPE_BASE_INIT_LIST (BINFO_TYPE (base_binfo))) == NULL_TREE)
- /* Nothing to initialize. */
- continue;
-
- /* ...ditto... */
- base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list);
-
- /* This is normally true for single inheritance.
- The win is we can shrink the chain of initializations
- to be done by only converting to the actual type
- we are interested in. */
- if (TREE_VALUE (blist)
- && TREE_CODE (TREE_VALUE (blist)) == TREE_VEC
- && tree_int_cst_equal (BINFO_OFFSET (base_binfo),
- BINFO_OFFSET (TREE_VALUE (blist))))
- {
- if (base_init_list)
- {
- /* Does it do more than just fill in a
- virtual function table pointer? */
- if (! TREE_ADDRESSABLE (blist))
- base_init_list = build_tree_list (blist, base_init_list);
- /* Can we get by just with the virtual function table
- pointer that it fills in? */
- else if (TREE_ADDRESSABLE (base_init_list)
- && TREE_VALUE (base_init_list) == 0)
- base_init_list = blist;
- /* Maybe, but it is not obvious as the previous case. */
- else if (! CLASSTYPE_NEEDS_VIRTUAL_REINIT (type))
- {
- tree last = tree_last (base_init_list);
- while (TREE_VALUE (last)
- && TREE_CODE (TREE_VALUE (last)) == TREE_LIST)
- last = tree_last (TREE_VALUE (last));
- if (TREE_VALUE (last) == 0)
- base_init_list = build_tree_list (blist, base_init_list);
- }
- }
- else
- base_init_list = blist;
- }
- else
- {
- /* The function expand_aggr_init knows how to do the
- initialization of `basetype' without getting
- an explicit `blist'. */
- if (base_init_list)
- base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list);
- else
- base_init_list = CLASSTYPE_BINFO_AS_LIST (BINFO_TYPE (base_binfo));
- }
- }
-
- if (base_init_list)
- if (member_init_list)
- CLASSTYPE_BASE_INIT_LIST (type) = build_tree_list (base_init_list, member_init_list);
- else
- CLASSTYPE_BASE_INIT_LIST (type) = base_init_list;
- else if (member_init_list)
- CLASSTYPE_BASE_INIT_LIST (type) = member_init_list;
-}
-
-struct base_info
-{
- int has_virtual;
- int max_has_virtual;
- int n_ancestors;
- tree vfield;
- tree vfields;
- char needs_default_ctor;
- char cant_have_default_ctor;
- char needs_const_ctor;
- char cant_have_const_ctor;
- char members_need_dtors;
- char needs_virtual_dtor;
-};
-
-/* Record information about type T derived from its base classes.
- Store most of that information in T itself, and place the
- remaining information in the struct BASE_INFO.
-
- Propagate basetype offsets throughout the lattice. Note that the
- lattice topped by T is really a pair: it's a DAG that gives the
- structure of the derivation hierarchy, and it's a list of the
- virtual baseclasses that appear anywhere in the DAG. When a vbase
- type appears in the DAG, it's offset is 0, and it's children start
- their offsets from that point. When a vbase type appears in the list,
- its offset is the offset it has in the hierarchy, and its children's
- offsets include that offset in theirs.
-
- Returns the index of the first base class to have virtual functions,
- or zero if no such base class. */
-
-static int
-finish_base_struct (t, b, binfos)
- tree t;
- struct base_info *b;
- tree binfos;
-{
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int first_vfn_base_index = -1;
- bzero (b, sizeof (struct base_info));
-
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree basetype = BINFO_TYPE (base_binfo);
-
- /* If the type of basetype is incomplete, then
- we already complained about that fact
- (and we should have fixed it up as well). */
- if (TYPE_SIZE (basetype) == 0)
- {
- int j;
- /* The base type is of incomplete type. It is
- probably best to pretend that it does not
- exist. */
- if (i == n_baseclasses-1)
- TREE_VEC_ELT (binfos, i) = NULL_TREE;
- TREE_VEC_LENGTH (binfos) -= 1;
- n_baseclasses -= 1;
- for (j = i; j+1 < n_baseclasses; j++)
- TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
- }
-
- if (TYPE_NEEDS_DESTRUCTOR (basetype))
- b->members_need_dtors = 1;
- if (TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
- b->needs_default_ctor = 1;
- else if (TYPE_HAS_CONSTRUCTOR (basetype))
- b->cant_have_default_ctor = 1;
- if (TYPE_GETS_CONST_INIT_REF (basetype))
- b->needs_const_ctor = 1;
- else if (TYPE_GETS_INIT_REF (basetype))
- b->cant_have_const_ctor = 1;
-
- CLASSTYPE_ALTERS_VISIBILITIES_P (t)
- |= CLASSTYPE_ALTERS_VISIBILITIES_P (basetype);
-
- b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
- TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
- TYPE_NEEDS_CONSTRUCTOR (t) |= TYPE_NEEDS_CONSTRUCTOR (basetype);
- TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
- TYPE_GETS_ASSIGNMENT (t) |= TYPE_GETS_ASSIGNMENT (basetype);
- TYPE_GETS_INIT_REF (t) |= TYPE_GETS_INIT_REF (basetype);
-
- TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype);
- TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
- TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
-
- if (! TREE_VIA_VIRTUAL (base_binfo)
-#if 0
- /* This cannot be done, as prepare_fresh_vtable wants to modify
- binfos associated with vfields anywhere in the hierarchy, not
- just immediate base classes. Due to unsharing, the compiler
- might consume 3% more memory on a real program.
- */
- && ! BINFO_OFFSET_ZEROP (base_binfo)
-#endif
- && BINFO_BASETYPES (base_binfo))
- {
- tree base_binfos = BINFO_BASETYPES (base_binfo);
- tree chain = NULL_TREE;
- int j;
-
- /* Now unshare the structure beneath BASE_BINFO. */
- for (j = TREE_VEC_LENGTH (base_binfos)-1;
- j >= 0; j--)
- {
- tree base_base_binfo = TREE_VEC_ELT (base_binfos, j);
- if (! TREE_VIA_VIRTUAL (base_base_binfo))
- TREE_VEC_ELT (base_binfos, j)
- = make_binfo (BINFO_OFFSET (base_base_binfo),
- BINFO_TYPE (base_base_binfo),
- BINFO_VTABLE (base_base_binfo),
- BINFO_VIRTUALS (base_base_binfo),
- chain);
- chain = TREE_VEC_ELT (base_binfos, j);
- TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
- TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
- }
-
- /* Completely unshare potentially shared data, and
- update what is ours. */
- propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
- }
-
- if (! TREE_VIA_VIRTUAL (base_binfo))
- CLASSTYPE_N_SUPERCLASSES (t) += 1;
-
- if (TYPE_VIRTUAL_P (basetype))
- {
- /* If there's going to be a destructor needed, make
- sure it will be virtual. */
- b->needs_virtual_dtor = 1;
-
- /* Don't borrow virtuals from virtual baseclasses. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- if (first_vfn_base_index < 0)
- {
- first_vfn_base_index = i;
-
- b->has_virtual = CLASSTYPE_VSIZE (basetype);
- b->vfield = CLASSTYPE_VFIELD (basetype);
- b->vfields = CLASSTYPE_VFIELDS (basetype);
- CLASSTYPE_VFIELD (t) = b->vfield;
- }
- else
- {
- /* Only add unique vfields, and flatten them out as we go. */
- tree vfields = CLASSTYPE_VFIELDS (basetype);
- while (vfields)
- {
- if (VF_BINFO_VALUE (vfields) == NULL_TREE
- || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields)))
- {
- tree value = VF_BASETYPE_VALUE (vfields);
- b->vfields = tree_cons (base_binfo, value, b->vfields);
- if (DECL_NAME (CLASSTYPE_VFIELD (value))
- == DECL_NAME (CLASSTYPE_VFIELD (basetype)))
- VF_NORMAL_VALUE (b->vfields) = basetype;
- else
- VF_NORMAL_VALUE (b->vfields) = VF_NORMAL_VALUE (vfields);
- }
- vfields = TREE_CHAIN (vfields);
- }
-
- if (b->has_virtual == 0)
- {
- first_vfn_base_index = i;
- b->has_virtual = CLASSTYPE_VSIZE (basetype);
- b->vfield = CLASSTYPE_VFIELD (basetype);
- CLASSTYPE_VFIELD (t) = b->vfield;
- }
- }
- }
- }
-
- {
- tree vfields;
- /* Find the base class with the largest number of virtual functions. */
- for (vfields = b->vfields; vfields; vfields = TREE_CHAIN (vfields))
- {
- if (CLASSTYPE_VSIZE (VF_BASETYPE_VALUE (vfields)) > b->max_has_virtual)
- b->max_has_virtual = CLASSTYPE_VSIZE (VF_BASETYPE_VALUE (vfields));
- if (VF_DERIVED_VALUE (vfields)
- && CLASSTYPE_VSIZE (VF_DERIVED_VALUE (vfields)) > b->max_has_virtual)
- b->max_has_virtual = CLASSTYPE_VSIZE (VF_DERIVED_VALUE (vfields));
- }
- }
-
- if (b->vfield == 0)
- /* If all virtual functions come only from virtual baseclasses. */
- return -1;
- return first_vfn_base_index;
-}
-
-static int
-typecode_p (type, code)
- tree type;
- enum tree_code code;
-{
- return (TREE_CODE (type) == code
- || (TREE_CODE (type) == REFERENCE_TYPE
- && TREE_CODE (TREE_TYPE (type)) == code));
-}
-
-/* Set memoizing fields and bits of T (and its variants) for later use.
- MAX_HAS_VIRTUAL is the largest size of any T's virtual function tables. */
-static void
-finish_struct_bits (t, max_has_virtual)
- tree t;
- int max_has_virtual;
-{
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
- tree method_vec = CLASSTYPE_METHOD_VEC (t);
-
- /* Fix up variants (if any). */
- tree variants = TYPE_NEXT_VARIANT (t);
- while (variants)
- {
- /* These fields are in the _TYPE part of the node, not in
- the TYPE_LANG_SPECIFIC component, so they are not shared. */
- TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
- TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);
- TYPE_NEEDS_CONSTRUCTOR (variants) = TYPE_NEEDS_CONSTRUCTOR (t);
- TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
- TYPE_NEEDS_DESTRUCTOR (variants) = TYPE_NEEDS_DESTRUCTOR (t);
-
- TYPE_USES_COMPLEX_INHERITANCE (variants) = TYPE_USES_COMPLEX_INHERITANCE (t);
- TYPE_VIRTUAL_P (variants) = TYPE_VIRTUAL_P (t);
- TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t);
- /* Copy whatever these are holding today. */
- TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t);
- TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t);
- variants = TYPE_NEXT_VARIANT (variants);
- }
-
- if (n_baseclasses && max_has_virtual)
- {
- /* Done by `finish_struct' for classes without baseclasses. */
- int has_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0;
- tree binfos = TYPE_BINFO_BASETYPES (t);
- for (i = n_baseclasses-1; i >= 0; i--)
- {
- has_abstract_virtuals
- |= (CLASSTYPE_ABSTRACT_VIRTUALS (BINFO_TYPE (TREE_VEC_ELT (binfos, i))) != 0);
- if (has_abstract_virtuals)
- break;
- }
- if (has_abstract_virtuals)
- CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
- }
-
- if (n_baseclasses)
- {
- /* Notice whether this class has type conversion functions defined.
- Also report whether joining two types yields an ambiguity in the
- virtual function table, e.g.,
-
- struct A { virtual int f (); };
- struct B { virtual int f (); };
- struct C : A, B { / * no f (); * / }; / / error, ambiguous
- */
- tree binfo = TYPE_BINFO (t);
- tree binfos = BINFO_BASETYPES (binfo);
- int n_binfos = list_length (binfo);
- tree vbases = CLASSTYPE_VBASECLASSES (t), basetype;
- int n_vbases = list_length (vbases), j;
-
- build_mi_virtuals (n_binfos+n_vbases*n_baseclasses, max_has_virtual);
- /* Fill in virtual function table with values which do not come
- "normal"ly, i.e., those which come from virtual and/or
- non-leftmost base classes. */
- for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
- {
- if (TREE_VIA_VIRTUAL (binfo))
- /* Virtual functions from virtual baseclasses are done below. */;
- else if (CLASSTYPE_VSIZE (BINFO_TYPE (binfo)))
- {
- tree virtuals = TREE_CHAIN (BINFO_VIRTUALS (binfo));
- if (flag_dossier)
- virtuals = TREE_CHAIN (virtuals);
- add_mi_virtuals (++i, virtuals);
- }
- }
- for (; vbases; vbases = TREE_CHAIN (vbases))
- {
- basetype = BINFO_TYPE (vbases);
- if (CLASSTYPE_VSIZE (basetype))
- for (j = n_baseclasses-1; j >= 0; j--)
- {
- tree this_binfo = TREE_VEC_ELT (binfos, j);
- if (UNIQUELY_DERIVED_FROM_P (basetype, this_binfo))
- {
- tree virtuals = TREE_CHAIN (BINFO_VIRTUALS (vbases));
- if (flag_dossier)
- virtuals = TREE_CHAIN (virtuals);
- add_mi_virtuals (++i, virtuals);
- }
- }
- }
- for (i = n_baseclasses-1; i >= 0; i--)
- {
- basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
-
- if (TYPE_HAS_CONVERSION (basetype))
- {
- TYPE_HAS_CONVERSION (t) = 1;
- TYPE_HAS_INT_CONVERSION (t) |= TYPE_HAS_INT_CONVERSION (basetype);
- TYPE_HAS_REAL_CONVERSION (t) |= TYPE_HAS_REAL_CONVERSION (basetype);
- }
- if (CLASSTYPE_MAX_DEPTH (basetype) >= CLASSTYPE_MAX_DEPTH (t))
- CLASSTYPE_MAX_DEPTH (t) = CLASSTYPE_MAX_DEPTH (basetype) + 1;
- }
- report_ambiguous_mi_virtuals (n_binfos+n_vbases*n_baseclasses, t);
-#if 0
- /* Now that we know what the virtual function table looks like,
- fix up offsets in the presence of virtual base classes. */
- if (n_vbases)
- fixup_vbase_offsets (t);
-#endif
- }
-
- /* Need to test METHOD_VEC here in case all methods
- (conversions and otherwise) are inherited. */
- if (TYPE_HAS_CONVERSION (t) && method_vec != NULL_TREE)
- {
- tree first_conversions[last_conversion_type];
- tree last_conversions[last_conversion_type];
- enum conversion_type conv_index;
- tree *tmp;
- int i;
-
- bzero (first_conversions, sizeof (first_conversions));
- bzero (last_conversions, sizeof (last_conversions));
- for (tmp = &TREE_VEC_ELT (method_vec, 1);
- tmp != TREE_VEC_END (method_vec); tmp += 1)
- {
- /* ??? This should compare DECL_NAME (*tmp) == ansi_opname[TYPE_EXPR]. */
- if (IDENTIFIER_TYPENAME_P (DECL_ASSEMBLER_NAME (*tmp)))
- {
- tree fntype = TREE_TYPE (*tmp);
- tree return_type = TREE_TYPE (fntype);
- my_friendly_assert (TREE_CODE (fntype) == METHOD_TYPE, 171);
-
- if (typecode_p (return_type, POINTER_TYPE))
- {
- if (TYPE_READONLY (TREE_TYPE (return_type)))
- conv_index = constptr_conv;
- else
- conv_index = ptr_conv;
- }
- else if (typecode_p (return_type, INTEGER_TYPE))
- {
- TYPE_HAS_INT_CONVERSION (t) = 1;
- conv_index = int_conv;
- }
- else if (typecode_p (return_type, REAL_TYPE))
- {
- TYPE_HAS_REAL_CONVERSION (t) = 1;
- conv_index = real_conv;
- }
- else
- continue;
-
- if (first_conversions[(int) conv_index] == NULL_TREE)
- first_conversions[(int) conv_index] = *tmp;
- last_conversions[(int) conv_index] = *tmp;
- }
- }
-
- for (i = 0; i < (int) last_conversion_type; i++)
- if (first_conversions[i] != last_conversions[i])
- CLASSTYPE_CONVERSION (t, i) = error_mark_node;
- else
- CLASSTYPE_CONVERSION (t, i) = first_conversions[i];
- }
-
- /* If this type has constructors, force its mode to be BLKmode,
- and force its TREE_ADDRESSABLE bit to be nonzero. */
- if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t))
- {
- tree variants = t;
-
- if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
- DECL_MODE (TYPE_NAME (t)) = BLKmode;
- while (variants)
- {
- TYPE_MODE (variants) = BLKmode;
- TREE_ADDRESSABLE (variants) = 1;
- variants = TYPE_NEXT_VARIANT (variants);
- }
- }
-}
-
-/* Warn about duplicate methods in fn_fields. Also compact method
- lists so that lookup can be made faster.
-
- Algorithm: Outer loop builds lists by method name. Inner loop
- checks for redundant method names within a list.
-
- Data Structure: List of method lists. The outer list is a
- TREE_LIST, whose TREE_PURPOSE field is the field name and the
- TREE_VALUE is the TREE_CHAIN of the FUNCTION_DECLs. Friends are
- chained in the same way as member functions, but they live in the
- TREE_TYPE field of the outer list. That allows them to be quickly
- deleted, and requires no extra storage.
-
- If there are any constructors/destructors, they are moved to the
- front of the list. This makes pushclass more efficient.
-
- We also link each field which has shares a name with its baseclass
- to the head of the list of fields for that base class. This allows
- us to reduce search time in places like `build_method_call' to
- consider only reasonably likely functions. */
-
-static tree
-finish_struct_methods (t, fn_fields, nonprivate_method)
- tree t;
- tree fn_fields;
- int nonprivate_method;
-{
- tree method_vec;
- tree name = constructor_name (t);
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
-
- /* Now prepare to gather fn_fields into vector. */
- struct obstack *ambient_obstack = current_obstack;
- current_obstack = &class_obstack;
- method_vec = make_node (TREE_VEC);
- /* Room has been saved for constructors and destructors. */
- current_obstack = ambient_obstack;
- /* Now make this a live vector. */
- obstack_free (&class_obstack, method_vec);
- obstack_blank (&class_obstack, sizeof (struct tree_vec));
-
- while (fn_fields)
- {
- /* NEXT Pointer, TEST Pointer, and BASE Pointer. */
- tree nextp, *testp;
- tree fn_name = DECL_NAME (fn_fields);
- if (fn_name == NULL_TREE)
- fn_name = name;
-
- nextp = TREE_CHAIN (fn_fields);
- TREE_CHAIN (fn_fields) = NULL_TREE;
- /* Constructors are handled easily in search routines.
- Besides, we know we won't find any, so do not bother looking. */
- if (fn_name == name && TREE_VEC_ELT (method_vec, 0) == 0)
- TREE_VEC_ELT (method_vec, 0) = fn_fields;
- else
- {
- testp = &TREE_VEC_ELT (method_vec, 0);
- if (*testp == NULL_TREE)
- testp++;
- while (((HOST_WIDE_INT) testp
- < (HOST_WIDE_INT) obstack_next_free (&class_obstack))
- && DECL_NAME (*testp) != fn_name)
- testp++;
- if ((HOST_WIDE_INT) testp
- < (HOST_WIDE_INT) obstack_next_free (&class_obstack))
- {
- tree x, prev_x;
-
- for (x = *testp; x; x = DECL_CHAIN (x))
- {
- if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR])
- {
- /* ANSI C++ June 5 1992 WP 12.5.5.1 */
- error_with_decl (fn_fields, "operator delete cannot be overloaded");
- error_with_decl (x, "previous declaration here");
- }
- if (DECL_ASSEMBLER_NAME (fn_fields) == DECL_ASSEMBLER_NAME (x))
- {
- /* We complain about multiple destructors on sight,
- so we do not repeat the warning here. Friend-friend
- ambiguities are warned about outside this loop. */
- if (! DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields)))
- error_with_file_and_line (DECL_SOURCE_FILE (fn_fields),
- DECL_SOURCE_LINE (fn_fields),
- "ambiguous method `%s' in structure",
- lang_printable_name (fn_fields));
- break;
- }
- prev_x = x;
- }
- if (x == 0)
- if (*testp)
- DECL_CHAIN (prev_x) = fn_fields;
- else
- *testp = fn_fields;
- }
- else
- {
- obstack_ptr_grow (&class_obstack, fn_fields);
- method_vec = (tree)obstack_base (&class_obstack);
- }
- }
- fn_fields = nextp;
- }
-
- TREE_VEC_LENGTH (method_vec)
- = (tree *)obstack_next_free (&class_obstack) - (&TREE_VEC_ELT (method_vec, 0));
- obstack_finish (&class_obstack);
- CLASSTYPE_METHOD_VEC (t) = method_vec;
-
- if (nonprivate_method == 0
- && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE)
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
- for (i = 0; i < n_baseclasses; i++)
- if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i))
- || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i)))
- {
- nonprivate_method = 1;
- break;
- }
- if (nonprivate_method == 0)
- warning ("all member functions in class `%s' are private",
- TYPE_NAME_STRING (t));
- }
-
- /* If there are constructors (and destructors), they are at the
- front. Place destructors at very front. Also warn if all
- constructors and/or destructors are private (in which case this
- class is effectively unusable. */
- if (TYPE_HAS_DESTRUCTOR (t))
- {
- tree dtor, prev;
-
- for (dtor = TREE_VEC_ELT (method_vec, 0); dtor; prev = dtor, dtor = DECL_CHAIN (dtor))
- {
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (dtor)))
- {
- if (TREE_PRIVATE (dtor)
- && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE)
- warning_with_decl (TYPE_NAME (t), "class `%s' only defines a private destructor and has no friends");
- break;
- }
- }
- /* Wild parse errors can cause this to happen. */
- if (dtor == NULL_TREE)
- TYPE_HAS_DESTRUCTOR (t) = 0;
- else if (dtor != TREE_VEC_ELT (method_vec, 0))
- {
- DECL_CHAIN (prev) = DECL_CHAIN (dtor);
- DECL_CHAIN (dtor) = TREE_VEC_ELT (method_vec, 0);
- TREE_VEC_ELT (method_vec, 0) = dtor;
- }
- }
-
- /* Now for each member function (except for constructors and
- destructors), compute where member functions of the same
- name reside in base classes. */
- if (n_baseclasses != 0
- && TREE_VEC_LENGTH (method_vec) > 1)
- {
- int len = TREE_VEC_LENGTH (method_vec);
- tree baselink_vec = make_tree_vec (len);
- int any_links = 0;
- tree baselink_binfo = build_tree_list (NULL_TREE, TYPE_BINFO (t));
-
- for (i = 1; i < len; i++)
- {
- TREE_VEC_ELT (baselink_vec, i)
- = get_baselinks (baselink_binfo, t, DECL_NAME (TREE_VEC_ELT (method_vec, i)));
- if (TREE_VEC_ELT (baselink_vec, i) != 0)
- any_links = 1;
- }
- if (any_links != 0)
- CLASSTYPE_BASELINK_VEC (t) = baselink_vec;
- else
- obstack_free (current_obstack, baselink_vec);
- }
-
- /* Now add the methods to the TYPE_METHODS of T, arranged in a chain. */
- {
- tree x, last_x = NULL_TREE;
- int limit = TREE_VEC_LENGTH (method_vec);
-
- for (i = 1; i < limit; i++)
- {
- for (x = TREE_VEC_ELT (method_vec, i); x; x = DECL_CHAIN (x))
- {
- if (last_x != NULL_TREE)
- TREE_CHAIN (last_x) = x;
- last_x = x;
- }
- }
-
- /* Put ctors and dtors at the front of the list. */
- x = TREE_VEC_ELT (method_vec, 0);
- if (x)
- {
- while (DECL_CHAIN (x))
- {
- /* Let's avoid being circular about this. */
- if (x == DECL_CHAIN (x))
- break;
- TREE_CHAIN (x) = DECL_CHAIN (x);
- x = DECL_CHAIN (x);
- }
- if (TREE_VEC_LENGTH (method_vec) > 1)
- TREE_CHAIN (x) = TREE_VEC_ELT (method_vec, 1);
- else
- TREE_CHAIN (x) = NULL_TREE;
- }
- }
-
-#if 0
- TYPE_METHODS (t) = TREE_VEC_ELT (method_vec, 0)
- ? TREE_VEC_ELT (method_vec, 0) : TREE_VEC_ELT (method_vec, 1);
-#else
- TYPE_METHODS (t) = method_vec;
-#endif
-
- return method_vec;
-}
-
-/* Emit error when a duplicate definition of a type is seen. Patch up. */
-
-void
-duplicate_tag_error (t)
- tree t;
-{
- char *err_name;
- tree name = TYPE_NAME (t);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- err_name = IDENTIFIER_POINTER (name);
- if (TREE_CODE (t) == UNION_TYPE)
- error ("redefinition of `union %s'", err_name);
- else if (TREE_CODE (t) == RECORD_TYPE)
- error ("redefinition of `struct %s'", err_name);
- else
- error ("redefinition of tag %s", err_name);
-
- /* Pretend we haven't defined this type. */
-
- /* All of the component_decl's were TREE_CHAINed together in the parser.
- finish_struct_methods walks these chains and assembles all methods with
- the same base name into DECL_CHAINs. Now we don't need the parser chains
- anymore, so we unravel them.
- */
- /*
- * This used to be in finish_struct, but it turns out that the
- * TREE_CHAIN is used by dbxout_type_methods and perhaps some other things...
- */
- if (CLASSTYPE_METHOD_VEC(t))
- {
- tree tv = CLASSTYPE_METHOD_VEC(t);
- int i, len = TREE_VEC_LENGTH (tv);
- for (i = 0; i < len; i++)
- {
- tree unchain = TREE_VEC_ELT (tv, i);
- while(unchain != NULL_TREE)
- {
- TREE_CHAIN (unchain) = NULL_TREE;
- unchain = DECL_CHAIN(unchain);
- }
- }
- }
-
- if (TYPE_LANG_SPECIFIC (t))
- {
- tree as_list = CLASSTYPE_AS_LIST (t);
- tree binfo = TYPE_BINFO (t);
- tree binfo_as_list = CLASSTYPE_BINFO_AS_LIST (t);
- int interface_only = CLASSTYPE_INTERFACE_ONLY (t);
- int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t);
-
- bzero (TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type));
- BINFO_BASETYPES(binfo) = NULL_TREE;
-
- CLASSTYPE_AS_LIST (t) = as_list;
- TYPE_BINFO (t) = binfo;
- CLASSTYPE_BINFO_AS_LIST (t) = binfo_as_list;
- CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- CLASSTYPE_INTERFACE_UNKNOWN (t) = interface_unknown;
- CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
- TYPE_REDEFINED (t) = 1;
- }
- TYPE_SIZE (t) = NULL_TREE;
- TYPE_MODE (t) = VOIDmode;
- TYPE_FIELDS (t) = NULL_TREE;
- TYPE_METHODS (t) = NULL_TREE;
- TYPE_VFIELD (t) = NULL_TREE;
- TYPE_CONTEXT (t) = NULL_TREE;
-}
-
-/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
- (or C++ class declaration).
-
- For C++, we must handle the building of derived classes.
- Also, C++ allows static class members. The way that this is
- handled is to keep the field name where it is (as the DECL_NAME
- of the field), and place the overloaded decl in the DECL_FIELD_BITPOS
- of the field. layout_record and layout_union will know about this.
-
- More C++ hair: inline functions have text in their
- DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
- meaningful tree structure. After the struct has been laid out, set
- things up so that this can happen.
-
- And still more: virtual functions. In the case of single inheritance,
- when a new virtual function is seen which redefines a virtual function
- from the base class, the new virtual function is placed into
- the virtual function table at exactly the same address that
- it had in the base class. When this is extended to multiple
- inheritance, the same thing happens, except that multiple virtual
- function tables must be maintained. The first virtual function
- table is treated in exactly the same way as in the case of single
- inheritance. Additional virtual function tables have different
- DELTAs, which tell how to adjust `this' to point to the right thing.
-
- LIST_OF_FIELDLISTS is just that. The elements of the list are
- TREE_LIST elements, whose TREE_PURPOSE field tells what visibility
- the list has, and the TREE_VALUE slot gives the actual fields.
-
- If flag_all_virtual == 1, then we lay all functions into
- the virtual function table, as though they were declared
- virtual. Constructors do not lay down in the virtual function table.
-
- If flag_all_virtual == 2, then we lay all functions into
- the virtual function table, such that virtual functions
- occupy a space by themselves, and then all functions
- of the class occupy a space by themselves. This is illustrated
- in the following diagram:
-
- class A; class B : A;
-
- Class A's vtbl: Class B's vtbl:
- --------------------------------------------------------------------
- | A's virtual functions| | B's virtual functions |
- | | | (may inherit some from A). |
- --------------------------------------------------------------------
- | All of A's functions | | All of A's functions |
- | (such as a->A::f). | | (such as b->A::f) |
- --------------------------------------------------------------------
- | B's new virtual functions |
- | (not defined in A.) |
- -------------------------------
- | All of B's functions |
- | (such as b->B::f) |
- -------------------------------
-
- this allows the program to make references to any function, virtual
- or otherwise in a type-consistent manner. */
-
-tree
-finish_struct (t, list_of_fieldlists, warn_anon)
- tree t;
- tree list_of_fieldlists;
- int warn_anon;
-{
- extern int interface_only, interface_unknown;
- int old;
- int round_up_size = 1;
- /* Set non-zero to debug using default functions.
- Not set by program. */
- static int debug_default_functions = 0;
-
- enum tree_code code = TREE_CODE (t);
- register tree x, last_x, method_vec;
- int needs_ctor = 0, needs_dtor = 0;
- int members_need_dtors, needs_virtual_dtor;
- tree name = TYPE_NAME (t), fields, fn_fields, tail;
- enum visibility_type visibility;
- int all_virtual;
- int has_virtual;
- int max_has_virtual;
- tree pending_virtuals = NULL_TREE;
- tree abstract_virtuals = NULL_TREE;
- tree vfield;
- tree vfields;
- int needs_default_ctor;
- int cant_have_default_ctor;
- int needs_const_ctor;
- int cant_have_const_ctor;
-
- /* The index of the first base class which has virtual
- functions. Only applied to non-virtual baseclasses. */
- int first_vfn_base_index;
-
- int n_baseclasses;
- int any_default_members = 0;
- char *err_name;
- int const_sans_init = 0;
- int ref_sans_init = 0;
- int nonprivate_method = 0;
- tree t_binfo = TYPE_BINFO (t);
-
- if (TREE_CODE (name) == TYPE_DECL)
- {
- extern int lineno;
-
- DECL_SOURCE_FILE (name) = input_filename;
- /* For TYPE_DECL that are not typedefs (those marked with a line number
- of zero, we don't want to mark them as real typedefs. If this fails
- one needs to make sure real typedefs have a previous line number,
- even if it is wrong, that way the below will fill in the right line
- number. (mrs) */
- if (DECL_SOURCE_LINE (name))
- DECL_SOURCE_LINE (name) = lineno;
- name = DECL_NAME (name);
- }
- err_name = IDENTIFIER_POINTER (name);
-
- if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name))
- {
- warning ("un-usable class ignored (anonymous classes and unions are useless)");
- err_name = "(anon)";
- }
-
-#if 0
- /* This is set here, but it's never actually used anywhere. (bpk) */
- leftmost_baseclasses = NULL_TREE;
-#endif
- if (TYPE_SIZE (t))
- {
- if (TREE_CODE (t) == UNION_TYPE)
- error ("redefinition of `union %s'", err_name);
- else if (TREE_CODE (t) == RECORD_TYPE)
- error ("redefinition of `struct %s'", err_name);
- else
- my_friendly_abort (172);
- popclass (0);
- return t;
- }
-
- GNU_xref_decl (current_function_decl, t);
-
- /* If this type was previously laid out as a forward reference,
- make sure we lay it out again. */
-
- TYPE_SIZE (t) = 0;
- CLASSTYPE_GOT_SEMICOLON (t) = 0;
- CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- CLASSTYPE_INTERFACE_UNKNOWN (t) = interface_unknown;
-
- if (flag_dossier)
- build_t_desc (t, 0);
-
- TYPE_BINFO (t) = NULL_TREE;
-
- old = suspend_momentary ();
-
- /* Install struct as DECL_FIELD_CONTEXT of each field decl.
- Also process specified field sizes.
- Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
- The specified size is found in the DECL_INITIAL.
- Store 0 there, except for ": 0" fields (so we can find them
- and delete them, below). */
-
- if (t_binfo && BINFO_BASETYPES (t_binfo))
- n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo));
- else
- n_baseclasses = 0;
-
- if (n_baseclasses > 0)
- {
- struct base_info base_info;
-
- /* If using multiple inheritance, this may cause variants of our
- basetypes to be used (instead of their canonical forms). */
- fields = layout_basetypes (t, BINFO_BASETYPES (t_binfo));
- last_x = tree_last (fields);
-
- first_vfn_base_index = finish_base_struct (t, &base_info,
- BINFO_BASETYPES (t_binfo));
- has_virtual = base_info.has_virtual;
- max_has_virtual = base_info.max_has_virtual;
- CLASSTYPE_N_SUPERCLASSES (t) += base_info.n_ancestors;
- vfield = base_info.vfield;
- vfields = base_info.vfields;
- needs_default_ctor = base_info.needs_default_ctor;
- cant_have_default_ctor = base_info.cant_have_default_ctor;
- needs_const_ctor = base_info.needs_const_ctor;
- cant_have_const_ctor = base_info.cant_have_const_ctor;
- members_need_dtors = base_info.members_need_dtors;
- needs_virtual_dtor = base_info.needs_virtual_dtor;
- n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo));
- }
- else
- {
- first_vfn_base_index = -1;
- has_virtual = 0;
- max_has_virtual = has_virtual;
- vfield = NULL_TREE;
- vfields = NULL_TREE;
- fields = NULL_TREE;
- last_x = NULL_TREE;
- needs_default_ctor = 0;
- cant_have_default_ctor = 0;
- needs_const_ctor = 0;
- cant_have_const_ctor = 0;
- members_need_dtors = 0;
- needs_virtual_dtor = 0;
- }
-
- if (write_virtuals == 3 && ! CLASSTYPE_INTERFACE_UNKNOWN (t)
- && current_lang_name == lang_name_cplusplus)
- {
- CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! interface_only;
- }
-
- /* The three of these are approximations which may later be
- modified. Needed at this point to make add_virtual_function
- and modify_vtable_entries work. */
- TREE_CHAIN (t_binfo) = TYPE_BINFO (t);
- TYPE_BINFO (t) = t_binfo;
- CLASSTYPE_VFIELDS (t) = vfields;
- CLASSTYPE_VFIELD (t) = vfield;
-
- fn_fields = NULL_TREE;
- tail = NULL_TREE;
- if (last_x && list_of_fieldlists)
- TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
-
- if (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (t))
- all_virtual = 1;
- else
- all_virtual = 0;
-
- if (CLASSTYPE_DECLARED_CLASS (t) == 0)
- {
- nonprivate_method = 1;
- if (list_of_fieldlists
- && TREE_PURPOSE (list_of_fieldlists) == (tree)visibility_default)
- TREE_PURPOSE (list_of_fieldlists) = (tree)visibility_public;
- }
- else if (list_of_fieldlists
- && TREE_PURPOSE (list_of_fieldlists) == (tree)visibility_default)
- TREE_PURPOSE (list_of_fieldlists) = (tree)visibility_private;
-
- while (list_of_fieldlists)
- {
- visibility = (enum visibility_type)TREE_PURPOSE (list_of_fieldlists);
-
- for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x))
- {
- TREE_PRIVATE (x) = visibility == visibility_private;
- TREE_PROTECTED (x) = visibility == visibility_protected;
- GNU_xref_member (current_class_name, x);
-
- if (TREE_CODE (x) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE)
- {
-#if 0
- /* @@ Um. This doesn't seem to be handled properly, at
- least in my PT test cases. Not sure if it's really
- supposed to work for non-PT cases. Let's find out. */
- static tree t, d;
- d = DECL_NAME (x);
- t = TYPE_IDENTIFIER (TREE_TYPE (x));
- if (d == t) continue;
- if (IDENTIFIER_TEMPLATE (t))
- {
- t = DECL_NAME (TREE_PURPOSE (IDENTIFIER_TEMPLATE (t)));
- my_friendly_assert (t == d, 173);
- continue;
- }
- else if (IDENTIFIER_CLASS_VALUE (t))
- my_friendly_assert (TREE_TYPE (DECL_NAME (d))
- == TREE_TYPE (DECL_NAME (TREE_TYPE (t))),
- 174);
- else
- abort ();
-#endif
- continue;
- }
-
-
- if (TREE_CODE (x) == FUNCTION_DECL)
- {
- /* Clear out this flag.
-
- @@ Doug may figure out how to break
- @@ this with nested classes and friends. */
- DECL_IN_AGGR_P (x) = 0;
-
- nonprivate_method |= ! TREE_PRIVATE (x);
-
- /* If this was an evil function, don't keep it in class. */
- if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
- continue;
-
- if (last_x) TREE_CHAIN (last_x) = TREE_CHAIN (x);
- if (! fn_fields) fn_fields = x;
- else TREE_CHAIN (tail) = x;
- tail = x;
-
-#if 0
- /* ??? What if we have duplicate declarations
- in T's definition? */
- if (DECL_CLASS_CONTEXT (x))
- continue;
-#endif
- DECL_CLASS_CONTEXT (x) = t;
-
- DECL_FIELD_SIZE (x) = 0;
-
- /* The name of the field is the original field name
- Save this in auxiliary field for later overloading. */
- if (DECL_VINDEX (x)
- || (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x)))
- {
- pending_virtuals = add_virtual_function (pending_virtuals,
- &has_virtual, x, t);
- if (DECL_ABSTRACT_VIRTUAL_P (x))
- abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
- }
- continue;
- }
-
- /* Handle visibility declarations. */
- if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF)
- {
- tree fdecl = TREE_OPERAND (DECL_NAME (x), 1);
-
- if (last_x) TREE_CHAIN (last_x) = TREE_CHAIN (x);
- /* Make type T see field decl FDECL with
- the visibility VISIBILITY. */
- if (TREE_CODE (fdecl) == TREE_LIST)
- {
- fdecl = TREE_VALUE (fdecl);
- while (fdecl)
- {
- if (alter_visibility (t, fdecl, visibility) == 0)
- break;
- fdecl = DECL_CHAIN (fdecl);
- }
- }
- else alter_visibility (t, fdecl, visibility);
- CLASSTYPE_ALTERS_VISIBILITIES_P (t) = 1;
- continue;
- }
-
- /* If this is of reference type, check if it needs an init. */
- if (TREE_CODE (x) != TYPE_DECL
- && TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE
- && DECL_INITIAL (x) == 0)
- ref_sans_init = 1;
-
- /* ``A local class cannot have static data members.'' ARM 9.4 */
- if (current_function_decl && TREE_STATIC (x))
- error_with_decl (x, "field `%s' in local class cannot be static");
-
- /* When this goes into scope, it will be a non-local reference. */
- DECL_NONLOCAL (x) = 1;
-
- /* Perform error checking that did not get done in grokdeclarator. */
- if (TREE_CODE (x) == FIELD_DECL || TREE_CODE (x) == VAR_DECL)
- {
- if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE)
- {
- error_with_decl (x, "field `%s' invalidly declared function type");
- TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
- }
- else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE)
- {
- error_with_decl (x, "field `%s' invalidly declared method type");
- TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
- }
- else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE)
- {
- error_with_decl (x, "field `%s' invalidly declared offset type");
- TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
- }
- }
-
- if (TREE_CODE (x) == FIELD_DECL)
- {
- /* If the field has a bogus type, don't bother with it. */
- if (TREE_TYPE (x) != error_mark_node)
- {
- /* Never let anything with uninheritable virtuals
- make it through without complaint. */
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
- && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (x)))
- abstract_virtuals_error (x, TREE_TYPE (x));
-
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (x)))
- {
- if (TYPE_HAS_DEFAULT_CONSTRUCTOR (TREE_TYPE (x)))
- needs_default_ctor = 1;
- if (TYPE_GETS_CONST_INIT_REF (TREE_TYPE (x)))
- needs_const_ctor = 1;
- else if (TYPE_GETS_INIT_REF (TREE_TYPE (x)))
- cant_have_const_ctor = 1;
- }
- else if (DECL_INITIAL (x) == NULL_TREE
- && (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (x))
- || TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE))
- cant_have_default_ctor = 1;
- }
-
- /* If any field is const, the structure type is pseudo-const. */
- if (TREE_READONLY (x))
- {
- C_TYPE_FIELDS_READONLY (t) = 1;
- if (DECL_INITIAL (x) == 0)
- const_sans_init = 1;
- }
- else
- {
- /* A field that is pseudo-const makes the structure likewise. */
- tree t1 = TREE_TYPE (x);
- while (TREE_CODE (t1) == ARRAY_TYPE)
- t1 = TREE_TYPE (t1);
- if (IS_AGGR_TYPE (t1))
- {
- if (C_TYPE_FIELDS_READONLY (t1))
- C_TYPE_FIELDS_READONLY (t) = 1;
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (t1))
- const_sans_init = 1;
- }
- }
- }
- else if (TREE_CODE (x) == VAR_DECL && TREE_CODE (t) == UNION_TYPE)
- /* Unions cannot have static members. */
- error_with_decl (x, "field `%s' declared static in union");
-
- if (! fields) fields = x;
- DECL_FIELD_CONTEXT (x) = t;
- /* We could be making an extern "C" function a friend. */
- if (DECL_LANG_SPECIFIC (x))
- DECL_CLASS_CONTEXT (x) = t;
- DECL_FIELD_SIZE (x) = 0;
-
- /* We set DECL_BIT_FIELD tentatively in grokbitfield.
- If the type and width are valid, we'll keep it set.
- Otherwise, the flag is cleared. */
- if (DECL_BIT_FIELD (x))
- {
- DECL_BIT_FIELD (x) = 0;
- /* Invalid bit-field size done by grokfield. */
- /* Detect invalid bit-field type. */
- if (DECL_INITIAL (x)
- && TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
- {
- error_with_decl (x, "bit-field `%s' has invalid type");
- DECL_INITIAL (x) = NULL;
- }
- if (DECL_INITIAL (x) && pedantic
- && TREE_TYPE (x) != integer_type_node
- && TREE_TYPE (x) != unsigned_type_node
- && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
- warning_with_decl (x, "bit-field `%s' type invalid in ANSI C++");
-
- /* Detect and ignore out of range field width. */
- if (DECL_INITIAL (x))
- {
- register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
- if (width < 0)
- {
- DECL_INITIAL (x) = NULL;
- warning_with_decl (x, "negative width in bit-field `%s'");
- }
- else if (width == 0 && DECL_NAME (x) != 0)
- {
- error_with_decl (x, "zero width for bit-field `%s'");
- DECL_INITIAL (x) = NULL;
- }
- else if ((unsigned)width > TYPE_PRECISION (TREE_TYPE (x)))
- {
- DECL_INITIAL (x) = NULL;
- warning_with_decl (x, "width of `%s' exceeds its type");
- }
- }
-
- /* Process valid field width. */
- if (DECL_INITIAL (x))
- {
- register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
- if (width == 0)
- {
-#ifdef EMPTY_FIELD_BOUNDARY
- /* field size 0 => mark following field as "aligned" */
- if (TREE_CHAIN (x))
- DECL_ALIGN (TREE_CHAIN (x))
- = MAX (DECL_ALIGN (TREE_CHAIN (x)), EMPTY_FIELD_BOUNDARY);
- /* field of size 0 at the end => round up the size. */
- else
- round_up_size = EMPTY_FIELD_BOUNDARY;
-#endif
-#ifdef PCC_BITFIELD_TYPE_MATTERS
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
- TYPE_ALIGN (TREE_TYPE (x)));
-#endif
- }
- else
- {
- DECL_INITIAL (x) = NULL_TREE;
- DECL_FIELD_SIZE (x) = width;
- DECL_BIT_FIELD (x) = 1;
- /* Traditionally a bit field is unsigned
- even if declared signed. */
- if (flag_traditional
- && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE)
- TREE_TYPE (x) = unsigned_type_node;
- }
- }
- else
- /* Non-bit-fields are aligned for their type. */
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (TREE_TYPE (x)));
- }
- else if (TREE_CODE (x) == FIELD_DECL)
- {
- tree type = TREE_TYPE (x);
- if (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
- if (code == UNION_TYPE && IS_AGGR_TYPE (type))
- {
- if (TYPE_NEEDS_CONSTRUCTING (type)
- || TYPE_NEEDS_DESTRUCTOR (type))
- error_with_decl (x, "member `%s' with constructor or destructor not allowed in union");
- TYPE_GETS_ASSIGNMENT (t) |= TYPE_GETS_ASSIGNMENT (type);
- TYPE_GETS_INIT_REF (t) |= TYPE_GETS_INIT_REF (type);
- }
- else if (code == RECORD_TYPE)
- {
- /* Array of record type doesn't matter for this bit. */
- TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
- if (IS_AGGR_TYPE (type))
- {
- needs_ctor |= TYPE_NEEDS_CONSTRUCTOR (type);
- needs_dtor |= TYPE_NEEDS_DESTRUCTOR (type);
- members_need_dtors |= TYPE_NEEDS_DESTRUCTOR (type);
- TYPE_GETS_CONST_INIT_REF (t) |= TYPE_GETS_CONST_INIT_REF (type);
- TYPE_GETS_ASSIGNMENT (t) |= TYPE_GETS_ASSIGNMENT (type);
- TYPE_GETS_INIT_REF (t) |= TYPE_GETS_INIT_REF (type);
- }
- }
- if (DECL_INITIAL (x) != NULL_TREE)
- {
- /* `build_class_init_list' does not recognize non-FIELD_DECLs. */
- if (code == UNION_TYPE && any_default_members != 0)
- error ("multiple fields in union initialized");
- any_default_members = 1;
- }
- }
- last_x = x;
- }
- list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
- /* link the tail while we have it! */
- if (last_x)
- {
- TREE_CHAIN (last_x) = NULL_TREE;
-
- if (list_of_fieldlists
- && TREE_VALUE (list_of_fieldlists)
- && TREE_CODE (TREE_VALUE (list_of_fieldlists)) != FUNCTION_DECL)
- TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
- }
- }
-
- if (tail) TREE_CHAIN (tail) = NULL_TREE;
-
- /* If this type has any constant members which did not come
- with their own initialization, mark that fact here. It is
- not an error here, since such types can be saved either by their
- constructors, or by fortuitous initialization. */
- CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
- CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init;
- CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
-
- if (members_need_dtors && !TYPE_HAS_DESTRUCTOR (t))
- {
- /* Here we must cons up a destructor on the fly. */
- tree dtor = cons_up_default_function (t, name,
- needs_virtual_dtor != 0);
-
- /* If we couldn't make it work, then pretend we didn't need it. */
- if (dtor == void_type_node)
- TYPE_NEEDS_DESTRUCTOR (t) = 0;
- else
- {
- if (! fn_fields) fn_fields = dtor;
- else TREE_CHAIN (tail) = dtor;
- tail = dtor;
-
- if (DECL_VINDEX (dtor) == NULL_TREE
- && ! CLASSTYPE_DECLARED_EXCEPTION (t)
- && (needs_virtual_dtor
- || pending_virtuals != NULL_TREE
- || pending_hard_virtuals != NULL_TREE))
- DECL_VINDEX (dtor) = error_mark_node;
- if (DECL_VINDEX (dtor))
- pending_virtuals = add_virtual_function (pending_virtuals,
- &has_virtual, dtor, NULL_TREE);
- nonprivate_method = 1;
- TYPE_HAS_DESTRUCTOR (t) = 1;
- }
- }
-
- if (debug_default_functions)
- {
- if ((TYPE_NEEDS_CONSTRUCTOR (t) || TYPE_HAS_CONSTRUCTOR (t) || needs_ctor)
- && ! TYPE_HAS_INIT_REF (t))
- {
- tree default_fn = cons_up_default_function (t, name, 4);
- TREE_CHAIN (default_fn) = fn_fields;
- fn_fields = default_fn;
- TYPE_HAS_INIT_REF (t) = 1;
- default_fn = cons_up_default_function (t, name, 3);
- TREE_CHAIN (default_fn) = fn_fields;
- fn_fields = default_fn;
- nonprivate_method = 1;
- }
-
- if (! TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
- && needs_default_ctor && ! cant_have_default_ctor)
- {
- tree default_fn = cons_up_default_function (t, name, 2);
- TREE_CHAIN (default_fn) = fn_fields;
- fn_fields = default_fn;
- TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
- nonprivate_method = 1;
- }
- }
-
- if (fn_fields)
- {
- method_vec = finish_struct_methods (t, fn_fields, nonprivate_method);
-
- if (TYPE_HAS_CONSTRUCTOR (t)
- && ! CLASSTYPE_DECLARED_EXCEPTION (t)
- && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE)
- {
- int nonprivate_ctor = 0;
- tree ctor;
-
- for (ctor = TREE_VEC_ELT (method_vec, 0);
- ctor;
- ctor = DECL_CHAIN (ctor))
- if (! TREE_PRIVATE (ctor))
- {
- nonprivate_ctor = 1;
- break;
- }
- if (nonprivate_ctor == 0)
- warning ("class `%s' only defines private constructors and has no friends",
- err_name);
- }
- }
- else
- {
- method_vec = 0;
-
- /* Just in case these got accidentally
- filled in by syntax errors. */
- TYPE_HAS_CONSTRUCTOR (t) = 0;
- TYPE_HAS_DESTRUCTOR (t) = 0;
- }
-
- if (vfield == NULL_TREE && has_virtual)
- {
- /* We build this decl with ptr_type_node, and
- change the type when we know what it should be. */
- vfield = build_lang_field_decl (FIELD_DECL, get_vfield_name (t), ptr_type_node);
- /* If you change any of the below, take a look at all the
- other VFIELD_BASEs and VTABLE_BASEs in the code, and change
- them too. */
- DECL_ASSEMBLER_NAME (vfield) = get_identifier (VFIELD_BASE);
- CLASSTYPE_VFIELD (t) = vfield;
- DECL_VIRTUAL_P (vfield) = 1;
- DECL_FIELD_CONTEXT (vfield) = t;
- DECL_CLASS_CONTEXT (vfield) = t;
- DECL_FCONTEXT (vfield) = t;
- DECL_FIELD_SIZE (vfield) = 0;
- DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node);
- if (CLASSTYPE_DOSSIER (t))
- {
- /* vfield is always first entry in structure. */
- TREE_CHAIN (vfield) = fields;
- fields = vfield;
- }
- else if (last_x)
- {
- my_friendly_assert (TREE_CHAIN (last_x) == 0, 175);
- TREE_CHAIN (last_x) = vfield;
- last_x = vfield;
- }
- else fields = vfield;
- vfields = chainon (vfields, CLASSTYPE_AS_LIST (t));
- }
-
- /* Now DECL_INITIAL is null on all members except for zero-width bit-fields.
- And they have already done their work.
-
- C++: maybe we will support default field initialization some day... */
-
- /* Delete all zero-width bit-fields from the front of the fieldlist */
- while (fields && DECL_BIT_FIELD (fields)
- && DECL_INITIAL (fields))
- fields = TREE_CHAIN (fields);
- /* Delete all such fields from the rest of the fields. */
- for (x = fields; x;)
- {
- if (TREE_CHAIN (x) && DECL_BIT_FIELD (TREE_CHAIN (x))
- && DECL_INITIAL (TREE_CHAIN (x)))
- TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
- else x = TREE_CHAIN (x);
- }
- /* Delete all duplicate fields from the fields */
- delete_duplicate_fields (fields);
-
- /* Now we have the final fieldlist for the data fields. Record it,
- then lay out the structure or union (including the fields). */
-
- TYPE_FIELDS (t) = fields;
-
- /* If there's a :0 field at the end, round the size to the
- EMPTY_FIELD_BOUNDARY. */
- TYPE_ALIGN (t) = round_up_size;
-
- /* Pass layout information about base classes to layout_type, if any. */
-
- if (n_baseclasses)
- {
- tree pseudo_basetype = TREE_TYPE (base_layout_decl);
-
- TREE_CHAIN (base_layout_decl) = TYPE_FIELDS (t);
- TYPE_FIELDS (t) = base_layout_decl;
-
- TYPE_SIZE (pseudo_basetype) = CLASSTYPE_SIZE (t);
- TYPE_MODE (pseudo_basetype) = TYPE_MODE (t);
- TYPE_ALIGN (pseudo_basetype) = CLASSTYPE_ALIGN (t);
- DECL_ALIGN (base_layout_decl) = TYPE_ALIGN (pseudo_basetype);
- }
-
- layout_type (t);
-
- if (n_baseclasses)
- TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t));
-
- /* C++: do not let empty structures exist. */
- if (integer_zerop (TYPE_SIZE (t)))
- TYPE_SIZE (t) = TYPE_SIZE (char_type_node);
-
- /* Set the TYPE_DECL for this type to contain the right
- value for DECL_OFFSET, so that we can use it as part
- of a COMPONENT_REF for multiple inheritance. */
-
- if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
- layout_decl (TYPE_NAME (t), 0);
-
- /* Now fix up any virtual base class types that we
- left lying around. We must get these done
- before we try to lay out the virtual function table. */
- doing_hard_virtuals = 1;
- pending_hard_virtuals = nreverse (pending_hard_virtuals);
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (t))
- {
- tree vbases;
-
- max_has_virtual = layout_vbasetypes (t, max_has_virtual);
- vbases = CLASSTYPE_VBASECLASSES (t);
- CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases);
-
- /* This loop makes all the entries in the virtual function tables
- of interest contain the "latest" version of the functions
- we have defined. */
-
- while (vbases)
- {
- tree virtuals = BINFO_VIRTUALS (vbases);
-
- if (virtuals)
- {
- /* Get past the `null' vtable entry... */
- virtuals = TREE_CHAIN (virtuals);
- /* and the `dossier' vtable entry if we're doing dossiers. */
- if (flag_dossier)
- virtuals = TREE_CHAIN (virtuals);
- }
-
- while (virtuals != NULL_TREE)
- {
- tree pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
- tree base_fndecl = TREE_OPERAND (pfn, 0);
- tree decl = get_first_matching_virtual (TYPE_BINFO (t), base_fndecl,
- DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)));
- tree context = DECL_CLASS_CONTEXT (decl);
- if (decl != base_fndecl && context != t)
- {
- tree base_context = DECL_CLASS_CONTEXT (base_fndecl);
- tree binfo = NULL_TREE, these_virtuals;
-#if 0
- unsigned HOST_WIDE_INT i
- = (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
- & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1));
-#endif
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (context))
- binfo = virtual_member (base_context,
- CLASSTYPE_VBASECLASSES (context));
- if (binfo == NULL_TREE)
- binfo = binfo_value (base_context, context);
- if (binfo != NULL_TREE)
- {
-#if 1
- pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl)));
-#else
- these_virtuals = BINFO_VIRTUALS (binfo);
-
- while (i-- > 0)
- these_virtuals = TREE_CHAIN (these_virtuals);
- pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (these_virtuals));
-#endif
- modify_vtable_entries (t, decl, base_fndecl, pfn);
- }
- }
- virtuals = TREE_CHAIN (virtuals);
- }
- /* Update dossier info with offsets for virtual baseclasses. */
- if (flag_dossier && ! BINFO_NEW_VTABLE_MARKED (vbases))
- prepare_fresh_vtable (vbases, vbases, t);
-
- vbases = TREE_CHAIN (vbases);
- }
- }
-
- while (pending_hard_virtuals)
- {
- /* Need an entry in some other virtual function table. */
- if (TREE_TYPE (pending_hard_virtuals))
- {
- /* This is how we modify entries when a vfn's index changes
- between derived and base type. */
- modify_vtable_entries (t, TREE_PURPOSE (pending_hard_virtuals),
- TREE_TYPE (pending_hard_virtuals),
- TREE_VALUE (pending_hard_virtuals));
- }
- else
- {
- /* This is how we modify entries when a vfn comes from
- a virtual baseclass. */
- tree base_fndecls = DECL_VINDEX (TREE_PURPOSE (pending_hard_virtuals));
- my_friendly_assert (base_fndecls != error_mark_node, 176);
- while (base_fndecls)
- {
- modify_vtable_entries (t, TREE_PURPOSE (pending_hard_virtuals),
- TREE_VALUE (base_fndecls),
- TREE_VALUE (pending_hard_virtuals));
- base_fndecls = TREE_CHAIN (base_fndecls);
- }
- }
- pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals);
- }
- doing_hard_virtuals = 0;
-
- /* Under our model of GC, every C++ class gets its own virtual
- function table, at least virtually. */
- if (pending_virtuals || CLASSTYPE_DOSSIER (t))
- {
- pending_virtuals = nreverse (pending_virtuals);
- /* We must enter these virtuals into the table. */
- if (first_vfn_base_index < 0)
- {
- if (flag_dossier)
- pending_virtuals = tree_cons (NULL_TREE,
- build_vtable_entry (integer_zero_node,
- build_t_desc (t, 0)),
- pending_virtuals);
- pending_virtuals = tree_cons (NULL_TREE, the_null_vtable_entry,
- pending_virtuals);
- build_vtable (NULL_TREE, t);
- }
- else
- {
- /* Here we know enough to change the type of our virtual
- function table, but we will wait until later this function. */
-
- if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))
- build_vtable (binfo_value (TYPE_BINFO_BASETYPE (t, first_vfn_base_index), t), t);
-
- /* Update the dossier pointer for this class. */
- if (flag_dossier)
- TREE_VALUE (TREE_CHAIN (TYPE_BINFO_VIRTUALS (t)))
- = build_vtable_entry (integer_zero_node, build_t_desc (t, 0));
- }
-
- /* If this type has basetypes with constructors, then those
- constructors might clobber the virtual function table. But
- they don't if the derived class shares the exact vtable of the base
- class. */
-
- CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
- }
- else if (first_vfn_base_index >= 0)
- {
- tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0);
-
- /* This class contributes nothing new to the virtual function
- table. However, it may have declared functions which
- went into the virtual function table "inherited" from the
- base class. If so, we grab a copy of those updated functions,
- and pretend they are ours. */
-
- /* See if we should steal the virtual info from base class. */
- if (TYPE_BINFO_VTABLE (t) == NULL_TREE)
- TYPE_BINFO_VTABLE (t) = BINFO_VTABLE (binfo);
- if (TYPE_BINFO_VIRTUALS (t) == NULL_TREE)
- TYPE_BINFO_VIRTUALS (t) = BINFO_VIRTUALS (binfo);
- if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo))
- CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
- }
-
- if (has_virtual > max_has_virtual)
- max_has_virtual = has_virtual;
- if (max_has_virtual || first_vfn_base_index >= 0)
- {
-#ifdef VTABLE_USES_MASK
- if (max_has_virtual >= VINDEX_MAX)
- {
- error ("too many virtual functions for class `%s' (VINDEX_MAX < %d)",
- err_name, has_virtual);
- }
-#endif
- TYPE_VIRTUAL_P (t) = 1;
- CLASSTYPE_VSIZE (t) = has_virtual;
- if (first_vfn_base_index >= 0)
- {
- if (pending_virtuals)
- TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t),
- pending_virtuals);
- }
- else if (has_virtual)
- {
- TYPE_BINFO_VIRTUALS (t) = pending_virtuals;
- if (write_virtuals >= 0)
- DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)) = 1;
- }
- }
-
- /* Now lay out the virtual function table. */
- if (has_virtual)
- {
- tree atype, itype;
-
- if (TREE_TYPE (vfield) == ptr_type_node)
- {
- /* We must create a pointer to this table because
- the one inherited from base class does not exist.
- We will fill in the type when we know what it
- should really be. Use `size_int' so values are memoized
- in common cases. */
- itype = build_index_type (size_int (has_virtual));
- atype = build_array_type (vtable_entry_type, itype);
- layout_type (atype);
- TREE_TYPE (vfield) = build_pointer_type (atype);
- }
- else
- {
- atype = TREE_TYPE (TREE_TYPE (vfield));
-
- if (has_virtual != TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))))
- {
- /* We must extend (or create) the boundaries on this array,
- because we picked up virtual functions from multiple
- base classes. */
- itype = build_index_type (size_int (has_virtual));
- atype = build_array_type (vtable_entry_type, itype);
- layout_type (atype);
- vfield = copy_node (vfield);
- TREE_TYPE (vfield) = build_pointer_type (atype);
- }
- }
-
- CLASSTYPE_VFIELD (t) = vfield;
- if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype)
- {
- TREE_TYPE (TYPE_BINFO_VTABLE (t)) = atype;
- layout_decl (TYPE_BINFO_VTABLE (t), 0);
- DECL_ALIGN (TYPE_BINFO_VTABLE (t))
- = MAX (TYPE_ALIGN (double_type_node),
- DECL_ALIGN (TYPE_BINFO_VTABLE (t)));
- }
- }
- else if (first_vfn_base_index >= 0)
- CLASSTYPE_VFIELD (t) = vfield;
- CLASSTYPE_VFIELDS (t) = vfields;
-
- /* Set all appropriate CLASSTYPE_... flags for this type
- and its variants. */
- TYPE_NEEDS_CONSTRUCTOR (t) |= needs_ctor || TYPE_HAS_CONSTRUCTOR (t);
- TYPE_NEEDS_CONSTRUCTING (t)
- |= ((TYPE_NEEDS_CONSTRUCTOR (t)|TYPE_USES_VIRTUAL_BASECLASSES (t))
- || has_virtual || any_default_members
- || first_vfn_base_index >= 0);
- TYPE_NEEDS_DESTRUCTOR (t) |= needs_dtor || TYPE_HAS_DESTRUCTOR (t);
- finish_struct_bits (t, max_has_virtual);
-
- /* Promote each bit-field's type to int if it is narrower than that.
- There's more: complete the rtl for any static member objects which
- is of the same type we're working on.
- */
- for (x = fields; x; x = TREE_CHAIN (x))
- {
- if (DECL_BIT_FIELD (x)
- && C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x)))
- TREE_TYPE (x) = TREE_UNSIGNED (TREE_TYPE (x))
- ? unsigned_type_node : integer_type_node;
- if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
- && TREE_TYPE (x) == t)
- {
- DECL_MODE (x) = TYPE_MODE (t);
- make_decl_rtl (x, NULL, 0);
- }
- }
-
- /* Now add the tags, if any, to the list of TYPE_DECLs
- defined for this type. */
- if (CLASSTYPE_TAGS (t))
- {
- x = CLASSTYPE_TAGS (t);
- last_x = tree_last (TYPE_FIELDS (t));
- while (x)
- {
- tree tag = build_lang_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x));
- DECL_CONTEXT (tag) = t;
- DECL_CLASS_CONTEXT (tag) = t;
- x = TREE_CHAIN (x);
- last_x = chainon (last_x, tag);
- }
- if (TYPE_FIELDS (t) == 0)
- TYPE_FIELDS (t) = last_x;
- CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
- }
-
- if (TYPE_HAS_CONSTRUCTOR (t))
- {
- tree vfields = CLASSTYPE_VFIELDS (t);
-
- while (vfields)
- {
- /* Mark the fact that constructor for T
- could affect anybody inheriting from T
- who wants to initialize vtables for VFIELDS's type. */
- if (VF_DERIVED_VALUE (vfields))
- TREE_ADDRESSABLE (vfields) = 1;
- vfields = TREE_CHAIN (vfields);
- }
- if (any_default_members != 0)
- build_class_init_list (t);
- }
- else if (TYPE_NEEDS_CONSTRUCTING (t))
- build_class_init_list (t);
-
- if (current_lang_name == lang_name_cplusplus)
- {
- if (! CLASSTYPE_DECLARED_EXCEPTION (t))
- embrace_waiting_friends (t);
-
- /* Write out inline function definitions. */
- do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t));
- CLASSTYPE_INLINE_FRIENDS (t) = 0;
- }
-
- if (CLASSTYPE_VSIZE (t) != 0)
- {
-#if 0
- if (!TYPE_USES_COMPLEX_INHERITANCE (t))
- TYPE_NONCOPIED_PARTS (t) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield);
-#endif
-
- if ((flag_this_is_variable & 1) == 0)
- {
- tree vtbl_ptr = build_decl (VAR_DECL, get_identifier (VPTR_NAME),
- TREE_TYPE (vfield));
- DECL_REGISTER (vtbl_ptr) = 1;
- CLASSTYPE_VTBL_PTR (t) = vtbl_ptr;
- }
- if (DECL_FIELD_CONTEXT (vfield) != t)
- {
- tree binfo = binfo_value (DECL_FIELD_CONTEXT (vfield), t);
- tree offset = BINFO_OFFSET (binfo);
-
- vfield = copy_node (vfield);
- copy_lang_decl (vfield);
-
- if (! integer_zerop (offset))
- offset = size_binop (MULT_EXPR, offset, size_int (BITS_PER_UNIT));
- DECL_FIELD_CONTEXT (vfield) = t;
- DECL_CLASS_CONTEXT (vfield) = t;
- DECL_FIELD_BITPOS (vfield)
- = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield));
- CLASSTYPE_VFIELD (t) = vfield;
- }
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
- && DECL_VINDEX (TREE_VEC_ELT (method_vec, 0)) == NULL_TREE)
- warning ("class `%s' has virtual functions but non-virtual destructor",
- err_name);
- }
-
- /* Make the rtl for any new vtables we have created, and unmark
- the base types we marked. */
- unmark_finished_struct (t);
- TYPE_BEING_DEFINED (t) = 0;
-
- if (flag_dossier && CLASSTYPE_VTABLE_NEEDS_WRITING (t))
- {
- tree variants;
- tree tdecl;
-
- /* Now instantiate its type descriptors. */
- tdecl = TREE_OPERAND (build_t_desc (t, 1), 0);
- variants = TYPE_POINTER_TO (t);
- build_type_variant (variants, 1, 0);
- while (variants)
- {
- build_t_desc (variants, 1);
- variants = TYPE_NEXT_VARIANT (variants);
- }
- variants = build_reference_type (t);
- build_type_variant (variants, 1, 0);
- while (variants)
- {
- build_t_desc (variants, 1);
- variants = TYPE_NEXT_VARIANT (variants);
- }
-#if 0
- DECL_VPARENT (tdecl) = t;
-#endif
- DECL_CONTEXT (tdecl) = t;
- }
- /* Still need to instantiate this C struct's type descriptor. */
- else if (flag_dossier && ! CLASSTYPE_DOSSIER (t))
- build_t_desc (t, 1);
-
- if (TYPE_NAME (t) && TYPE_IDENTIFIER (t))
- undo_template_name_overload (TYPE_IDENTIFIER (t), 1);
- if (current_class_type)
- popclass (0);
- else
- error ("trying to finish struct, but kicked out due to previous parse errors.");
-
- hack_incomplete_structures (t);
-
- resume_momentary (old);
-
- if (flag_cadillac)
- cadillac_finish_struct (t);
-
-#if 0
- /* This has to be done after we have sorted out what to do with
- the enclosing type. */
- /* Be smarter about nested classes here. If a type is nested,
- only output it if we would output the enclosing type. */
- if (DECL_CONTEXT (TYPE_NAME (t))
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (TYPE_NAME (t)))) == 't')
- DECL_IGNORED_P (TYPE_NAME (t)) = TREE_ASM_WRITTEN (TYPE_NAME (t));
-#endif
-
- /* If the type has methods, we want to think about cutting down
- the amount of symbol table stuff we output. The value stored in
- the TYPE_DECL's DECL_IGNORED_P slot is a first approximation.
- For example, if a member function is seen and we decide to
- write out that member function, then we can change the value
- of the DECL_IGNORED_P slot, and the type will be output when
- that member function's debug info is written out. */
- if (CLASSTYPE_METHOD_VEC (t))
- {
- extern tree pending_vtables;
-
- /* Don't output full info about any type
- which does not have its implementation defined here. */
- if (TYPE_VIRTUAL_P (t) && write_virtuals == 2)
- DECL_IGNORED_P (TYPE_NAME (t))
- = (value_member (TYPE_IDENTIFIER (t), pending_vtables) == 0);
- else if (CLASSTYPE_INTERFACE_ONLY (t))
- DECL_IGNORED_P (TYPE_NAME (t)) = 1;
- else if (CLASSTYPE_INTERFACE_UNKNOWN (t))
- /* Only a first approximation! */
- DECL_IGNORED_P (TYPE_NAME (t)) = 1;
- }
- else if (CLASSTYPE_INTERFACE_ONLY (t))
- DECL_IGNORED_P (TYPE_NAME (t)) = 1;
-
- /* Finish debugging output for this type. */
- rest_of_type_compilation (t, global_bindings_p ());
-
- return t;
-}
-
-/* Return non-zero if the effective type of INSTANCE is static.
- Used to determine whether the virtual function table is needed
- or not.
-
- *NONNULL is set iff INSTANCE can be known to be nonnull, regardless
- of our knowledge of its type. */
-int
-resolves_to_fixed_type_p (instance, nonnull)
- tree instance;
- int *nonnull;
-{
- switch (TREE_CODE (instance))
- {
- case INDIRECT_REF:
- /* Check that we are not going through a cast of some sort. */
- if (TREE_TYPE (instance)
- == TREE_TYPE (TREE_TYPE (TREE_OPERAND (instance, 0))))
- instance = TREE_OPERAND (instance, 0);
- /* fall through... */
- case CALL_EXPR:
- /* This is a call to a constructor, hence it's never zero. */
- if (TREE_HAS_CONSTRUCTOR (instance))
- {
- if (nonnull)
- *nonnull = 1;
- return 1;
- }
- return 0;
-
- case SAVE_EXPR:
- /* This is a call to a constructor, hence it's never zero. */
- if (TREE_HAS_CONSTRUCTOR (instance))
- {
- if (nonnull)
- *nonnull = 1;
- return 1;
- }
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
-
- case RTL_EXPR:
- /* This is a call to `new', hence it's never zero. */
- if (TREE_CALLS_NEW (instance))
- {
- if (nonnull)
- *nonnull = 1;
- return 1;
- }
- return 0;
-
- case PLUS_EXPR:
- case MINUS_EXPR:
- if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
- /* Propagate nonnull. */
- resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
- if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
- return 0;
-
- case NOP_EXPR:
- case CONVERT_EXPR:
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
-
- case ADDR_EXPR:
- if (nonnull)
- *nonnull = 1;
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
-
- case COMPONENT_REF:
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 1), nonnull);
-
- case WITH_CLEANUP_EXPR:
- if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
- /* fall through... */
- case VAR_DECL:
- case FIELD_DECL:
- if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE
- && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (instance))))
- {
- if (nonnull)
- *nonnull = 1;
- return 1;
- }
- /* fall through... */
- case TARGET_EXPR:
- case PARM_DECL:
- if (IS_AGGR_TYPE (TREE_TYPE (instance)))
- {
- if (nonnull)
- *nonnull = 1;
- return 1;
- }
- else if (nonnull)
- {
- if (instance == current_class_decl
- && flag_this_is_variable <= 0)
- {
- /* Some people still use `this = 0' inside destructors. */
- *nonnull = ! DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (current_function_decl));
- /* In a constructor, we know our type. */
- if (flag_this_is_variable < 0)
- return 1;
- }
- else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- /* Reference variables should be references to objects. */
- *nonnull = 1;
- }
- return 0;
-
- default:
- return 0;
- }
-}
-
-void
-init_class_processing ()
-{
- current_class_depth = 0;
- current_class_stacksize = 10;
- current_class_base = (tree *)xmalloc(current_class_stacksize * sizeof (tree));
- current_class_stack = current_class_base;
-
- current_lang_stacksize = 10;
- current_lang_base = (tree *)xmalloc(current_lang_stacksize * sizeof (tree));
- current_lang_stack = current_lang_base;
-
- delta_name = get_identifier (VTABLE_DELTA_NAME);
- pfn_name = get_identifier (VTABLE_PFN_NAME);
-
- /* Keep these values lying around. */
- the_null_vtable_entry = build_vtable_entry (integer_zero_node, integer_zero_node);
- base_layout_decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, error_mark_node);
- TREE_TYPE (base_layout_decl) = make_node (RECORD_TYPE);
-
- gcc_obstack_init (&class_obstack);
-}
-
-/* Set current scope to NAME. CODE tells us if this is a
- STRUCT, UNION, or ENUM environment.
-
- NAME may end up being NULL_TREE if this is an anonymous or
- late-bound struct (as in "struct { ... } foo;") */
-
-/* Here's a subroutine we need because C lacks lambdas. */
-static void
-unuse_fields (type)
- tree type;
-{
- tree fields;
-
- for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- {
- if (TREE_CODE (fields) != FIELD_DECL)
- continue;
-
- TREE_USED (fields) = 0;
- if (DECL_NAME (fields) == NULL_TREE
- && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
- unuse_fields (TREE_TYPE (fields));
- }
-}
-
-/* Set global variables CURRENT_CLASS_NAME and CURRENT_CLASS_TYPE to
- appropriate values, found by looking up the type definition of
- NAME (as a CODE).
-
- If MODIFY is 1, we set IDENTIFIER_CLASS_VALUE's of names
- which can be seen locally to the class. They are shadowed by
- any subsequent local declaration (including parameter names).
-
- If MODIFY is 2, we set IDENTIFIER_CLASS_VALUE's of names
- which have static meaning (i.e., static members, static
- member functions, enum declarations, etc).
-
- If MODIFY is 3, we set IDENTIFIER_CLASS_VALUE of names
- which can be seen locally to the class (as in 1), but
- know that we are doing this for declaration purposes
- (i.e. friend foo::bar (int)).
-
- So that we may avoid calls to lookup_name, we cache the _TYPE
- nodes of local TYPE_DECLs in the TREE_TYPE field of the name.
-
- For multiple inheritance, we perform a two-pass depth-first search
- of the type lattice. The first pass performs a pre-order search,
- marking types after the type has had its fields installed in
- the appropriate IDENTIFIER_CLASS_VALUE slot. The second pass merely
- unmarks the marked types. If a field or member function name
- appears in an ambiguous way, the IDENTIFIER_CLASS_VALUE of
- that name becomes `error_mark_node'. */
-
-void
-pushclass (type, modify)
- tree type;
- int modify;
-{
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "pushclass");
- debug_bindings_indentation += 4;
-#endif
-
- push_memoized_context (type, modify);
-
- current_class_depth++;
- *current_class_stack++ = current_class_name;
- *current_class_stack++ = current_class_type;
- if (current_class_stack >= current_class_base + current_class_stacksize)
- {
- current_class_base =
- (tree *)xrealloc (current_class_base,
- sizeof (tree) * (current_class_stacksize + 10));
- current_class_stack = current_class_base + current_class_stacksize;
- current_class_stacksize += 10;
- }
-
- current_class_name = TYPE_NAME (type);
- if (TREE_CODE (current_class_name) == TYPE_DECL)
- current_class_name = DECL_NAME (current_class_name);
- current_class_type = type;
-
- if (prev_class_type != NULL_TREE
- && (type != prev_class_type
- || TYPE_SIZE (prev_class_type) == NULL_TREE
- /* ??? Is this necessary any more? */
- || IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (prev_class_type)))
- && (current_class_depth == 1 || modify == 3))
- {
- /* Forcibly remove any old class remnants. */
- popclass (-1);
- prev_class_type = 0;
- }
-
- pushlevel_class ();
-
- if (modify)
- {
- tree tags;
- tree this_fndecl = current_function_decl;
-
- if (current_function_decl
- && DECL_CONTEXT (current_function_decl)
- && TREE_CODE (DECL_CONTEXT (current_function_decl)) == FUNCTION_DECL)
- current_function_decl = DECL_CONTEXT (current_function_decl);
- else
- current_function_decl = NULL_TREE;
-
- if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- {
- declare_uninstantiated_type_level ();
- overload_template_name (current_class_name, 0);
- }
- else if (type != prev_class_type)
- {
- build_mi_matrix (type);
- push_class_decls (type);
- free_mi_matrix ();
- prev_class_type = type;
- }
- else
- unuse_fields (type);
-
- for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
- {
- TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1;
- if (! TREE_PURPOSE (tags))
- continue;
- pushtag (TREE_PURPOSE (tags), TREE_VALUE (tags));
- if (IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (tags)) == NULL_TREE
- && TREE_CODE (TYPE_NAME (TREE_VALUE (tags))) == TYPE_DECL)
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (tags))
- = TYPE_NAME (TREE_VALUE (tags));
- }
-
- current_function_decl = this_fndecl;
- }
-
- if (flag_cadillac)
- cadillac_push_class (type);
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-/* Get out of the current class scope. If we were in a class scope
- previously, that is the one popped to. The flag MODIFY tells
- whether the current scope declarations needs to be modified
- as a result of popping to the previous scope. */
-void
-popclass (modify)
- int modify;
-{
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "popclass");
- debug_bindings_indentation += 4;
-#endif
-
- if (flag_cadillac)
- cadillac_pop_class ();
-
- if (modify < 0)
- {
- /* Back this old class out completely. */
- tree tags = CLASSTYPE_TAGS (prev_class_type);
-
- pop_class_decls (prev_class_type);
- while (tags)
- {
- TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (tags)) = NULL_TREE;
- tags = TREE_CHAIN (tags);
- }
- goto ret;
- }
-
- if (modify)
- {
- /* Just remove from this class what didn't make
- it into IDENTIFIER_CLASS_VALUE. */
- tree tags = CLASSTYPE_TAGS (current_class_type);
-
- while (tags)
- {
- TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
- if (TREE_PURPOSE (tags))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (tags)) = NULL_TREE;
- tags = TREE_CHAIN (tags);
- }
- }
- if (TREE_CODE (current_class_type) == UNINSTANTIATED_P_TYPE)
- undo_template_name_overload (current_class_name, 0);
- poplevel_class ();
-
- current_class_depth--;
- current_class_type = *--current_class_stack;
- current_class_name = *--current_class_stack;
-
- if (current_class_type)
- {
- if (CLASSTYPE_VTBL_PTR (current_class_type))
- {
- current_vtable_decl = lookup_name (DECL_NAME (CLASSTYPE_VTBL_PTR (current_class_type)), 0);
- if (current_vtable_decl)
- current_vtable_decl = build_indirect_ref (current_vtable_decl,
- NULL);
- }
- current_class_decl = lookup_name (get_identifier (THIS_NAME), 0);
- if (current_class_decl)
- {
- if (TREE_CODE (TREE_TYPE (current_class_decl)) == POINTER_TYPE)
- {
- tree temp;
- /* Can't call build_indirect_ref here, because it has special
- logic to return C_C_D given this argument. */
- C_C_D = build1 (INDIRECT_REF, current_class_type, current_class_decl);
- temp = TREE_TYPE (TREE_TYPE (current_class_decl));
- TREE_READONLY (C_C_D) = TYPE_READONLY (temp);
- TREE_SIDE_EFFECTS (C_C_D) = TYPE_VOLATILE (temp);
- TREE_THIS_VOLATILE (C_C_D) = TYPE_VOLATILE (temp);
- }
- else
- C_C_D = current_class_decl;
- }
- else C_C_D = NULL_TREE;
- }
- else
- {
- current_class_decl = NULL_TREE;
- current_vtable_decl = NULL_TREE;
- C_C_D = NULL_TREE;
- }
-
- pop_memoized_context (modify);
-
- ret:
- ;
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-/* Set global variables CURRENT_LANG_NAME to appropriate value
- so that behavior of name-mangling machinery is correct. */
-
-void
-push_lang_context (name)
- tree name;
-{
- *current_lang_stack++ = current_lang_name;
- if (current_lang_stack >= current_lang_base + current_lang_stacksize)
- {
- current_lang_base =
- (tree *)xrealloc (current_lang_base,
- sizeof (tree) * (current_lang_stacksize + 10));
- current_lang_stack = current_lang_base + current_lang_stacksize;
- current_lang_stacksize += 10;
- }
-
- if (name == lang_name_cplusplus)
- {
- strict_prototype = strict_prototypes_lang_cplusplus;
- current_lang_name = name;
- }
- else if (name == lang_name_c)
- {
- strict_prototype = strict_prototypes_lang_c;
- current_lang_name = name;
- }
- else
- error ("language string `\"%s\"' not recognized", IDENTIFIER_POINTER (name));
-
- if (flag_cadillac)
- cadillac_push_lang (name);
-}
-
-/* Get out of the current language scope. */
-void
-pop_lang_context ()
-{
- if (flag_cadillac)
- cadillac_pop_lang ();
-
- current_lang_name = *--current_lang_stack;
- if (current_lang_name == lang_name_cplusplus)
- strict_prototype = strict_prototypes_lang_cplusplus;
- else if (current_lang_name == lang_name_c)
- strict_prototype = strict_prototypes_lang_c;
-}
-
-int
-root_lang_context_p ()
-{
- return current_lang_stack == current_lang_base;
-}
-
-/* Type instantiation routines. */
-
-/* This function will instantiate the type of the expression given
- in RHS to match the type of LHSTYPE. If LHSTYPE is NULL_TREE,
- or other errors exist, the TREE_TYPE of RHS will be ERROR_MARK_NODE.
-
- This function is used in build_modify_expr, convert_arguments,
- build_c_cast, and compute_conversion_costs. */
-tree
-instantiate_type (lhstype, rhs, complain)
- tree lhstype, rhs;
- int complain;
-{
- if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
- {
- if (complain)
- error ("not enough type information");
- return error_mark_node;
- }
-
- if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs)))
- return rhs;
-
- /* This should really only be used when attempting to distinguish
- what sort of a pointer to function we have. For now, any
- arithmetic operation which is not supported on pointers
- is rejected as an error. */
-
- switch (TREE_CODE (rhs))
- {
- case TYPE_EXPR:
- case CONVERT_EXPR:
- case SAVE_EXPR:
- case CONSTRUCTOR:
- case BUFFER_REF:
- my_friendly_abort (177);
- return error_mark_node;
-
- case INDIRECT_REF:
- case ARRAY_REF:
- TREE_TYPE (rhs) = lhstype;
- lhstype = build_pointer_type (lhstype);
- TREE_OPERAND (rhs, 0)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
- if (TREE_OPERAND (rhs, 0) == error_mark_node)
- return error_mark_node;
-
- return rhs;
-
- case NOP_EXPR:
- rhs = copy_node (TREE_OPERAND (rhs, 0));
- TREE_TYPE (rhs) = unknown_type_node;
- return instantiate_type (lhstype, rhs, complain);
-
- case COMPONENT_REF:
- {
- tree field = TREE_OPERAND (rhs, 1);
- if (TREE_CODE (field) == TREE_LIST)
- {
- tree function = instantiate_type (lhstype, field, complain);
- if (function == error_mark_node)
- return error_mark_node;
- my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185);
- if (DECL_VINDEX (function))
- {
- tree base = TREE_OPERAND (rhs, 0);
- tree base_ptr = build_unary_op (ADDR_EXPR, base, 0);
- if (base_ptr == error_mark_node)
- return error_mark_node;
- base_ptr = convert_pointer_to (DECL_CONTEXT (function), base_ptr);
- if (base_ptr == error_mark_node)
- return error_mark_node;
- return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function));
- }
- return function;
- }
-
- my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 178);
- my_friendly_assert (!(TREE_CODE (TREE_TYPE (field)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (field)) == METHOD_TYPE),
- 179);
-
- TREE_TYPE (rhs) = lhstype;
- /* First look for an exact match */
-
- while (field && TREE_TYPE (field) != lhstype)
- field = TREE_CHAIN (field);
- if (field)
- {
- TREE_OPERAND (rhs, 1) = field;
- return rhs;
- }
-
- /* No exact match found, look for a compatible function. */
- field = TREE_OPERAND (rhs, 1);
- while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
- field = TREE_CHAIN (field);
- if (field)
- {
- TREE_OPERAND (rhs, 1) = field;
- field = TREE_CHAIN (field);
- while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
- field = TREE_CHAIN (field);
- if (field)
- {
- if (complain)
- error ("ambiguous overload for COMPONENT_REF requested");
- return error_mark_node;
- }
- }
- else
- {
- if (complain)
- error ("no appropriate overload exists for COMPONENT_REF");
- return error_mark_node;
- }
- return rhs;
- }
-
- case TREE_LIST:
- {
- tree elem, baselink, name;
- int globals = overloaded_globals_p (rhs);
-
- /* If there's only one function we know about, return that. */
- if (globals > 0 && TREE_CHAIN (rhs) == NULL_TREE)
- return TREE_VALUE (rhs);
-
- /* First look for an exact match. Search either overloaded
- functions or member functions. May have to undo what
- `default_conversion' might do to lhstype. */
-
- if (TREE_CODE (lhstype) == POINTER_TYPE)
- if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
- lhstype = TREE_TYPE (lhstype);
- else
- {
- if (complain)
- error ("invalid type combination for overload");
- return error_mark_node;
- }
-
- if (TREE_CODE (lhstype) != FUNCTION_TYPE && globals > 0)
- {
- if (complain)
- error ("cannot resolve overloaded function `%s' based on non-function type",
- IDENTIFIER_POINTER (TREE_PURPOSE (rhs)));
- return error_mark_node;
- }
-
- if (globals > 0)
- {
- my_friendly_assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL,
- 180);
- elem = rhs;
- while (elem)
- if (TREE_TYPE (TREE_VALUE (elem)) != lhstype)
- elem = TREE_CHAIN (elem);
- else
- return TREE_VALUE (elem);
- /* No exact match found, look for a compatible function. */
- elem = rhs;
- while (elem && ! comp_target_types (lhstype, TREE_TYPE (TREE_VALUE (elem)), 1))
- elem = TREE_CHAIN (elem);
- if (elem)
- {
- tree save_elem = TREE_VALUE (elem);
- elem = TREE_CHAIN (elem);
- while (elem && ! comp_target_types (lhstype, TREE_TYPE (TREE_VALUE (elem)), 0))
- elem = TREE_CHAIN (elem);
- if (elem)
- {
- if (complain)
- error ("ambiguous overload for overloaded function requested");
- return error_mark_node;
- }
- return save_elem;
- }
- if (complain)
- {
- if (TREE_CHAIN (rhs))
- error ("no appropriate overload for overloaded function `%s' exists",
- IDENTIFIER_POINTER (TREE_PURPOSE (rhs)));
- else
- error ("function `%s' has inappropriate type signature",
- IDENTIFIER_POINTER (TREE_PURPOSE (rhs)));
- }
- return error_mark_node;
- }
-
- if (TREE_NONLOCAL_FLAG (rhs))
- {
- /* Got to get it as a baselink. */
- rhs = lookup_fnfields (TYPE_BINFO (current_class_type),
- TREE_PURPOSE (rhs), 0);
- }
- else
- {
- my_friendly_assert (TREE_CHAIN (rhs) == NULL_TREE, 181);
- if (TREE_CODE (TREE_VALUE (rhs)) == TREE_LIST)
- rhs = TREE_VALUE (rhs);
- my_friendly_assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL,
- 182);
- }
-
- for (baselink = rhs; baselink;
- baselink = next_baselink (baselink))
- {
- elem = TREE_VALUE (baselink);
- while (elem)
- if (TREE_TYPE (elem) != lhstype)
- elem = TREE_CHAIN (elem);
- else
- return elem;
- }
-
- /* No exact match found, look for a compatible method. */
- for (baselink = rhs; baselink;
- baselink = next_baselink (baselink))
- {
- elem = TREE_VALUE (baselink);
- while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1))
- elem = TREE_CHAIN (elem);
- if (elem)
- {
- tree save_elem = elem;
- elem = TREE_CHAIN (elem);
- while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 0))
- elem = TREE_CHAIN (elem);
- if (elem)
- {
- if (complain)
- error ("ambiguous overload for overloaded method requested");
- return error_mark_node;
- }
- return save_elem;
- }
- name = DECL_NAME (TREE_VALUE (rhs));
- if (TREE_CODE (lhstype) == FUNCTION_TYPE && globals < 0)
- {
- /* Try to instantiate from non-member functions. */
- rhs = IDENTIFIER_GLOBAL_VALUE (name);
- if (rhs && TREE_CODE (rhs) == TREE_LIST)
- {
- /* This code seems to be missing a `return'. */
- my_friendly_abort (4);
- instantiate_type (lhstype, rhs, complain);
- }
- }
- }
- if (complain)
- error ("no static member functions named `%s'",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
-
- case CALL_EXPR:
- /* This is too hard for now. */
- my_friendly_abort (183);
- return error_mark_node;
-
- case PLUS_EXPR:
- case MINUS_EXPR:
- case COMPOUND_EXPR:
- TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
- if (TREE_OPERAND (rhs, 0) == error_mark_node)
- return error_mark_node;
- TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
- if (TREE_OPERAND (rhs, 1) == error_mark_node)
- return error_mark_node;
-
- TREE_TYPE (rhs) = lhstype;
- return rhs;
-
- case MULT_EXPR:
- case TRUNC_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case RDIV_EXPR:
- case TRUNC_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case CEIL_MOD_EXPR:
- case ROUND_MOD_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_CEIL_EXPR:
- case FIX_TRUNC_EXPR:
- case FLOAT_EXPR:
- case NEGATE_EXPR:
- case ABS_EXPR:
- case MAX_EXPR:
- case MIN_EXPR:
- case FFS_EXPR:
-
- case BIT_AND_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case LROTATE_EXPR:
- case RROTATE_EXPR:
-
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- if (complain)
- error ("illegal operation on uninstantiated type");
- return error_mark_node;
-
- case TRUTH_AND_EXPR:
- case TRUTH_OR_EXPR:
- case TRUTH_XOR_EXPR:
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- case TRUTH_ANDIF_EXPR:
- case TRUTH_ORIF_EXPR:
- case TRUTH_NOT_EXPR:
- if (complain)
- error ("not enough type information");
- return error_mark_node;
-
- case COND_EXPR:
- if (type_unknown_p (TREE_OPERAND (rhs, 0)))
- {
- if (complain)
- error ("not enough type information");
- return error_mark_node;
- }
- TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
- if (TREE_OPERAND (rhs, 1) == error_mark_node)
- return error_mark_node;
- TREE_OPERAND (rhs, 2) = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain);
- if (TREE_OPERAND (rhs, 2) == error_mark_node)
- return error_mark_node;
-
- TREE_TYPE (rhs) = lhstype;
- return rhs;
-
- case MODIFY_EXPR:
- TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
- if (TREE_OPERAND (rhs, 1) == error_mark_node)
- return error_mark_node;
-
- TREE_TYPE (rhs) = lhstype;
- return rhs;
-
- case ADDR_EXPR:
- if (TREE_CODE (lhstype) != POINTER_TYPE)
- {
- if (complain)
- error ("type for resolving address of overloaded function must be pointer type");
- return error_mark_node;
- }
- TREE_TYPE (rhs) = lhstype;
- lhstype = TREE_TYPE (lhstype);
- TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
- if (TREE_OPERAND (rhs, 0) == error_mark_node)
- return error_mark_node;
-
- mark_addressable (TREE_OPERAND (rhs, 0));
- return rhs;
-
- case ENTRY_VALUE_EXPR:
- my_friendly_abort (184);
- return error_mark_node;
-
- case ERROR_MARK:
- return error_mark_node;
-
- default:
- my_friendly_abort (185);
- return error_mark_node;
- }
-}
-
-/* Return the name of the virtual function pointer field
- (as an IDENTIFIER_NODE) for the given TYPE. Note that
- this may have to look back through base types to find the
- ultimate field name. (For single inheritance, these could
- all be the same name. Who knows for multiple inheritance). */
-static tree
-get_vfield_name (type)
- tree type;
-{
- tree binfo = TYPE_BINFO (type);
- char *buf;
-
- while (BINFO_BASETYPES (binfo)
- && TYPE_VIRTUAL_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
- && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0)))
- binfo = BINFO_BASETYPE (binfo, 0);
-
- type = BINFO_TYPE (binfo);
- buf = (char *)alloca (sizeof (VFIELD_NAME_FORMAT)
- + TYPE_NAME_LENGTH (type) + 2);
- sprintf (buf, VFIELD_NAME_FORMAT, TYPE_NAME_STRING (type));
- return get_identifier (buf);
-}
-
-void
-print_class_statistics ()
-{
-#ifdef GATHER_STATISTICS
- fprintf (stderr, "convert_harshness = %d\n", n_convert_harshness);
- fprintf (stderr, "compute_conversion_costs = %d\n", n_compute_conversion_costs);
- fprintf (stderr, "build_method_call = %d (inner = %d)\n",
- n_build_method_call, n_inner_fields_searched);
- if (n_vtables)
- {
- fprintf (stderr, "vtables = %d; vtable searches = %d\n",
- n_vtables, n_vtable_searches);
- fprintf (stderr, "vtable entries = %d; vtable elems = %d\n",
- n_vtable_entries, n_vtable_elems);
- }
-#endif
-}
diff --git a/gnu/gcc2/cc1plus/cp-class.h b/gnu/gcc2/cc1plus/cp-class.h
deleted file mode 100644
index 2c042d72741f..000000000000
--- a/gnu/gcc2/cc1plus/cp-class.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Variables and structures for overloading rules.
- Copyright (C) 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* The following structure is used when comparing various alternatives
- for overloading. The unsigned quantity `strikes.i' is used
- for fast comparison of two possibilities. This number is an
- aggregate of four constituents:
-
- EVIL: if this is non-zero, then the candidate should not be considered
- ELLIPSIS: if this is non-zero, then some actual argument has been matched
- against an ellipsis
- USER: if this is non-zero, then a user-defined type conversion is needed
- B_OR_D: if this is non-zero, then use a base pointer instead of the
- type of the pointer we started with.
- EASY: if this is non-zero, then we have a builtin conversion
- (such as int to long, int to float, etc) to do.
-
- If two candidates require user-defined type conversions, and the
- type conversions are not identical, then an ambiguity error
- is reported.
-
- If two candidates agree on user-defined type conversions,
- and one uses pointers of strictly higher type (derived where
- another uses base), then that alternative is silently chosen.
-
- If two candidates have a non-monotonic derived/base pointer
- relationship, and/or a non-monotonic easy conversion relationship,
- then a warning is emitted to show which paths are possible, and
- which one is being chosen.
-
- For example:
-
- int i;
- double x;
-
- overload f;
- int f (int, int);
- double f (double, double);
-
- f (i, x); // draws a warning
-
- struct B
- {
- f (int);
- } *bb;
- struct D : B
- {
- f (double);
- } *dd;
-
- dd->f (x); // exact match
- dd->f (i); // draws warning
-
- Note that this technique really only works for 255 arguments. Perhaps
- this is not enough. */
-
-struct candidate
-{
- tree function; /* A FUNCTION_DECL */
-
- unsigned char evil; /* !0 if this will never convert. */
- unsigned char ellipsis; /* !0 if a match against an ellipsis occurred */
- unsigned char user; /* !0 if at least one user-defined type conv. */
- unsigned short b_or_d; /* count number of derived->base or
- base->derived conv. */
- unsigned short easy; /* count number of builtin type conv. */
- tree arg; /* first parm to function. */
- unsigned short *harshness; /* Indexed by argument number, encodes
- evil, user, d_to_b, and easy strikes for
- that argument.
- At end of array, we store the index+1
- of where we started using default
- parameters, or 0 if there are none. */
- union
- {
- tree field; /* If no evil strikes, the FUNCTION_DECL of
- the function (if a member function). */
- int bad_arg; /* the index of the first bad argument:
- 0 if no bad arguments
- > 0 is first bad argument
- -1 if extra actual arguments
- -2 if too few actual arguments.
- -3 if const/non const method mismatch.
- -4 if type unification failed.
- -5 if contravariance violation. */
- } u;
-};
-int rank_for_overload ();
-
-/* Variables shared between cp-class.c and cp-call.c. */
-
-extern int n_vtables;
-extern int n_vtable_entries;
-extern int n_vtable_searches;
-extern int n_vtable_elems;
-extern int n_convert_harshness;
-extern int n_compute_conversion_costs;
-extern int n_build_method_call;
-extern int n_inner_fields_searched;
diff --git a/gnu/gcc2/cc1plus/cp-cvt.c b/gnu/gcc2/cc1plus/cp-cvt.c
deleted file mode 100644
index 998c5034925c..000000000000
--- a/gnu/gcc2/cc1plus/cp-cvt.c
+++ /dev/null
@@ -1,1790 +0,0 @@
-/* Language-level data type conversion for GNU C++.
- Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-
-/* This file contains the functions for converting C expressions
- to different data types. The only entry point is `convert'.
- Every language front end must have a `convert' function
- but what kind of conversions it does will depend on the language. */
-
-#include "config.h"
-#include "tree.h"
-#include "flags.h"
-#include "cp-tree.h"
-#include "convert.h"
-
-#undef NULL
-#define NULL (char *)0
-
-/* Change of width--truncation and extension of integers or reals--
- is represented with NOP_EXPR. Proper functioning of many things
- assumes that no other conversions can be NOP_EXPRs.
-
- Conversion between integer and pointer is represented with CONVERT_EXPR.
- Converting integer to real uses FLOAT_EXPR
- and real to integer uses FIX_TRUNC_EXPR.
-
- Here is a list of all the functions that assume that widening and
- narrowing is always done with a NOP_EXPR:
- In c-convert.c, convert_to_integer.
- In c-typeck.c, build_binary_op_nodefault (boolean ops),
- and truthvalue_conversion.
- In expr.c: expand_expr, for operands of a MULT_EXPR.
- In fold-const.c: fold.
- In tree.c: get_narrower and get_unwidened.
-
- C++: in multiple-inheritance, converting between pointers may involve
- adjusting them by a delta stored within the class definition. */
-
-/* Subroutines of `convert'. */
-
-static tree
-cp_convert_to_pointer (type, expr)
- tree type, expr;
-{
- register tree intype = TREE_TYPE (expr);
- register enum tree_code form = TREE_CODE (intype);
-
- if (form == POINTER_TYPE)
- {
- intype = TYPE_MAIN_VARIANT (intype);
-
- if (TYPE_MAIN_VARIANT (type) != intype
- && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
- && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
- {
- enum tree_code code = PLUS_EXPR;
- tree binfo = get_binfo (TREE_TYPE (type), TREE_TYPE (intype), 1);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (binfo == NULL_TREE)
- {
- binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 1);
- if (binfo == error_mark_node)
- return error_mark_node;
- code = MINUS_EXPR;
- }
- if (binfo)
- {
- if (TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (type))
- || TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (intype))
- || ! BINFO_OFFSET_ZEROP (binfo))
- {
- /* Need to get the path we took. */
- tree path;
-
- if (code == PLUS_EXPR)
- get_base_distance (TREE_TYPE (type), TREE_TYPE (intype), 0, &path);
- else
- get_base_distance (TREE_TYPE (intype), TREE_TYPE (type), 0, &path);
- return build_vbase_path (code, type, expr, path, 0);
- }
- }
- }
- return build1 (NOP_EXPR, type, expr);
- }
-
- my_friendly_assert (form != OFFSET_TYPE, 186);
-
- if (IS_AGGR_TYPE (intype))
- {
- /* If we cannot convert to the specific pointer type,
- try to convert to the type `void *'. */
- tree rval;
- rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);
- if (rval)
- {
- if (rval == error_mark_node)
- error ("ambiguous pointer conversion");
- return rval;
- }
- }
-
- return convert_to_pointer (type, expr);
-}
-
-/* Like convert, except permit conversions to take place which
- are not normally allowed due to visibility restrictions
- (such as conversion from sub-type to private super-type). */
-static tree
-convert_to_pointer_force (type, expr)
- tree type, expr;
-{
- register tree intype = TREE_TYPE (expr);
- register enum tree_code form = TREE_CODE (intype);
-
- if (integer_zerop (expr))
- {
- if (type == TREE_TYPE (null_pointer_node))
- return null_pointer_node;
- expr = build_int_2 (0, 0);
- TREE_TYPE (expr) = type;
- return expr;
- }
-
- if (form == POINTER_TYPE)
- {
- intype = TYPE_MAIN_VARIANT (intype);
-
- if (TYPE_MAIN_VARIANT (type) != intype
- && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
- && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
- {
- enum tree_code code = PLUS_EXPR;
- tree path;
- int distance = get_base_distance (TREE_TYPE (type),
- TREE_TYPE (intype), 0, &path);
- if (distance == -2)
- {
- ambig:
- error_with_aggr_type (TREE_TYPE (type), "type `%s' is ambiguous baseclass of `%s'",
- TYPE_NAME_STRING (TREE_TYPE (intype)));
- return error_mark_node;
- }
- if (distance == -1)
- {
- distance = get_base_distance (TREE_TYPE (intype),
- TREE_TYPE (type), 0, &path);
- if (distance == -2)
- goto ambig;
- if (distance < 0)
- /* Doesn't need any special help from us. */
- return build1 (NOP_EXPR, type, expr);
-
- code = MINUS_EXPR;
- }
- return build_vbase_path (code, type, expr, path, 0);
- }
- return build1 (NOP_EXPR, type, expr);
- }
-
- return cp_convert_to_pointer (type, expr);
-}
-
-/* We are passing something to a function which requires a reference.
- The type we are interested in is in TYPE. The initial
- value we have to begin with is in ARG.
-
- FLAGS controls how we manage visibility checking.
- CHECKCONST controls if we report error messages on const subversion. */
-static tree
-build_up_reference (type, arg, flags, checkconst)
- tree type, arg;
- int flags, checkconst;
-{
- tree rval, targ;
- int literal_flag = 0;
- tree argtype = TREE_TYPE (arg), basetype = argtype;
- tree target_type = TREE_TYPE (type);
- tree binfo = NULL_TREE;
-
- my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
- if (flags != 0
- && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
- && IS_AGGR_TYPE (argtype)
- && IS_AGGR_TYPE (target_type))
- {
- binfo = get_binfo (target_type, argtype,
- (flags & LOOKUP_PROTECTED_OK) ? 3 : 2);
- if ((flags & LOOKUP_PROTECT) && binfo == error_mark_node)
- return error_mark_node;
- if (basetype == NULL_TREE)
- return (tree) error_not_base_type (target_type, argtype);
- basetype = BINFO_TYPE (binfo);
- }
-
- /* Pass along const and volatile down into the type. */
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
- target_type = build_type_variant (target_type, TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- targ = arg;
- if (TREE_CODE (targ) == SAVE_EXPR)
- targ = TREE_OPERAND (targ, 0);
-
- switch (TREE_CODE (targ))
- {
- case INDIRECT_REF:
- /* This is a call to a constructor which did not know what it was
- initializing until now: it needs to initialize a temporary. */
- if (TREE_HAS_CONSTRUCTOR (targ))
- {
- tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0), 1);
- TREE_HAS_CONSTRUCTOR (targ) = 0;
- return build_up_reference (type, temp, flags, 1);
- }
- /* Let &* cancel out to simplify resulting code.
- Also, throw away intervening NOP_EXPRs. */
- arg = TREE_OPERAND (targ, 0);
- if (TREE_CODE (arg) == NOP_EXPR || TREE_CODE (arg) == NON_LVALUE_EXPR
- || (TREE_CODE (arg) == CONVERT_EXPR && TREE_REFERENCE_EXPR (arg)))
- arg = TREE_OPERAND (arg, 0);
-
- /* in doing a &*, we have to get rid of the const'ness on the pointer
- value. Haven't thought about volatile here. Pointers come to mind
- here. */
- if (TREE_READONLY (arg))
- {
- arg = copy_node (arg);
- TREE_READONLY (arg) = 0;
- }
-
- rval = build1 (CONVERT_EXPR, type, arg);
- TREE_REFERENCE_EXPR (rval) = 1;
-
- /* propagate the const flag on something like:
-
- class Base {
- public:
- int foo;
- };
-
- class Derived : public Base {
- public:
- int bar;
- };
-
- void func(Base&);
-
- void func2(const Derived& d) {
- func(d);
- }
-
- on the d parameter. The below could have been avoided, if the flags
- were down in the tree, not sure why they are not. (mrs) */
- /* The below code may have to be propagated to other parts of this
- switch. */
- if (TREE_READONLY (targ) && !TREE_READONLY (arg)
- && (TREE_CODE (arg) == PARM_DECL || TREE_CODE (arg) == VAR_DECL)
- && TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
- && (TYPE_READONLY (target_type) && checkconst))
- {
- arg = copy_node (arg);
- TREE_READONLY (arg) = TREE_READONLY (targ);
- }
- literal_flag = TREE_CONSTANT (arg);
-
- goto done_but_maybe_warn;
-
- /* Get this out of a register if we happened to be in one by accident.
- Also, build up references to non-lvalues it we must. */
- /* For &x[y], return (&) x+y */
- case ARRAY_REF:
- if (mark_addressable (TREE_OPERAND (targ, 0)) == 0)
- return error_mark_node;
- rval = build_binary_op (PLUS_EXPR, TREE_OPERAND (targ, 0),
- TREE_OPERAND (targ, 1), 1);
- TREE_TYPE (rval) = type;
- if (TREE_CONSTANT (TREE_OPERAND (targ, 1))
- && staticp (TREE_OPERAND (targ, 0)))
- TREE_CONSTANT (rval) = 1;
- goto done;
-
- case SCOPE_REF:
- /* Could be a reference to a static member. */
- {
- tree field = TREE_OPERAND (targ, 1);
- if (TREE_STATIC (field))
- {
- rval = build1 (ADDR_EXPR, type, field);
- literal_flag = 1;
- goto done;
- }
- }
-
- /* We should have farmed out member pointers above. */
- my_friendly_abort (188);
-
- case COMPONENT_REF:
- rval = build_component_addr (targ, build_pointer_type (argtype),
- "attempt to make a reference to bit-field structure member `%s'");
- TREE_TYPE (rval) = type;
- literal_flag = staticp (TREE_OPERAND (targ, 0));
-
- goto done_but_maybe_warn;
-
- /* Anything not already handled and not a true memory reference
- needs to have a reference built up. Do so silently for
- things like integers and return values from function,
- but complain if we need a reference to something declared
- as `register'. */
-
- case RESULT_DECL:
- if (staticp (targ))
- literal_flag = 1;
- TREE_ADDRESSABLE (targ) = 1;
- put_var_into_stack (targ);
- break;
-
- case PARM_DECL:
- if (targ == current_class_decl)
- {
- error ("address of `this' not available");
-#if 0
- /* This code makes the following core dump the compiler on a sun4,
- if the code below is used.
-
- class e_decl;
- class a_decl;
- typedef a_decl* a_ref;
-
- class a_s {
- public:
- a_s();
- void* append(a_ref& item);
- };
- class a_decl {
- public:
- a_decl (e_decl *parent);
- a_s generic_s;
- a_s decls;
- e_decl* parent;
- };
-
- class e_decl {
- public:
- e_decl();
- a_s implementations;
- };
-
- void foobar(void *);
-
- a_decl::a_decl(e_decl *parent) {
- parent->implementations.append(this);
- }
- */
-
- TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */
- put_var_into_stack (targ);
- break;
-#else
- return error_mark_node;
-#endif
- }
- /* Fall through. */
- case VAR_DECL:
- case CONST_DECL:
- if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ))
- warning ("address needed to build reference for `%s', which is declared `register'",
- IDENTIFIER_POINTER (DECL_NAME (targ)));
- else if (staticp (targ))
- literal_flag = 1;
-
- TREE_ADDRESSABLE (targ) = 1;
- put_var_into_stack (targ);
- break;
-
- case COMPOUND_EXPR:
- {
- tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1),
- LOOKUP_PROTECT, checkconst);
- rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference);
- TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1));
- return rval;
- }
-
- case MODIFY_EXPR:
- case INIT_EXPR:
- {
- tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0),
- LOOKUP_PROTECT, checkconst);
- rval = build (COMPOUND_EXPR, type, arg, real_reference);
- TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0));
- return rval;
- }
-
- case COND_EXPR:
- return build (COND_EXPR, type,
- TREE_OPERAND (targ, 0),
- build_up_reference (type, TREE_OPERAND (targ, 1),
- LOOKUP_PROTECT, checkconst),
- build_up_reference (type, TREE_OPERAND (targ, 2),
- LOOKUP_PROTECT, checkconst));
-
- case WITH_CLEANUP_EXPR:
- return build (WITH_CLEANUP_EXPR, type,
- build_up_reference (type, TREE_OPERAND (targ, 0),
- LOOKUP_PROTECT, checkconst),
- 0, TREE_OPERAND (targ, 2));
-
- case BIND_EXPR:
- arg = TREE_OPERAND (targ, 1);
- if (arg == NULL_TREE)
- {
- compiler_error ("({ ... }) expression not expanded when needed for reference");
- return error_mark_node;
- }
- rval = build1 (ADDR_EXPR, type, arg);
- TREE_REFERENCE_EXPR (rval) = 1;
- return rval;
-
- default:
- break;
- }
-
- if (TREE_ADDRESSABLE (targ) == 0)
- {
- tree temp;
-
- if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))
- {
- temp = build_cplus_new (argtype, targ, 1);
- rval = build1 (ADDR_EXPR, type, temp);
- goto done;
- }
- else
- {
- temp = get_temp_name (argtype, 0);
- if (global_bindings_p ())
- {
- /* Give this new temp some rtl and initialize it. */
- DECL_INITIAL (temp) = targ;
- TREE_STATIC (temp) = 1;
- finish_decl (temp, targ, NULL_TREE, 0);
- /* Do this after declaring it static. */
- rval = build_unary_op (ADDR_EXPR, temp, 0);
- literal_flag = TREE_CONSTANT (rval);
- goto done;
- }
- else
- {
- rval = build_unary_op (ADDR_EXPR, temp, 0);
- /* Put a value into the rtl. */
- if (IS_AGGR_TYPE (argtype))
- {
- /* This may produce surprising results,
- since we commit to initializing the temp
- when the temp may not actually get used. */
- expand_aggr_init (temp, targ, 0);
- TREE_TYPE (rval) = type;
- literal_flag = TREE_CONSTANT (rval);
- goto done;
- }
- else
- {
- if (binfo && !BINFO_OFFSET_ZEROP (binfo))
- rval = convert_pointer_to (target_type, rval);
- else
- TREE_TYPE (rval) = type;
- return build (COMPOUND_EXPR, type,
- build (MODIFY_EXPR, argtype, temp, arg), rval);
- }
- }
- }
- }
- else
- {
- if (TREE_CODE (arg) == SAVE_EXPR)
- my_friendly_abort (5);
- rval = build1 (ADDR_EXPR, type, arg);
- }
-
- done_but_maybe_warn:
- if (checkconst && TREE_READONLY (arg) && ! TYPE_READONLY (target_type))
- readonly_error (arg, "conversion to reference", 1);
-
- done:
- if (TYPE_USES_COMPLEX_INHERITANCE (argtype))
- {
- TREE_TYPE (rval) = TYPE_POINTER_TO (argtype);
- rval = convert_pointer_to (target_type, rval);
- TREE_TYPE (rval) = type;
- }
- TREE_CONSTANT (rval) = literal_flag;
- return rval;
-}
-
-/* For C++: Only need to do one-level references, but cannot
- get tripped up on signed/unsigned differences.
-
- If DECL is NULL_TREE it means convert as though casting (by force).
- If it is ERROR_MARK_NODE, it means the conversion is implicit,
- and that temporaries may be created.
- Make sure the use of user-defined conversion operators is un-ambiguous.
- Otherwise, DECL is a _DECL node which can be used in error reporting.
-
- FNDECL, PARMNUM, and ERRTYPE are only used when checking for use of
- volatile or const references where they aren't desired. */
-
-tree
-convert_to_reference (decl, reftype, expr, fndecl, parmnum,
- errtype, strict, flags)
-
- tree decl;
- tree reftype, expr;
- tree fndecl;
- int parmnum;
- char *errtype;
- int strict, flags;
-{
- register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
- register tree intype = TREE_TYPE (expr);
- register enum tree_code form = TREE_CODE (intype);
- tree rval = NULL_TREE;
-
- if (form == REFERENCE_TYPE)
- intype = TREE_TYPE (intype);
- intype = TYPE_MAIN_VARIANT (intype);
-
- /* @@ Probably need to have a check for X(X&) here. */
-
- if (IS_AGGR_TYPE (intype))
- {
- rval = build_type_conversion (CONVERT_EXPR, reftype, expr, 1);
- if (rval)
- {
- if (rval == error_mark_node)
- error ("ambiguous pointer conversion");
- return rval;
- }
- else if (type != intype
- && (rval = build_type_conversion (CONVERT_EXPR, type, expr, 1)))
- {
- if (rval == error_mark_node)
- return rval;
- if (TYPE_NEEDS_DESTRUCTOR (type))
- {
- rval = convert_to_reference (NULL_TREE, reftype, rval, NULL_TREE,
--1, (char *)NULL, strict, flags);
- }
- else
- {
- decl = get_temp_name (type, 0);
- rval = build (INIT_EXPR, type, decl, rval);
- rval = build (COMPOUND_EXPR, reftype, rval,
- convert_to_reference (NULL_TREE, reftype, decl,
- NULL_TREE, -1, (char*)NULL,
- strict, flags));
- }
- }
-
- if (form == REFERENCE_TYPE
- && type != intype
- && TYPE_USES_COMPLEX_INHERITANCE (intype))
- {
- /* If it may move around, build a fresh reference. */
- expr = convert_from_reference (expr);
- form = TREE_CODE (TREE_TYPE (expr));
- }
- }
-
- /* @@ Perhaps this should try to go through a constructor first
- @@ for proper initialization, but I am not sure when that
- @@ is needed or desirable.
-
- @@ The second disjunct is provided to make references behave
- @@ as some people think they should, i.e., an interconvertibility
- @@ between references to builtin types (such as short and
- @@ unsigned short). There should be no conversion between
- @@ types whose codes are different, or whose sizes are different. */
-
- if (((IS_AGGR_TYPE (type) || IS_AGGR_TYPE (intype))
- && comptypes (type, intype, strict))
- || (!IS_AGGR_TYPE (type)
- && TREE_CODE (type) == TREE_CODE (intype)
- && int_size_in_bytes (type) == int_size_in_bytes (intype)))
- {
- /* Section 13. */
- /* Since convert_for_initialization didn't call convert_for_assignment,
- we have to do this checking here. XXX We should have a common
- routine between here and convert_for_assignment. */
- if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
- {
- register tree ttl = TREE_TYPE (reftype);
- register tree ttr = TREE_TYPE (TREE_TYPE (expr));
-
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- warn_for_assignment ("%s of non-`const &' reference from `const &'",
- "reference to const given for argument %d of `%s'",
- errtype, fndecl, parmnum, pedantic);
- if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s of non-`volatile &' reference from `volatile &'",
- "reference to volatile given for argument %d of `%s'",
- errtype, fndecl, parmnum, pedantic);
- }
-
- /* If EXPR is of aggregate type, and is really a CALL_EXPR,
- then we don't need to convert it to reference type if
- it is only being used to initialize DECL which is also
- of the same aggregate type. */
- if (form == REFERENCE_TYPE
- || (decl != NULL_TREE && decl != error_mark_node
- && IS_AGGR_TYPE (type)
- && TREE_CODE (expr) == CALL_EXPR
- && TYPE_MAIN_VARIANT (type) == intype))
- {
- if (decl && decl != error_mark_node)
- {
- tree e1 = build (INIT_EXPR, void_type_node, decl, expr);
- tree e2;
-
- TREE_SIDE_EFFECTS (e1) = 1;
- if (form == REFERENCE_TYPE)
- e2 = build1 (NOP_EXPR, reftype, decl);
- else
- {
- e2 = build_unary_op (ADDR_EXPR, decl, 0);
- TREE_TYPE (e2) = reftype;
- TREE_REFERENCE_EXPR (e2) = 1;
- }
- return build_compound_expr (tree_cons (NULL_TREE, e1,
- build_tree_list (NULL_TREE, e2)));
- }
- expr = copy_node (expr);
- TREE_TYPE (expr) = reftype;
- return expr;
- }
- if (decl == error_mark_node)
- flags |= LOOKUP_PROTECTED_OK;
- return build_up_reference (reftype, expr, flags, decl!=NULL_TREE);
- }
-
- /* Definitely need to go through a constructor here. */
- if (TYPE_HAS_CONSTRUCTOR (type))
- {
- tree init = build_method_call (NULL_TREE, constructor_name (type),
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (type), LOOKUP_NO_CONVERSION);
-
- if (init != error_mark_node)
- if (rval)
- {
- error ("both constructor and type conversion operator apply");
- return error_mark_node;
- }
-
- init = build_method_call (NULL_TREE, constructor_name (type),
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (type), LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
-
- if (init == error_mark_node)
- return error_mark_node;
- rval = build_cplus_new (type, init, 1);
- if (decl == error_mark_node)
- flags |= LOOKUP_PROTECTED_OK;
- return build_up_reference (reftype, rval, flags, decl!=NULL_TREE);
- }
-
- my_friendly_assert (form != OFFSET_TYPE, 189);
-
- /* This is in two pieces for now, because pointer to first becomes
- invalid once type_as_string is called again. */
- error ("cannot convert type `%s'", type_as_string (intype));
- error (" to type `%s'", type_as_string (reftype));
-
- return error_mark_node;
-}
-
-/* We are using a reference VAL for its value. Bash that reference all the
- way down to its lowest form. */
-tree
-convert_from_reference (val)
- tree val;
-{
- tree type = TREE_TYPE (val);
-
- if (TREE_CODE (type) == OFFSET_TYPE)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- tree target_type = TREE_TYPE (type);
- tree nval;
-
- /* This can happen if we cast to a reference type. */
- if (TREE_CODE (val) == ADDR_EXPR)
- {
- nval = build1 (NOP_EXPR, build_pointer_type (target_type), val);
- nval = build_indirect_ref (nval, 0);
- /* The below was missing, are other important flags missing too? */
- TREE_SIDE_EFFECTS (nval) = TREE_SIDE_EFFECTS (val);
- return nval;
- }
-
- nval = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (target_type), val);
-
- TREE_THIS_VOLATILE (nval) = TYPE_VOLATILE (target_type);
- TREE_SIDE_EFFECTS (nval) = TYPE_VOLATILE (target_type);
- TREE_READONLY (nval) = TYPE_READONLY (target_type);
- /* The below was missing, are other important flags missing too? */
- TREE_SIDE_EFFECTS (nval) = TREE_SIDE_EFFECTS (val);
- return nval;
- }
- return val;
-}
-
-/* See if there is a constructor of type TYPE which will convert
- EXPR. The reference manual seems to suggest (8.5.6) that we need
- not worry about finding constructors for base classes, then converting
- to the derived class.
-
- MSGP is a pointer to a message that would be an appropriate error
- string. If MSGP is NULL, then we are not interested in reporting
- errors. */
-tree
-convert_to_aggr (type, expr, msgp, protect)
- tree type, expr;
- char **msgp;
- int protect;
-{
- tree basetype = type;
- tree name = TYPE_IDENTIFIER (basetype);
- tree function, fndecl, fntype, parmtypes, parmlist, result;
- tree method_name;
- enum visibility_type visibility;
- int can_be_private, can_be_protected;
-
- if (! TYPE_HAS_CONSTRUCTOR (basetype))
- {
- if (msgp)
- *msgp = "type `%s' does not have a constructor";
- return error_mark_node;
- }
-
- visibility = visibility_public;
- can_be_private = 0;
- can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name;
-
- parmlist = build_tree_list (NULL_TREE, expr);
- parmtypes = tree_cons (NULL_TREE, TREE_TYPE (expr), void_list_node);
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
- parmlist = tree_cons (NULL_TREE, integer_one_node, parmlist);
- }
-
- /* The type of the first argument will be filled in inside the loop. */
- parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);
- parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes);
-
- method_name = build_decl_overload (name, parmtypes, 1);
-
- /* constructors are up front. */
- fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
- if (TYPE_HAS_DESTRUCTOR (basetype))
- fndecl = DECL_CHAIN (fndecl);
-
- while (fndecl)
- {
- if (DECL_ASSEMBLER_NAME (fndecl) == method_name)
- {
- function = fndecl;
- if (protect)
- {
- if (TREE_PRIVATE (fndecl))
- {
- can_be_private =
- (basetype == current_class_type
- || is_friend (basetype, current_function_decl)
- || purpose_member (basetype, DECL_VISIBILITY (fndecl)));
- if (! can_be_private)
- goto found;
- }
- else if (TREE_PROTECTED (fndecl))
- {
- if (! can_be_protected)
- goto found;
- }
- }
- goto found_and_ok;
- }
- fndecl = DECL_CHAIN (fndecl);
- }
-
- /* No exact conversion was found. See if an approximate
- one will do. */
- fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
- if (TYPE_HAS_DESTRUCTOR (basetype))
- fndecl = DECL_CHAIN (fndecl);
-
- {
- int saw_private = 0;
- int saw_protected = 0;
- struct candidate *candidates =
- (struct candidate *) alloca ((decl_list_length (fndecl)+1) * sizeof (struct candidate));
- struct candidate *cp = candidates;
-
- while (fndecl)
- {
- function = fndecl;
- cp->harshness = (unsigned short *)alloca (3 * sizeof (short));
- compute_conversion_costs (fndecl, parmlist, cp, 2);
- if (cp->evil == 0)
- {
- cp->u.field = fndecl;
- if (protect)
- {
- if (TREE_PRIVATE (fndecl))
- visibility = visibility_private;
- else if (TREE_PROTECTED (fndecl))
- visibility = visibility_protected;
- else
- visibility = visibility_public;
- }
- else
- visibility = visibility_public;
-
- if (visibility == visibility_private
- ? (basetype == current_class_type
- || is_friend (basetype, cp->function)
- || purpose_member (basetype, DECL_VISIBILITY (fndecl)))
- : visibility == visibility_protected
- ? (can_be_protected
- || purpose_member (basetype, DECL_VISIBILITY (fndecl)))
- : 1)
- {
- if (cp->user == 0 && cp->b_or_d == 0
- && cp->easy <= 1)
- {
- goto found_and_ok;
- }
- cp++;
- }
- else
- {
- if (visibility == visibility_private)
- saw_private = 1;
- else
- saw_protected = 1;
- }
- }
- fndecl = DECL_CHAIN (fndecl);
- }
- if (cp - candidates)
- {
- /* Rank from worst to best. Then cp will point to best one.
- Private fields have their bits flipped. For unsigned
- numbers, this should make them look very large.
- If the best alternate has a (signed) negative value,
- then all we ever saw were private members. */
- if (cp - candidates > 1)
- qsort (candidates, /* char *base */
- cp - candidates, /* int nel */
- sizeof (struct candidate), /* int width */
- rank_for_overload); /* int (*compar)() */
-
- --cp;
- if (cp->evil > 1)
- {
- if (msgp)
- *msgp = "ambiguous type conversion possible for `%s'";
- return error_mark_node;
- }
-
- function = cp->function;
- fndecl = cp->u.field;
- goto found_and_ok;
- }
- else if (msgp)
- {
- if (saw_private)
- if (saw_protected)
- *msgp = "only private and protected conversions apply";
- else
- *msgp = "only private conversions apply";
- else if (saw_protected)
- *msgp = "only protected conversions apply";
- }
- return error_mark_node;
- }
- /* NOTREACHED */
-
- not_found:
- if (msgp) *msgp = "no appropriate conversion to type `%s'";
- return error_mark_node;
- found:
- if (visibility == visibility_private)
- if (! can_be_private)
- {
- if (msgp)
- *msgp = TREE_PRIVATE (fndecl)
- ? "conversion to type `%s' is private"
- : "conversion to type `%s' is from private base class";
- return error_mark_node;
- }
- if (visibility == visibility_protected)
- if (! can_be_protected)
- {
- if (msgp)
- *msgp = TREE_PRIVATE (fndecl)
- ? "conversion to type `%s' is protected"
- : "conversion to type `%s' is from protected base class";
- return error_mark_node;
- }
- function = fndecl;
- found_and_ok:
-
- /* It will convert, but we don't do anything about it yet. */
- if (msgp == 0)
- return NULL_TREE;
-
- fntype = TREE_TYPE (function);
- if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL)
- function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
- else
- function = default_conversion (function);
-
- result = build_nt (CALL_EXPR, function,
- convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
- parmlist, NULL_TREE, LOOKUP_NORMAL),
- NULL_TREE);
- TREE_TYPE (result) = TREE_TYPE (fntype);
- TREE_SIDE_EFFECTS (result) = 1;
- TREE_RAISES (result) = !! TYPE_RAISES_EXCEPTIONS (fntype);
- return result;
-}
-
-/* Call this when we know (for any reason) that expr is
- not, in fact, zero. */
-tree
-convert_pointer_to (binfo, expr)
- tree binfo, expr;
-{
- register tree intype = TREE_TYPE (expr);
- tree ptr_type;
- tree type, rval;
-
- if (TREE_CODE (binfo) == TREE_VEC)
- type = BINFO_TYPE (binfo);
- else if (IS_AGGR_TYPE (binfo))
- {
- type = binfo;
- binfo = TYPE_BINFO (binfo);
- }
- else
- {
- type = binfo;
- binfo = NULL_TREE;
- }
-
- ptr_type = build_pointer_type (type);
- if (ptr_type == TYPE_MAIN_VARIANT (intype))
- return expr;
-
- if (intype == error_mark_node)
- return error_mark_node;
-
- my_friendly_assert (!integer_zerop (expr), 191);
-
- if (TREE_CODE (type) == RECORD_TYPE
- && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE
- && type != TYPE_MAIN_VARIANT (TREE_TYPE (intype)))
- {
- tree path;
- int distance
- = get_base_distance (type, TYPE_MAIN_VARIANT (TREE_TYPE (intype)),
- 0, &path);
-
- /* This function shouldn't be called with unqualified arguments
- but if it is, give them an error message that they can read.
- */
- if (distance < 0)
- {
- error ("cannot convert a pointer of type `%s'",
- TYPE_NAME_STRING (TREE_TYPE (intype)));
- error_with_aggr_type (type, "to a pointer of type `%s'");
-
- return error_mark_node;
- }
-
- return build_vbase_path (PLUS_EXPR, ptr_type, expr, path, 1);
- }
- rval = build1 (NOP_EXPR, ptr_type,
- TREE_CODE (expr) == NOP_EXPR ? TREE_OPERAND (expr, 0) : expr);
- TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
- return rval;
-}
-
-/* Same as above, but don't abort if we get an "ambiguous" baseclass.
- There's only one virtual baseclass we are looking for, and once
- we find one such virtual baseclass, we have found them all. */
-
-tree
-convert_pointer_to_vbase (binfo, expr)
- tree binfo;
- tree expr;
-{
- tree intype = TREE_TYPE (TREE_TYPE (expr));
- tree binfos = TYPE_BINFO_BASETYPES (intype);
- int i;
-
- for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
- {
- tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
- if (BINFO_TYPE (binfo) == basetype)
- return convert_pointer_to (binfo, expr);
- if (binfo_member (BINFO_TYPE (binfo), CLASSTYPE_VBASECLASSES (basetype)))
- return convert_pointer_to_vbase (binfo, convert_pointer_to (basetype, expr));
- }
- my_friendly_abort (6);
- /* NOTREACHED */
- return NULL_TREE;
-}
-
-/* Create an expression whose value is that of EXPR,
- converted to type TYPE. The TREE_TYPE of the value
- is always TYPE. This function implements all reasonable
- conversions; callers should filter out those that are
- not permitted by the language being compiled. */
-
-tree
-convert (type, expr)
- tree type, expr;
-{
- register tree e = expr;
- register enum tree_code code = TREE_CODE (type);
-
- if (type == TREE_TYPE (expr)
- || TREE_CODE (expr) == ERROR_MARK)
- return expr;
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
- return fold (build1 (NOP_EXPR, type, expr));
- if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
- return error_mark_node;
- if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)
- {
- error ("void value not ignored as it ought to be");
- return error_mark_node;
- }
- if (code == VOID_TYPE)
- {
- tree rval = build_type_conversion (NOP_EXPR, type, e, 0);
- /* If we can convert to void type via a type conversion, do so. */
- if (rval)
- return rval;
- return build1 (CONVERT_EXPR, type, e);
- }
-#if 0
- /* This is incorrect. A truncation can't be stripped this way.
- Extensions will be stripped by the use of get_unwidened. */
- if (TREE_CODE (expr) == NOP_EXPR)
- return convert (type, TREE_OPERAND (expr, 0));
-#endif
-
- /* Just convert to the type of the member. */
- if (code == OFFSET_TYPE)
- {
- type = TREE_TYPE (type);
- code = TREE_CODE (type);
- }
-
- /* C++ */
- if (code == REFERENCE_TYPE)
- return fold (convert_to_reference (error_mark_node,
- type, e,
- NULL_TREE, -1, (char *)NULL,
- -1, LOOKUP_NORMAL));
- else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
- e = convert_from_reference (e);
-
- if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
- {
- tree intype = TREE_TYPE (expr);
- enum tree_code form = TREE_CODE (intype);
- if (flag_int_enum_equivalence == 0
- && TREE_CODE (type) == ENUMERAL_TYPE
- && form == INTEGER_TYPE)
- {
- if (pedantic)
- pedwarn ("anachronistic conversion from integer type to enumeral type `%s'",
- TYPE_NAME_STRING (type));
- if (flag_pedantic_errors)
- return error_mark_node;
- }
- if (form == OFFSET_TYPE)
- error_with_decl (TYPE_NAME (TYPE_OFFSET_BASETYPE (intype)),
- "pointer-to-member expression object not composed with type `%s' object");
- else if (IS_AGGR_TYPE (intype))
- {
- tree rval;
- rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);
- if (rval) return rval;
- error ("aggregate value used where an integer was expected");
- return error_mark_node;
- }
- return fold (convert_to_integer (type, e));
- }
- if (code == POINTER_TYPE)
- return fold (cp_convert_to_pointer (type, e));
- if (code == REAL_TYPE)
- {
- if (IS_AGGR_TYPE (TREE_TYPE (e)))
- {
- tree rval;
- rval = build_type_conversion (CONVERT_EXPR, type, e, 1);
- if (rval)
- return rval;
- else
- error ("aggregate value used where a floating point value was expected");
- }
- return fold (convert_to_real (type, e));
- }
-
- /* New C++ semantics: since assignment is now based on
- memberwise copying, if the rhs type is derived from the
- lhs type, then we may still do a conversion. */
- if (IS_AGGR_TYPE_CODE (code))
- {
- tree dtype = TREE_TYPE (e);
-
- if (TREE_CODE (dtype) == REFERENCE_TYPE)
- {
- e = convert_from_reference (e);
- dtype = TREE_TYPE (e);
- }
- dtype = TYPE_MAIN_VARIANT (dtype);
-
- /* Conversion between aggregate types. New C++ semantics allow
- objects of derived type to be cast to objects of base type.
- Old semantics only allowed this between pointers.
-
- There may be some ambiguity between using a constructor
- vs. using a type conversion operator when both apply. */
-
- if (IS_AGGR_TYPE (dtype))
- {
- tree binfo;
-
- tree conversion = TYPE_HAS_CONVERSION (dtype)
- ? build_type_conversion (CONVERT_EXPR, type, e, 1) : NULL_TREE;
-
- if (TYPE_HAS_CONSTRUCTOR (type))
- {
- tree rval = build_method_call (NULL_TREE, constructor_name (type),
- build_tree_list (NULL_TREE, e),
- TYPE_BINFO (type),
- conversion ? LOOKUP_NO_CONVERSION : 0);
-
- if (rval != error_mark_node)
- {
- if (conversion)
- {
- error ("both constructor and type conversion operator apply");
- return error_mark_node;
- }
- /* call to constructor successful. */
- rval = build_cplus_new (type, rval, 0);
- return rval;
- }
- }
- /* Type conversion successful/applies. */
- if (conversion)
- {
- if (conversion == error_mark_node)
- error ("ambiguous pointer conversion");
- return conversion;
- }
-
- /* now try normal C++ assignment semantics. */
- binfo = TYPE_BINFO (dtype);
- if (BINFO_TYPE (binfo) == type
- || (binfo = get_binfo (type, dtype, 1)))
- {
- if (binfo == error_mark_node)
- return error_mark_node;
- }
- if (binfo != NULL_TREE)
- {
- if (lvalue_p (e))
- {
- e = build_unary_op (ADDR_EXPR, e, 0);
-
- if (! BINFO_OFFSET_ZEROP (binfo))
- e = build (PLUS_EXPR, TYPE_POINTER_TO (type),
- e, BINFO_OFFSET (binfo));
- return build1 (INDIRECT_REF, type, e);
- }
-
- sorry ("addressable aggregates");
- return error_mark_node;
- }
- error ("conversion between incompatible aggregate types requested");
- return error_mark_node;
- }
- /* conversion from non-aggregate to aggregate type requires constructor. */
- else if (TYPE_HAS_CONSTRUCTOR (type))
- {
- tree rval;
- tree init = build_method_call (NULL_TREE, constructor_name (type),
- build_tree_list (NULL_TREE, e),
- TYPE_BINFO (type), LOOKUP_NORMAL);
- if (init == error_mark_node)
- {
- error_with_aggr_type (type, "in conversion to type `%s'");
- return error_mark_node;
- }
- rval = build_cplus_new (type, init, 0);
- return rval;
- }
- }
-
- /* If TYPE or TREE_TYPE (EXPR) is not on the permanent_obstack,
- then the it won't be hashed and hence compare as not equal,
- even when it is. */
- if (code == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (expr)) == TREE_TYPE (type)
- && index_type_equal (TYPE_DOMAIN (TREE_TYPE (expr)), TYPE_DOMAIN (type)))
- return expr;
-
- error ("conversion to non-scalar type requested");
- return error_mark_node;
-}
-
-/* Like convert, except permit conversions to take place which
- are not normally allowed due to visibility restrictions
- (such as conversion from sub-type to private super-type). */
-tree
-convert_force (type, expr)
- tree type;
- tree expr;
-{
- register tree e = expr;
- register enum tree_code code = TREE_CODE (type);
-
- if (code == REFERENCE_TYPE)
- return fold (convert_to_reference (0, type, e,
- NULL_TREE, -1, (char *)NULL,
- -1, 0));
- else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
- e = convert_from_reference (e);
-
- if (code == POINTER_TYPE)
- return fold (convert_to_pointer_force (type, e));
-
- {
- int old_equiv = flag_int_enum_equivalence;
- flag_int_enum_equivalence = 1;
- e = convert (type, e);
- flag_int_enum_equivalence = old_equiv;
- }
- return e;
-}
-
-/* Subroutine of build_type_conversion. */
-static tree
-build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
- tree xtype, basetype;
- tree expr;
- tree typename;
- int for_sure;
-{
- tree first_arg = expr;
- tree rval;
- int flags;
-
- if (for_sure == 0)
- {
- if (! lvalue_p (expr))
- first_arg = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node);
- flags = LOOKUP_PROTECT;
- }
- else
- flags = LOOKUP_NORMAL;
-
- rval = build_method_call (first_arg, constructor_name (typename),
- NULL_TREE, NULL_TREE, flags);
- if (rval == error_mark_node)
- {
- if (for_sure == 0)
- return NULL_TREE;
- return error_mark_node;
- }
- if (first_arg != expr)
- {
- expr = build_up_reference (build_reference_type (TREE_TYPE (expr)), expr,
- LOOKUP_COMPLAIN, 1);
- TREE_VALUE (TREE_OPERAND (rval, 1)) = build_unary_op (ADDR_EXPR, expr, 0);
- }
- if (TREE_CODE (TREE_TYPE (rval)) == REFERENCE_TYPE
- && TREE_CODE (xtype) != REFERENCE_TYPE)
- rval = default_conversion (rval);
-
- if (pedantic
- && TREE_TYPE (xtype)
- && (TREE_READONLY (TREE_TYPE (TREE_TYPE (rval)))
- > TREE_READONLY (TREE_TYPE (xtype))))
- pedwarn ("user-defined conversion casting away `const'");
- return convert (xtype, rval);
-}
-
-/* Convert an aggregate EXPR to type XTYPE. If a conversion
- exists, return the attempted conversion. This may
- return ERROR_MARK_NODE if the conversion is not
- allowed (references private members, etc).
- If no conversion exists, NULL_TREE is returned.
-
- If (FOR_SURE & 1) is non-zero, then we allow this type conversion
- to take place immediately. Otherwise, we build a SAVE_EXPR
- which can be evaluated if the results are ever needed.
-
- If FOR_SURE >= 2, then we only look for exact conversions.
-
- TYPE may be a reference type, in which case we first look
- for something that will convert to a reference type. If
- that fails, we will try to look for something of the
- reference's target type, and then return a reference to that. */
-tree
-build_type_conversion (code, xtype, expr, for_sure)
- enum tree_code code;
- tree xtype, expr;
- int for_sure;
-{
- /* C++: check to see if we can convert this aggregate type
- into the required scalar type. */
- tree type, type_default;
- tree typename = build_typename_overload (xtype), *typenames;
- int n_variants = 0;
- tree basetype, save_basetype;
- tree rval;
- int exact_conversion = for_sure >= 2;
- for_sure &= 1;
-
- if (expr == error_mark_node)
- return error_mark_node;
-
- basetype = TREE_TYPE (expr);
- if (TREE_CODE (basetype) == REFERENCE_TYPE)
- basetype = TREE_TYPE (basetype);
-
- basetype = TYPE_MAIN_VARIANT (basetype);
- if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype))
- return 0;
-
- if (TREE_CODE (xtype) == POINTER_TYPE
- || TREE_CODE (xtype) == REFERENCE_TYPE)
- {
- /* Prepare to match a variant of this type. */
- type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype));
- for (n_variants = 0; type; type = TYPE_NEXT_VARIANT (type))
- n_variants++;
- typenames = (tree *)alloca (n_variants * sizeof (tree));
- for (n_variants = 0, type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype));
- type; n_variants++, type = TYPE_NEXT_VARIANT (type))
- {
- if (type == TREE_TYPE (xtype))
- typenames[n_variants] = typename;
- else if (TREE_CODE (xtype) == POINTER_TYPE)
- typenames[n_variants] = build_typename_overload (build_pointer_type (type));
- else
- typenames[n_variants] = build_typename_overload (build_reference_type (type));
- }
- }
-
- save_basetype = basetype;
- type = xtype;
-
- while (TYPE_HAS_CONVERSION (basetype))
- {
- int i;
- if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
- return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
- for (i = 0; i < n_variants; i++)
- if (typenames[i] != typename
- && lookup_fnfields (TYPE_BINFO (basetype), typenames[i], 0))
- return build_type_conversion_1 (xtype, basetype, expr, typenames[i], for_sure);
-
- if (TYPE_BINFO_BASETYPES (basetype))
- basetype = TYPE_BINFO_BASETYPE (basetype, 0);
- else break;
- }
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- tree first_arg = expr;
- type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- basetype = save_basetype;
-
- /* May need to build a temporary for this. */
- while (TYPE_HAS_CONVERSION (basetype))
- {
- if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
- {
- int flags;
-
- if (for_sure == 0)
- {
- if (! lvalue_p (expr))
- first_arg = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node);
- flags = LOOKUP_PROTECT;
- }
- else
- flags = LOOKUP_NORMAL;
- rval = build_method_call (first_arg, constructor_name (typename),
- NULL_TREE, NULL_TREE, flags);
- if (rval == error_mark_node)
- {
- if (for_sure == 0)
- return NULL_TREE;
- return error_mark_node;
- }
- TREE_VALUE (TREE_OPERAND (rval, 1)) = expr;
-
- if (IS_AGGR_TYPE (type))
- {
- tree init = build_method_call (NULL_TREE,
- constructor_name (type),
- build_tree_list (NULL_TREE, rval), NULL_TREE, LOOKUP_NORMAL);
- tree temp = build_cplus_new (type, init, 1);
- return build_up_reference (TYPE_REFERENCE_TO (type), temp,
- LOOKUP_COMPLAIN, 1);
- }
- return convert (xtype, rval);
- }
- if (TYPE_BINFO_BASETYPES (basetype))
- basetype = TYPE_BINFO_BASETYPE (basetype, 0);
- else break;
- }
- /* No free conversions for reference types, right?. */
- return NULL_TREE;
- }
-
- if (exact_conversion)
- return NULL_TREE;
-
- /* No perfect match found, try default. */
- if (code == CONVERT_EXPR && TREE_CODE (type) == POINTER_TYPE)
- type_default = ptr_type_node;
- else if (type == void_type_node)
- return NULL_TREE;
- else
- {
- tree tmp = default_conversion (build1 (NOP_EXPR, type, integer_zero_node));
- if (tmp == error_mark_node)
- return NULL_TREE;
- type_default = TREE_TYPE (tmp);
- }
-
- basetype = save_basetype;
-
- if (type_default != type)
- {
- type = type_default;
- typename = build_typename_overload (type);
-
- while (TYPE_HAS_CONVERSION (basetype))
- {
- if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
- return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
- if (TYPE_BINFO_BASETYPES (basetype))
- basetype = TYPE_BINFO_BASETYPE (basetype, 0);
- else break;
- }
- }
-
- try_pointer:
-
- if (type == ptr_type_node)
- {
- /* Try converting to some other pointer type
- with which void* is compatible, or in situations
- in which void* is appropriate (such as &&,||, and !). */
-
- while (TYPE_HAS_CONVERSION (basetype))
- {
- if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0)
- {
- if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node)
- return error_mark_node;
- typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv));
- return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
- }
- if (TYPE_BINFO_BASETYPES (basetype))
- basetype = TYPE_BINFO_BASETYPE (basetype, 0);
- else break;
- }
- }
- if (TREE_CODE (type) == POINTER_TYPE
- && TYPE_READONLY (TREE_TYPE (type))
- && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
- {
- /* Try converting to some other pointer type
- with which const void* is compatible. */
-
- while (TYPE_HAS_CONVERSION (basetype))
- {
- if (CLASSTYPE_CONVERSION (basetype, constptr_conv) != 0)
- {
- if (CLASSTYPE_CONVERSION (basetype, constptr_conv) == error_mark_node)
- return error_mark_node;
- typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, constptr_conv));
- return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
- }
- if (TYPE_BINFO_BASETYPES (basetype))
- basetype = TYPE_BINFO_BASETYPE (basetype, 0);
- else break;
- }
- }
- /* Use the longer or shorter conversion that is appropriate. Have
- to check against 0 because the conversion may come from a baseclass. */
- if (TREE_CODE (type) == INTEGER_TYPE
- && TYPE_HAS_INT_CONVERSION (basetype)
- && CLASSTYPE_CONVERSION (basetype, int_conv) != 0
- && CLASSTYPE_CONVERSION (basetype, int_conv) != error_mark_node)
- {
- typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, int_conv));
- return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
- }
- if (TREE_CODE (type) == REAL_TYPE
- && TYPE_HAS_REAL_CONVERSION (basetype)
- && CLASSTYPE_CONVERSION (basetype, real_conv) != 0
- && CLASSTYPE_CONVERSION (basetype, real_conv) != error_mark_node)
- {
- typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, real_conv));
- return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
- }
-
- /* THIS IS A KLUDGE. */
- if (TREE_CODE (type) != POINTER_TYPE
- && (code == TRUTH_ANDIF_EXPR
- || code == TRUTH_ORIF_EXPR
- || code == TRUTH_NOT_EXPR))
- {
- /* Here's when we can convert to a pointer. */
- type = ptr_type_node;
- goto try_pointer;
- }
-
- /* THESE ARE TOTAL KLUDGES. */
- /* Default promotion yields no new alternatives, try
- conversions which are anti-default, such as
-
- double -> float or int -> unsigned or unsigned -> long
-
- */
- if (type_default == type
- && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE))
- {
- int not_again = 0;
-
- if (type == double_type_node)
- typename = build_typename_overload (float_type_node);
- else if (type == integer_type_node)
- typename = build_typename_overload (unsigned_type_node);
- else if (type == unsigned_type_node)
- typename = build_typename_overload (long_integer_type_node);
-
- again:
- basetype = save_basetype;
- while (TYPE_HAS_CONVERSION (basetype))
- {
- if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
- return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
- if (TYPE_BINFO_BASETYPES (basetype))
- basetype = TYPE_BINFO_BASETYPE (basetype, 0);
- else break;
- }
- if (! not_again)
- {
- if (type == integer_type_node)
- {
- typename = build_typename_overload (long_integer_type_node);
- not_again = 1;
- goto again;
- }
- else
- {
- typename = build_typename_overload (integer_type_node);
- not_again = 1;
- goto again;
- }
- }
- }
-
- /* Now, try C promotions...
-
- float -> int
- int -> float, void *
- void * -> int
-
- Truthvalue conversions let us try to convert
- to pointer if we were going for int, and to int
- if we were looking for pointer. */
-
- basetype = save_basetype;
- if (TREE_CODE (type) == REAL_TYPE
- || (TREE_CODE (type) == POINTER_TYPE
- && (code == TRUTH_ANDIF_EXPR
- || code == TRUTH_ORIF_EXPR
- || code == TRUTH_NOT_EXPR)))
- type = integer_type_node;
- else if (TREE_CODE (type) == INTEGER_TYPE)
- if (TYPE_HAS_REAL_CONVERSION (basetype))
- type = double_type_node;
- else
- return NULL_TREE;
- else
- return NULL_TREE;
-
- typename = build_typename_overload (type);
- while (TYPE_HAS_CONVERSION (basetype))
- {
- if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
- {
- rval = build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
- return rval;
- }
- if (TYPE_BINFO_BASETYPES (basetype))
- basetype = TYPE_BINFO_BASETYPE (basetype, 0);
- else
- break;
- }
-
- return NULL_TREE;
-}
-
-/* Must convert two aggregate types to non-aggregate type.
- Attempts to find a non-ambiguous, "best" type conversion.
-
- Return 1 on success, 0 on failure.
-
- @@ What are the real semantics of this supposed to be??? */
-int
-build_default_binary_type_conversion (code, arg1, arg2)
- enum tree_code code;
- tree *arg1, *arg2;
-{
- tree type1 = TREE_TYPE (*arg1);
- tree type2 = TREE_TYPE (*arg2);
- char *name1, *name2;
-
- if (TREE_CODE (type1) == REFERENCE_TYPE)
- type1 = TREE_TYPE (type1);
- if (TREE_CODE (type2) == REFERENCE_TYPE)
- type2 = TREE_TYPE (type2);
-
- if (TREE_CODE (TYPE_NAME (type1)) != TYPE_DECL)
- {
- tree decl = typedecl_for_tag (type1);
- if (decl)
- error ("type conversion nonexistent for type `%s'",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- else
- error ("type conversion nonexistent for non-C++ type");
- return 0;
- }
- if (TREE_CODE (TYPE_NAME (type2)) != TYPE_DECL)
- {
- tree decl = typedecl_for_tag (type2);
- if (decl)
- error ("type conversion nonexistent for type `%s'",
- IDENTIFIER_POINTER (decl));
- else
- error ("type conversion nonexistent for non-C++ type");
- return 0;
- }
-
- name1 = TYPE_NAME_STRING (type1);
- name2 = TYPE_NAME_STRING (type2);
-
- if (!IS_AGGR_TYPE (type1) || !TYPE_HAS_CONVERSION (type1))
- {
- if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
- error ("type conversion required for binary operation on types `%s' and `%s'",
- name1, name2);
- else
- error ("type conversion required for type `%s'", name1);
- return 0;
- }
- else if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
- {
- error ("type conversion required for type `%s'", name2);
- return 0;
- }
-
- if (TYPE_HAS_INT_CONVERSION (type1) && TYPE_HAS_REAL_CONVERSION (type1))
- warning ("ambiguous type conversion for type `%s', defaulting to int", name1);
- if (TYPE_HAS_INT_CONVERSION (type1))
- {
- *arg1 = build_type_conversion (code, integer_type_node, *arg1, 1);
- *arg2 = build_type_conversion (code, integer_type_node, *arg2, 1);
- }
- else if (TYPE_HAS_REAL_CONVERSION (type1))
- {
- *arg1 = build_type_conversion (code, double_type_node, *arg1, 1);
- *arg2 = build_type_conversion (code, double_type_node, *arg2, 1);
- }
- else
- {
- *arg1 = build_type_conversion (code, ptr_type_node, *arg1, 1);
- if (*arg1 == error_mark_node)
- error ("ambiguous pointer conversion");
- *arg2 = build_type_conversion (code, ptr_type_node, *arg2, 1);
- if (*arg1 != error_mark_node && *arg2 == error_mark_node)
- error ("ambiguous pointer conversion");
- }
- if (*arg1 == 0)
- {
- if (*arg2 == 0 && type1 != type2)
- error ("default type conversion for types `%s' and `%s' failed",
- name1, name2);
- else
- error ("default type conversion for type `%s' failed", name1);
- return 0;
- }
- else if (*arg2 == 0)
- {
- error ("default type conversion for type `%s' failed", name2);
- return 0;
- }
- return 1;
-}
-
-/* Must convert two aggregate types to non-aggregate type.
- Attempts to find a non-ambiguous, "best" type conversion.
-
- Return 1 on success, 0 on failure.
-
- The type of the argument is expected to be of aggregate type here.
-
- @@ What are the real semantics of this supposed to be??? */
-int
-build_default_unary_type_conversion (code, arg)
- enum tree_code code;
- tree *arg;
-{
- tree type = TREE_TYPE (*arg);
- tree id = TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- ? TYPE_IDENTIFIER (type) : TYPE_NAME (type);
- char *name = IDENTIFIER_POINTER (id);
-
- if (! TYPE_HAS_CONVERSION (type))
- {
- error ("type conversion required for type `%s'", name);
- return 0;
- }
-
- if (TYPE_HAS_INT_CONVERSION (type) && TYPE_HAS_REAL_CONVERSION (type))
- warning ("ambiguous type conversion for type `%s', defaulting to int", name);
- if (TYPE_HAS_INT_CONVERSION (type))
- *arg = build_type_conversion (code, integer_type_node, *arg, 1);
- else if (TYPE_HAS_REAL_CONVERSION (type))
- *arg = build_type_conversion (code, double_type_node, *arg, 1);
- else
- {
- *arg = build_type_conversion (code, ptr_type_node, *arg, 1);
- if (*arg == error_mark_node)
- error ("ambiguous pointer conversion");
- }
- if (*arg == 0)
- {
- error ("default type conversion for type `%s' failed", name);
- return 0;
- }
- return 1;
-}
diff --git a/gnu/gcc2/cc1plus/cp-decl.c b/gnu/gcc2/cc1plus/cp-decl.c
deleted file mode 100644
index b888baa16b73..000000000000
--- a/gnu/gcc2/cc1plus/cp-decl.c
+++ /dev/null
@@ -1,11551 +0,0 @@
-/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-
-/* Process declarations and symbol lookup for C front end.
- Also constructs types; the standard scalar types at initialization,
- and structure, union, array and enum types when they are declared. */
-
-/* ??? not all decl nodes are given the most useful possible
- line numbers. For example, the CONST_DECLs for enum values. */
-
-#include <stdio.h>
-#include "config.h"
-#include "tree.h"
-#include "rtl.h"
-#include "flags.h"
-#include "cp-tree.h"
-#include "cp-decl.h"
-#include "cp-lex.h"
-#include <sys/types.h>
-#include <signal.h>
-#include "obstack.h"
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-extern struct obstack permanent_obstack;
-
-/* Stack of places to restore the search obstack back to. */
-
-/* Obstack used for remembering local class declarations (like
- enums and static (const) members. */
-#include "stack.h"
-static struct obstack decl_obstack;
-static struct stack_level *decl_stack;
-
-#undef NULL
-#define NULL (char *)0
-
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
-
-#ifndef SHORT_TYPE_SIZE
-#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2))
-#endif
-
-#ifndef INT_TYPE_SIZE
-#define INT_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef LONG_TYPE_SIZE
-#define LONG_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef LONG_LONG_TYPE_SIZE
-#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-#ifndef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-#endif
-
-#ifndef FLOAT_TYPE_SIZE
-#define FLOAT_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef DOUBLE_TYPE_SIZE
-#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-#ifndef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-/* We let tm.h override the types used here, to handle trivial differences
- such as the choice of unsigned int or long unsigned int for size_t.
- When machines start needing nontrivial differences in the size type,
- it would be best to do something here to figure out automatically
- from other information what type to use. */
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-#endif
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-#endif
-
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#endif
-
-#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
- define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME)
-#define auto_function(NAME, TYPE, CODE) \
- do { \
- tree __name = NAME; \
- tree __type = TYPE; \
- define_function (IDENTIFIER_POINTER (__name), __type, CODE, \
- (void (*)())push_overloaded_decl_1, \
- IDENTIFIER_POINTER (build_decl_overload (__name, TYPE_ARG_TYPES (__type), 0)));\
- } while (0)
-
-static tree grokparms PROTO((tree, int));
-static tree lookup_nested_type PROTO((tree, tree));
-static char *redeclaration_error_message PROTO((tree, tree));
-static int parmlist_is_random PROTO((tree));
-static void grok_op_properties PROTO((tree, int));
-static void expand_static_init PROTO((tree, tree));
-static void deactivate_exception_cleanups PROTO((void));
-
-tree define_function PROTO((char *, tree, enum built_in_function, void (*)(), char *));
-
-/* a node which has tree code ERROR_MARK, and whose type is itself.
- All erroneous expressions are replaced with this node. All functions
- that accept nodes as arguments should avoid generating error messages
- if this node is one of the arguments, since it is undesirable to get
- multiple error messages from one error in the input. */
-
-tree error_mark_node;
-
-/* Erroneous argument lists can use this *IFF* they do not modify it. */
-tree error_mark_list;
-
-/* INTEGER_TYPE and REAL_TYPE nodes for the standard data types */
-
-tree short_integer_type_node;
-tree integer_type_node;
-tree long_integer_type_node;
-tree long_long_integer_type_node;
-
-tree short_unsigned_type_node;
-tree unsigned_type_node;
-tree long_unsigned_type_node;
-tree long_long_unsigned_type_node;
-
-tree ptrdiff_type_node;
-
-tree unsigned_char_type_node;
-tree signed_char_type_node;
-tree char_type_node;
-tree wchar_type_node;
-tree signed_wchar_type_node;
-tree unsigned_wchar_type_node;
-
-tree float_type_node;
-tree double_type_node;
-tree long_double_type_node;
-
-tree intQI_type_node;
-tree intHI_type_node;
-tree intSI_type_node;
-tree intDI_type_node;
-
-tree unsigned_intQI_type_node;
-tree unsigned_intHI_type_node;
-tree unsigned_intSI_type_node;
-tree unsigned_intDI_type_node;
-
-/* a VOID_TYPE node, and the same, packaged in a TREE_LIST. */
-
-tree void_type_node, void_list_node;
-tree void_zero_node;
-
-/* Nodes for types `void *' and `const void *'. */
-
-tree ptr_type_node, const_ptr_type_node;
-
-/* Nodes for types `char *' and `const char *'. */
-
-tree string_type_node, const_string_type_node;
-
-/* Type `char[256]' or something like it.
- Used when an array of char is needed and the size is irrelevant. */
-
-tree char_array_type_node;
-
-/* Type `int[256]' or something like it.
- Used when an array of int needed and the size is irrelevant. */
-
-tree int_array_type_node;
-
-/* Type `wchar_t[256]' or something like it.
- Used when a wide string literal is created. */
-
-tree wchar_array_type_node;
-
-/* type `int ()' -- used for implicit declaration of functions. */
-
-tree default_function_type;
-
-/* function types `double (double)' and `double (double, double)', etc. */
-
-tree double_ftype_double, double_ftype_double_double;
-tree int_ftype_int, long_ftype_long;
-
-/* Function type `void (void *, void *, int)' and similar ones. */
-
-tree void_ftype_ptr_ptr_int, int_ftype_ptr_ptr_int, void_ftype_ptr_int_int;
-
-/* Function type `char *(char *, char *)' and similar ones */
-tree string_ftype_ptr_ptr, int_ftype_string_string;
-
-/* Function type `size_t (const char *)' */
-tree sizet_ftype_string;
-
-/* Function type `int (const void *, const void *, size_t)' */
-tree int_ftype_cptr_cptr_sizet;
-
-/* C++ extensions */
-tree vtable_entry_type;
-tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node;
-tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type;
-tree class_star_type_node;
-tree class_type_node, record_type_node, union_type_node, enum_type_node;
-tree exception_type_node, unknown_type_node;
-tree maybe_gc_cleanup;
-
-/* Used for virtual function tables. */
-tree vtbl_mask;
-
-/* Array type `(void *)[]' */
-tree vtbl_type_node;
-
-/* Static decls which do not have static initializers have no
- initializers as far as GNU C is concerned. EMPTY_INIT_NODE
- is a static initializer which makes varasm code place the decl
- in data rather than in bss space. Such gymnastics are necessary
- to avoid the problem that the linker will not include a library
- file if all the library appears to contribute are bss variables. */
-
-tree empty_init_node;
-
-/* In a destructor, the point at which all derived class destroying
- has been done, just before any base class destroying will be done. */
-
-tree dtor_label;
-
-/* In a constructor, the point at which we are ready to return
- the pointer to the initialized object. */
-
-tree ctor_label;
-
-/* A FUNCTION_DECL which can call `unhandled_exception'.
- Not necessarily the one that the user will declare,
- but sufficient to be called by routines that want to abort the program. */
-
-tree unhandled_exception_fndecl;
-
-/* A FUNCTION_DECL which can call `abort'. Not necessarily the
- one that the user will declare, but sufficient to be called
- by routines that want to abort the program. */
-
-tree abort_fndecl;
-
-extern rtx cleanup_label, return_label;
-
-/* If original DECL_RESULT of current function was a register,
- but due to being an addressable named return value, would up
- on the stack, this variable holds the named return value's
- original location. */
-rtx original_result_rtx;
-
-/* Sequence of insns which represents base initialization. */
-rtx base_init_insns;
-
-/* C++: Keep these around to reduce calls to `get_identifier'.
- Identifiers for `this' in member functions and the auto-delete
- parameter for destructors. */
-tree this_identifier, in_charge_identifier;
-
-/* A list (chain of TREE_LIST nodes) of named label uses.
- The TREE_PURPOSE field is the list of variables defined
- the the label's scope defined at the point of use.
- The TREE_VALUE field is the LABEL_DECL used.
- The TREE_TYPE field holds `current_binding_level' at the
- point of the label's use.
-
- Used only for jumps to as-yet undefined labels, since
- jumps to defined labels can have their validity checked
- by stmt.c. */
-
-static tree named_label_uses;
-
-/* A list of objects which have constructors or destructors
- which reside in the global scope. The decl is stored in
- the TREE_VALUE slot and the initializer is stored
- in the TREE_PURPOSE slot. */
-tree static_aggregates;
-
-/* A list of functions which were declared inline, but later had their
- address taken. Used only for non-virtual member functions, since we can
- find other functions easily enough. */
-tree pending_addressable_inlines;
-
-/* A list of overloaded functions which we should forget ever
- existed, such as functions declared in a function's scope,
- once we leave that function's scope. */
-static tree overloads_to_forget;
-
-/* -- end of C++ */
-
-/* Two expressions that are constants with value zero.
- The first is of type `int', the second of type `void *'. */
-
-tree integer_zero_node;
-tree null_pointer_node;
-
-/* A node for the integer constants 1, 2, and 3. */
-
-tree integer_one_node, integer_two_node, integer_three_node;
-
-/* Nonzero if we have seen an invalid cross reference
- to a struct, union, or enum, but not yet printed the message. */
-
-tree pending_invalid_xref;
-/* File and line to appear in the eventual error message. */
-char *pending_invalid_xref_file;
-int pending_invalid_xref_line;
-
-/* While defining an enum type, this is 1 plus the last enumerator
- constant value. */
-
-static tree enum_next_value;
-
-/* Parsing a function declarator leaves a list of parameter names
- or a chain or parameter decls here. */
-
-tree last_function_parms;
-
-/* Parsing a function declarator leaves here a chain of structure
- and enum types declared in the parmlist. */
-
-static tree last_function_parm_tags;
-
-/* After parsing the declarator that starts a function definition,
- `start_function' puts here the list of parameter names or chain of decls.
- `store_parm_decls' finds it here. */
-
-static tree current_function_parms;
-
-/* Similar, for last_function_parm_tags. */
-static tree current_function_parm_tags;
-
-/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
- that have names. Here so we can clear out their names' definitions
- at the end of the function. */
-
-static tree named_labels;
-
-/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
-
-static tree shadowed_labels;
-
-#if 0 /* Not needed by C++ */
-/* Nonzero when store_parm_decls is called indicates a varargs function.
- Value not meaningful after store_parm_decls. */
-
-static int c_function_varargs;
-#endif
-
-/* The FUNCTION_DECL for the function currently being compiled,
- or 0 if between functions. */
-tree current_function_decl;
-
-/* Set to 0 at beginning of a function definition, set to 1 if
- a return statement that specifies a return value is seen. */
-
-int current_function_returns_value;
-
-/* Set to 0 at beginning of a function definition, set to 1 if
- a return statement with no argument is seen. */
-
-int current_function_returns_null;
-
-/* Set to 0 at beginning of a function definition, and whenever
- a label (case or named) is defined. Set to value of expression
- returned from function when that value can be transformed into
- a named return value. */
-
-tree current_function_return_value;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-extern int warn_redundant_decls;
-
-/* Set to nonzero by `grokdeclarator' for a function
- whose return type is defaulted, if warnings for this are desired. */
-
-static int warn_about_return_type;
-
-/* Nonzero when starting a function declared `extern inline'. */
-
-static int current_extern_inline;
-
-/* Nonzero means give `double' the same size as `float'. */
-
-extern int flag_short_double;
-
-/* Nonzero means don't recognize any builtin functions. */
-
-extern int flag_no_builtin;
-
-/* Nonzero means do emit exported implementations of functions even if
- they can be inlined. */
-
-extern int flag_implement_inlines;
-
-/* Nonzero means handle things in ANSI, instead of GNU fashion. This
- flag should be tested for language behavior that's different between
- ANSI and GNU, but not so horrible as to merit a PEDANTIC label. */
-
-extern int flag_ansi;
-
-/* Pointers to the base and current top of the language name stack. */
-
-extern tree *current_lang_base, *current_lang_stack;
-
-/* C and C++ flags are in cp-decl2.c. */
-
-/* Set to 0 at beginning of a constructor, set to 1
- if that function does an allocation before referencing its
- instance variable. */
-int current_function_assigns_this;
-int current_function_just_assigned_this;
-
-/* Set to 0 at beginning of a function. Set non-zero when
- store_parm_decls is called. Don't call store_parm_decls
- if this flag is non-zero! */
-int current_function_parms_stored;
-
-/* Current end of entries in the gc obstack for stack pointer variables. */
-
-int current_function_obstack_index;
-
-/* Flag saying whether we have used the obstack in this function or not. */
-
-int current_function_obstack_usage;
-
-/* Flag used when debugging cp-spew.c */
-
-extern int spew_debug;
-
-/* Allocate a level of searching. */
-struct stack_level *
-push_decl_level (stack, obstack)
- struct stack_level *stack;
- struct obstack *obstack;
-{
- struct stack_level tem;
- tem.prev = stack;
-
- return push_stack_level (obstack, (char *)&tem, sizeof (tem));
-}
-
-/* Discard a level of decl allocation. */
-
-static struct stack_level *
-pop_decl_level (stack)
- struct stack_level *stack;
-{
- tree *bp, *tp;
- struct obstack *obstack = stack->obstack;
- bp = stack->first;
- tp = (tree *)obstack_next_free (obstack);
- while (tp != bp)
- {
- --tp;
- if (*tp != NULL_TREE)
- IDENTIFIER_CLASS_VALUE (DECL_NAME (*tp)) = NULL_TREE;
- }
- return pop_stack_level (stack);
-}
-
-/* For each binding contour we allocate a binding_level structure
- * which records the names defined in that contour.
- * Contours include:
- * 0) the global one
- * 1) one for each function definition,
- * where internal declarations of the parameters appear.
- * 2) one for each compound statement,
- * to record its declarations.
- *
- * The current meaning of a name can be found by searching the levels from
- * the current one out to the global one.
- *
- * Off to the side, may be the class_binding_level. This exists
- * only to catch class-local declarations. It is otherwise
- * nonexistent.
- *
- * Also there may be binding levels that catch cleanups that
- * must be run when exceptions occur.
- */
-
-/* Note that the information in the `names' component of the global contour
- is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
-
-struct binding_level
- {
- /* A chain of _DECL nodes for all variables, constants, functions,
- * and typedef types. These are in the reverse of the order supplied.
- */
- tree names;
-
- /* A list of structure, union and enum definitions,
- * for looking up tag names.
- * It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
- * or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
- * or ENUMERAL_TYPE node.
- *
- * C++: the TREE_VALUE nodes can be simple types for component_bindings.
- *
- */
- tree tags;
-
- /* For each level, a list of shadowed outer-level local definitions
- to be restored when this level is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
- tree shadowed;
-
- /* Same, for IDENTIFIER_CLASS_VALUE. */
- tree class_shadowed;
-
- /* Same, for IDENTIFIER_TYPE_VALUE. */
- tree type_shadowed;
-
- /* For each level (except not the global one),
- a chain of BLOCK nodes for all the levels
- that were entered and exited one level down. */
- tree blocks;
-
- /* The BLOCK node for this level, if one has been preallocated.
- If 0, the BLOCK is allocated (if needed) when the level is popped. */
- tree this_block;
-
- /* The binding level which this one is contained in (inherits from). */
- struct binding_level *level_chain;
-
- /* Number of decls in `names' that have incomplete
- structure or union types. */
- unsigned short n_incomplete;
-
- /* 1 for the level that holds the parameters of a function.
- 2 for the level that holds a class declaration.
- 3 for levels that hold parameter declarations. */
- unsigned parm_flag : 4;
-
- /* 1 means make a BLOCK for this level regardless of all else.
- 2 for temporary binding contours created by the compiler. */
- unsigned keep : 3;
-
- /* Nonzero if this level "doesn't exist" for tags. */
- unsigned tag_transparent : 1;
-
- /* Nonzero if this level can safely have additional
- cleanup-needing variables added to it. */
- unsigned more_cleanups_ok : 1;
- unsigned have_cleanups : 1;
-
- /* Nonzero if this level can safely have additional
- exception-raising statements added to it. */
- unsigned more_exceptions_ok : 1;
- unsigned have_exceptions : 1;
-
- /* Nonzero if we should accept any name as an identifier in
- this scope. This happens in some template definitions. */
- unsigned accept_any : 1;
-
- /* Nonzero if this level is for completing a template class definition
- inside a binding level that temporarily binds the parameters. This
- means that definitions here should not be popped off when unwinding
- this binding level. (Not actually implemented this way,
- unfortunately.) */
- unsigned pseudo_global : 1;
-
- /* Two bits left for this word. */
-
-#if PARANOID
- unsigned char depth;
-#endif
- };
-
-#define NULL_BINDING_LEVEL (struct binding_level *) NULL
-
-/* The binding level currently in effect. */
-
-static struct binding_level *current_binding_level;
-
-/* The binding level of the current class, if any. */
-
-static struct binding_level *class_binding_level;
-
-/* A chain of binding_level structures awaiting reuse. */
-
-static struct binding_level *free_binding_level;
-
-/* The outermost binding level, for names of file scope.
- This is created when the compiler is started and exists
- through the entire run. */
-
-static struct binding_level *global_binding_level;
-
-/* Binding level structures are initialized by copying this one. */
-
-static struct binding_level clear_binding_level;
-
-/* Nonzero means unconditionally make a BLOCK for the next level pushed. */
-
-static int keep_next_level_flag;
-
-#if PARANOID
-/* Perform sanity checking on binding levels. Normally not needed. */
-void
-binding_levels_sane ()
-{
- struct binding_level *b = current_binding_level;
- static int n;
- if (++n < 3)
- return;
- my_friendly_assert (global_binding_level != 0, 126);
- my_friendly_assert (current_binding_level != 0, 127);
- for (b = current_binding_level; b != global_binding_level; b = b->level_chain)
- {
- my_friendly_assert (b->level_chain != 0, 128);
- my_friendly_assert (b->depth == 1 + b->level_chain->depth, 129);
- }
- if (class_binding_level)
- for (b = class_binding_level;
- b != global_binding_level && b != current_binding_level;
- b = b->level_chain)
- {
- my_friendly_assert (b->level_chain != 0, 130);
- my_friendly_assert (b->depth == 1 + b->level_chain->depth, 131);
- }
- my_friendly_assert (global_binding_level->depth == 0, 132);
- my_friendly_assert (global_binding_level->level_chain == 0, 133);
- return;
-}
-
-#else
-#define binding_levels_sane() ((void)(1))
-#endif
-
-#ifdef DEBUG_CP_BINDING_LEVELS
-int debug_bindings_indentation;
-#endif
-
-static void
-#if !PARANOID && defined (__GNUC__)
-__inline
-#endif
-push_binding_level (newlevel, tag_transparent, keep)
- struct binding_level *newlevel;
- int tag_transparent, keep;
-{
- binding_levels_sane();
- /* Add this level to the front of the chain (stack) of levels that
- are active. */
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "pushing binding level ");
- fprintf (stderr, HOST_PTR_PRINTF, newlevel);
- fprintf (stderr, "\n");
-#endif
- *newlevel = clear_binding_level;
- if (class_binding_level)
- {
- newlevel->level_chain = class_binding_level;
- class_binding_level = (struct binding_level *)0;
- }
- else
- {
- newlevel->level_chain = current_binding_level;
- }
- current_binding_level = newlevel;
- newlevel->tag_transparent = tag_transparent;
- newlevel->more_cleanups_ok = 1;
- newlevel->more_exceptions_ok = 1;
- newlevel->keep = keep;
-#if PARANOID
- newlevel->depth = (newlevel->level_chain
- ? newlevel->level_chain->depth + 1
- : 0);
-#endif
- binding_levels_sane();
-}
-
-static void
-#if !PARANOID && defined (__GNUC__)
-__inline
-#endif
-pop_binding_level ()
-{
- binding_levels_sane();
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "popping binding level ");
- fprintf (stderr, HOST_PTR_PRINTF, current_binding_level);
- fprintf (stderr, "\n");
-#endif
- if (global_binding_level)
- {
- /* cannot pop a level, if there are none left to pop. */
- if (current_binding_level == global_binding_level)
- my_friendly_abort (123);
- }
- /* Pop the current level, and free the structure for reuse. */
- {
- register struct binding_level *level = current_binding_level;
- current_binding_level = current_binding_level->level_chain;
- level->level_chain = free_binding_level;
-#ifdef DEBUG_CP_BINDING_LEVELS
- memset (level, 0x69, sizeof (*level));
-#else
- free_binding_level = level;
-#if PARANOID
- level->depth = ~0; /* ~0 assumes that the depth is unsigned. */
-#endif
-#endif
- if (current_binding_level->parm_flag == 2)
- {
- class_binding_level = current_binding_level;
- do
- {
- current_binding_level = current_binding_level->level_chain;
- }
- while (current_binding_level->parm_flag == 2);
- }
- }
- binding_levels_sane();
-}
-
-/* Nonzero if we are currently in the global binding level. */
-
-int
-global_bindings_p ()
-{
- return current_binding_level == global_binding_level;
-}
-
-void
-keep_next_level ()
-{
- keep_next_level_flag = 1;
-}
-
-/* Nonzero if the current level needs to have a BLOCK made. */
-
-int
-kept_level_p ()
-{
- return (current_binding_level->blocks != NULL_TREE
- || current_binding_level->keep
- || current_binding_level->names != NULL_TREE
- || (current_binding_level->tags != NULL_TREE
- && !current_binding_level->tag_transparent));
-}
-
-/* Identify this binding level as a level of parameters. */
-
-void
-declare_parm_level ()
-{
- current_binding_level->parm_flag = 1;
-}
-
-/* Identify this binding level as a level of a default exception handler. */
-
-void
-declare_implicit_exception ()
-{
- current_binding_level->parm_flag = 3;
-}
-
-/* Nonzero if current binding contour contains expressions
- that might raise exceptions. */
-
-int
-have_exceptions_p ()
-{
- return current_binding_level->have_exceptions;
-}
-
-void
-declare_uninstantiated_type_level ()
-{
- current_binding_level->accept_any = 1;
-}
-
-int
-uninstantiated_type_level_p ()
-{
- return current_binding_level->accept_any;
-}
-
-void
-declare_pseudo_global_level ()
-{
- current_binding_level->pseudo_global = 1;
-}
-
-int
-pseudo_global_level_p ()
-{
- return current_binding_level->pseudo_global;
-}
-
-/* Enter a new binding level.
- If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
- not for that of tags. */
-
-void
-pushlevel (tag_transparent)
- int tag_transparent;
-{
- register struct binding_level *newlevel = NULL_BINDING_LEVEL;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "pushlevel");
- debug_bindings_indentation += 4;
-#endif
-
- /* If this is the top level of a function,
- just make sure that NAMED_LABELS is 0.
- They should have been set to 0 at the end of the previous function. */
-
- if (current_binding_level == global_binding_level)
- my_friendly_assert (named_labels == NULL_TREE, 134);
-
- /* Reuse or create a struct for this binding level. */
-
- if (free_binding_level)
- {
- newlevel = free_binding_level;
- free_binding_level = free_binding_level->level_chain;
- }
- else
- {
- /* Create a new `struct binding_level'. */
- newlevel = (struct binding_level *) xmalloc (sizeof (struct binding_level));
- }
- push_binding_level (newlevel, tag_transparent, keep_next_level_flag);
- GNU_xref_start_scope ((int) newlevel);
- keep_next_level_flag = 0;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-void
-pushlevel_temporary (tag_transparent)
- int tag_transparent;
-{
- pushlevel (tag_transparent);
- current_binding_level->keep = 2;
- clear_last_expr ();
-
- /* Note we don't call push_momentary() here. Otherwise, it would cause
- cleanups to be allocated on the momentary obstack, and they will be
- overwritten by the next statement. */
-
- expand_start_bindings (0);
-}
-
-/* Exit a binding level.
- Pop the level off, and restore the state of the identifier-decl mappings
- that were in effect when this level was entered.
-
- If KEEP == 1, this level had explicit declarations, so
- and create a "block" (a BLOCK node) for the level
- to record its declarations and subblocks for symbol table output.
-
- If KEEP == 2, this level's subblocks go to the front,
- not the back of the current binding level. This happens,
- for instance, when code for constructors and destructors
- need to generate code at the end of a function which must
- be moved up to the front of the function.
-
- If FUNCTIONBODY is nonzero, this level is the body of a function,
- so create a block as if KEEP were set and also clear out all
- label names.
-
- If REVERSE is nonzero, reverse the order of decls before putting
- them into the BLOCK. */
-
-tree
-poplevel (keep, reverse, functionbody)
- int keep;
- int reverse;
- int functionbody;
-{
- register tree link;
- /* The chain of decls was accumulated in reverse order.
- Put it into forward order, just for cleanliness. */
- tree decls;
- int tmp = functionbody;
- int implicit_try_block = current_binding_level->parm_flag == 3;
- int real_functionbody = current_binding_level->keep == 2
- ? ((functionbody = 0), tmp) : functionbody;
- tree tags = functionbody >= 0 ? current_binding_level->tags : 0;
- tree subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
- tree block = NULL_TREE;
- tree decl;
- int block_previously_created;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "poplevel");
- debug_bindings_indentation += 4;
-#endif
-
- binding_levels_sane();
- GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
- (HOST_WIDE_INT) current_binding_level->level_chain,
- current_binding_level->parm_flag,
- current_binding_level->keep,
- current_binding_level->tag_transparent);
-
- if (current_binding_level->keep == 1)
- keep = 1;
-
- /* This warning is turned off because it causes warnings for
- declarations like `extern struct foo *x'. */
-#if 0
- /* Warn about incomplete structure types in this level. */
- for (link = tags; link; link = TREE_CHAIN (link))
- if (TYPE_SIZE (TREE_VALUE (link)) == NULL_TREE)
- {
- tree type = TREE_VALUE (link);
- char *errmsg;
- switch (TREE_CODE (type))
- {
- case RECORD_TYPE:
- errmsg = "`struct %s' incomplete in scope ending here";
- break;
- case UNION_TYPE:
- errmsg = "`union %s' incomplete in scope ending here";
- break;
- case ENUMERAL_TYPE:
- errmsg = "`enum %s' incomplete in scope ending here";
- break;
- }
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type)));
- else
- /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */
- error (errmsg, TYPE_NAME_STRING (type));
- }
-#endif /* 0 */
-
- /* Get the decls in the order they were written.
- Usually current_binding_level->names is in reverse order.
- But parameter decls were previously put in forward order. */
-
- if (reverse)
- current_binding_level->names
- = decls = nreverse (current_binding_level->names);
- else
- decls = current_binding_level->names;
-
- /* Output any nested inline functions within this block
- if they weren't already output. */
-
- for (decl = decls; decl; decl = TREE_CHAIN (decl))
- if (TREE_CODE (decl) == FUNCTION_DECL
- && ! TREE_ASM_WRITTEN (decl)
- && DECL_INITIAL (decl) != NULL_TREE
- && TREE_ADDRESSABLE (decl))
- {
- /* If this decl was copied from a file-scope decl
- on account of a block-scope extern decl,
- propagate TREE_ADDRESSABLE to the file-scope decl. */
- if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE)
- TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
- else
- output_inline_function (decl);
- }
-
- /* If there were any declarations or structure tags in that level,
- or if this level is a function body,
- create a BLOCK to record them for the life of this function. */
-
- block = NULL_TREE;
- block_previously_created = (current_binding_level->this_block != NULL_TREE);
- if (block_previously_created)
- block = current_binding_level->this_block;
- else if (keep == 1 || functionbody)
- block = make_node (BLOCK);
- if (block != NULL_TREE)
- {
- BLOCK_VARS (block) = decls;
- BLOCK_TYPE_TAGS (block) = tags;
- BLOCK_SUBBLOCKS (block) = subblocks;
- remember_end_note (block);
- }
-
- /* In each subblock, record that this is its superior. */
-
- if (keep >= 0)
- for (link = subblocks; link; link = TREE_CHAIN (link))
- BLOCK_SUPERCONTEXT (link) = block;
-
- /* Clear out the meanings of the local variables of this level. */
-
- for (link = decls; link; link = TREE_CHAIN (link))
- {
- if (DECL_NAME (link) != NULL_TREE)
- {
- /* If the ident. was used or addressed via a local extern decl,
- don't forget that fact. */
- if (DECL_EXTERNAL (link))
- {
- if (TREE_USED (link))
- TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1;
- if (TREE_ADDRESSABLE (link))
- TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
- }
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
- }
- }
-
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-
- /* If the level being exited is the top level of a function,
- check over all the labels. */
-
- if (functionbody)
- {
- /* If this is the top level block of a function,
- the vars are the function's parameters.
- Don't leave them in the BLOCK because they are
- found in the FUNCTION_DECL instead. */
-
- BLOCK_VARS (block) = 0;
-
- /* Clear out the definitions of all label names,
- since their scopes end here. */
-
- for (link = named_labels; link; link = TREE_CHAIN (link))
- {
- register tree label = TREE_VALUE (link);
-
- if (DECL_INITIAL (label) == NULL_TREE)
- {
- error_with_decl (label, "label `%s' used but not defined");
- /* Avoid crashing later. */
- define_label (input_filename, 1, DECL_NAME (label));
- }
- else if (warn_unused && !TREE_USED (label))
- warning_with_decl (label,
- "label `%s' defined but not used");
- SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), 0);
-
- /* Put the labels into the "variables" of the
- top-level block, so debugger can see them. */
- TREE_CHAIN (label) = BLOCK_VARS (block);
- BLOCK_VARS (block) = label;
- }
-
- named_labels = NULL_TREE;
- }
-
- /* Any uses of undefined labels now operate under constraints
- of next binding contour. */
- {
- struct binding_level *level_chain;
- level_chain = current_binding_level->level_chain;
- if (level_chain)
- {
- tree labels;
- for (labels = named_label_uses; labels; labels = TREE_CHAIN (labels))
- if (TREE_TYPE (labels) == (tree)current_binding_level)
- {
- TREE_TYPE (labels) = (tree)level_chain;
- TREE_PURPOSE (labels) = level_chain->names;
- }
- }
- }
-
- tmp = current_binding_level->keep;
-
- pop_binding_level ();
- if (functionbody)
- DECL_INITIAL (current_function_decl) = block;
- else if (block)
- {
- if (!block_previously_created)
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
- }
-
- /* If we did not make a block for the level just exited,
- any blocks made for inner levels
- (since they cannot be recorded as subblocks in that level)
- must be carried forward so they will later become subblocks
- of something else. */
- else if (subblocks)
- if (keep == 2)
- current_binding_level->blocks = chainon (subblocks, current_binding_level->blocks);
- else
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, subblocks);
-
- /* Take care of compiler's internal binding structures. */
- if (tmp == 2 && !implicit_try_block)
- {
-#if 0
- /* We did not call push_momentary for this
- binding contour, so there is nothing to pop. */
- pop_momentary ();
-#endif
- expand_end_bindings (getdecls (), keep, 1);
- block = poplevel (keep, reverse, real_functionbody);
- }
- if (block)
- TREE_USED (block) = 1;
- binding_levels_sane();
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
- return block;
-}
-
-/* Delete the node BLOCK from the current binding level.
- This is used for the block inside a stmt expr ({...})
- so that the block can be reinserted where appropriate. */
-
-void
-delete_block (block)
- tree block;
-{
- tree t;
- if (current_binding_level->blocks == block)
- current_binding_level->blocks = TREE_CHAIN (block);
- for (t = current_binding_level->blocks; t;)
- {
- if (TREE_CHAIN (t) == block)
- TREE_CHAIN (t) = TREE_CHAIN (block);
- else
- t = TREE_CHAIN (t);
- }
- TREE_CHAIN (block) = NULL_TREE;
- /* Clear TREE_USED which is always set by poplevel.
- The flag is set again if insert_block is called. */
- TREE_USED (block) = 0;
-}
-
-/* Insert BLOCK at the end of the list of subblocks of the
- current binding level. This is used when a BIND_EXPR is expanded,
- to handle the BLOCK node inside the BIND_EXPR. */
-
-void
-insert_block (block)
- tree block;
-{
- TREE_USED (block) = 1;
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
-}
-
-/* Add BLOCK to the current list of blocks for this binding contour. */
-void
-add_block_current_level (block)
- tree block;
-{
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
-}
-
-/* Set the BLOCK node for the innermost scope
- (the one we are currently in). */
-
-void
-set_block (block)
- register tree block;
-{
- current_binding_level->this_block = block;
-}
-
-/* Do a pushlevel for class declarations. */
-void
-pushlevel_class ()
-{
- binding_levels_sane();
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "pushlevel_class");
- debug_bindings_indentation += 4;
-#endif
- pushlevel (0);
- decl_stack = push_decl_level (decl_stack, &decl_obstack);
- class_binding_level = current_binding_level;
- class_binding_level->parm_flag = 2;
- do
- {
- current_binding_level = current_binding_level->level_chain;
- }
- while (current_binding_level->parm_flag == 2);
- binding_levels_sane();
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-/* ...and a poplevel for class declarations. */
-tree
-poplevel_class ()
-{
- register struct binding_level *level = class_binding_level;
- tree block = NULL_TREE;
- tree shadowed;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "poplevel_class");
- debug_bindings_indentation += 4;
-#endif
- binding_levels_sane();
- if (level == (struct binding_level *)0)
- {
- while (current_binding_level && class_binding_level == (struct binding_level *)0)
- block = poplevel (0, 0, 0);
- if (current_binding_level == (struct binding_level *)0)
- fatal ("syntax error too serious");
- level = class_binding_level;
- }
- decl_stack = pop_decl_level (decl_stack);
- for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
- for (shadowed = level->class_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
- for (shadowed = level->type_shadowed; shadowed; shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
-
- GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
- (HOST_WIDE_INT) class_binding_level->level_chain,
- class_binding_level->parm_flag,
- class_binding_level->keep,
- class_binding_level->tag_transparent);
-
- class_binding_level = level->level_chain;
- if (class_binding_level->parm_flag != 2)
- class_binding_level = (struct binding_level *)0;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "popping class binding level ");
- fprintf (stderr, HOST_PTR_PRINTF, level);
- fprintf (stderr, "\n");
- memset (level, 0x69, sizeof (*level));
- debug_bindings_indentation -= 4;
-#else
- level->level_chain = free_binding_level;
- free_binding_level = level;
-#endif
- binding_levels_sane();
-
- return block;
-}
-
-/* For debugging. */
-int no_print_functions = 0;
-int no_print_builtins = 0;
-
-void
-print_binding_level (lvl)
- struct binding_level *lvl;
-{
- tree t;
- int i = 0, len;
- fprintf (stderr, " blocks=");
- fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
- fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d",
- lvl->n_incomplete, lvl->parm_flag, lvl->keep);
- if (lvl->tag_transparent)
- fprintf (stderr, " tag-transparent");
- if (lvl->more_cleanups_ok)
- fprintf (stderr, " more-cleanups-ok");
- if (lvl->have_cleanups)
- fprintf (stderr, " have-cleanups");
- if (lvl->more_exceptions_ok)
- fprintf (stderr, " more-exceptions-ok");
- if (lvl->have_exceptions)
- fprintf (stderr, " have-exceptions");
- fprintf (stderr, "\n");
- if (lvl->names)
- {
- fprintf (stderr, " names:\t");
- /* We can probably fit 3 names to a line? */
- for (t = lvl->names; t; t = TREE_CHAIN (t))
- {
- if (no_print_functions && (TREE_CODE(t) == FUNCTION_DECL))
- continue;
- if (no_print_builtins
- && (TREE_CODE(t) == TYPE_DECL)
- && (!strcmp(DECL_SOURCE_FILE(t),"<built-in>")))
- continue;
-
- /* Function decls tend to have longer names. */
- if (TREE_CODE (t) == FUNCTION_DECL)
- len = 3;
- else
- len = 2;
- i += len;
- if (i > 6)
- {
- fprintf (stderr, "\n\t");
- i = len;
- }
- print_node_brief (stderr, "", t, 0);
- if (TREE_CODE (t) == ERROR_MARK)
- break;
- }
- if (i)
- fprintf (stderr, "\n");
- }
- if (lvl->tags)
- {
- fprintf (stderr, " tags:\t");
- i = 0;
- for (t = lvl->tags; t; t = TREE_CHAIN (t))
- {
- if (TREE_PURPOSE (t) == NULL_TREE)
- len = 3;
- else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
- len = 2;
- else
- len = 4;
- i += len;
- if (i > 5)
- {
- fprintf (stderr, "\n\t");
- i = len;
- }
- if (TREE_PURPOSE (t) == NULL_TREE)
- {
- print_node_brief (stderr, "<unnamed-typedef", TREE_VALUE (t), 0);
- fprintf (stderr, ">");
- }
- else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
- print_node_brief (stderr, "", TREE_VALUE (t), 0);
- else
- {
- print_node_brief (stderr, "<typedef", TREE_PURPOSE (t), 0);
- print_node_brief (stderr, "", TREE_VALUE (t), 0);
- fprintf (stderr, ">");
- }
- }
- if (i)
- fprintf (stderr, "\n");
- }
- if (lvl->shadowed)
- {
- fprintf (stderr, " shadowed:");
- for (t = lvl->shadowed; t; t = TREE_CHAIN (t))
- {
- fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- }
- fprintf (stderr, "\n");
- }
- if (lvl->class_shadowed)
- {
- fprintf (stderr, " class-shadowed:");
- for (t = lvl->class_shadowed; t; t = TREE_CHAIN (t))
- {
- fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- }
- fprintf (stderr, "\n");
- }
- if (lvl->type_shadowed)
- {
- fprintf (stderr, " type-shadowed:");
- for (t = lvl->type_shadowed; t; t = TREE_CHAIN (t))
- {
-#if 0
- fprintf (stderr, "\n\t");
- print_node_brief (stderr, "<", TREE_PURPOSE (t), 0);
- if (TREE_VALUE (t))
- print_node_brief (stderr, " ", TREE_VALUE (t), 0);
- else
- fprintf (stderr, " (none)");
- fprintf (stderr, ">");
-#else
- fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-#endif
- }
- fprintf (stderr, "\n");
- }
-}
-
-void
-print_other_binding_stack (stack)
- struct binding_level *stack;
-{
- struct binding_level *level;
- for (level = stack; level != global_binding_level; level = level->level_chain)
- {
- fprintf (stderr, "binding level ");
- fprintf (stderr, HOST_PTR_PRINTF, level);
- fprintf (stderr, "\n");
- print_binding_level (level);
- }
-}
-
-void
-print_binding_stack ()
-{
- struct binding_level *b;
- fprintf (stderr, "current_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, current_binding_level);
- fprintf (stderr, "\nclass_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, class_binding_level);
- fprintf (stderr, "\nglobal_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, global_binding_level);
- fprintf (stderr, "\n");
- if (class_binding_level)
- {
- for (b = class_binding_level; b; b = b->level_chain)
- if (b == current_binding_level)
- break;
- if (b)
- b = class_binding_level;
- else
- b = current_binding_level;
- }
- else
- b = current_binding_level;
- print_other_binding_stack (b);
- fprintf (stderr, "global:\n");
- print_binding_level (global_binding_level);
-}
-
-/* Subroutines for reverting temporarily to top-level for instantiation
- of templates and such. We actually need to clear out the class- and
- local-value slots of all identifiers, so that only the global values
- are at all visible. Simply setting current_binding_level to the global
- scope isn't enough, because more binding levels may be pushed. */
-struct saved_scope {
- struct binding_level *old_binding_level;
- tree old_bindings;
- struct saved_scope *prev;
- tree class_name, class_type, class_decl, function_decl;
- struct binding_level *class_bindings;
-};
-static struct saved_scope *current_saved_scope;
-extern tree prev_class_type;
-
-void
-push_to_top_level ()
-{
- struct saved_scope *s =
- (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
- struct binding_level *b = current_binding_level;
- tree old_bindings = NULL_TREE;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- fprintf (stderr, "PUSH_TO_TOP_LEVEL\n");
-#endif
-
- /* Have to include global_binding_level, because class-level decls
- aren't listed anywhere useful. */
- for (; b; b = b->level_chain)
- {
- tree t;
- for (t = b->names; t; t = TREE_CHAIN (t))
- if (b != global_binding_level)
- {
- tree binding, t1, t2 = t;
- tree id = DECL_ASSEMBLER_NAME (t2);
-
- if (!id
- || (!IDENTIFIER_LOCAL_VALUE (id)
- && !IDENTIFIER_CLASS_VALUE (id)))
- continue;
-
- for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
- if (TREE_VEC_ELT (t1, 0) == id)
- goto skip_it;
-
- binding = make_tree_vec (4);
- if (id)
- {
- my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
- TREE_VEC_ELT (binding, 0) = id;
- TREE_VEC_ELT (binding, 1) = IDENTIFIER_TYPE_VALUE (id);
- TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
- TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
- IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
- adjust_type_value (id);
- }
- TREE_CHAIN (binding) = old_bindings;
- old_bindings = binding;
- skip_it:
- ;
- }
- /* Unwind type-value slots back to top level. */
- if (b != global_binding_level)
- for (t = b->type_shadowed; t; t = TREE_CHAIN (t))
- SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t));
- }
-
- s->old_binding_level = current_binding_level;
- current_binding_level = global_binding_level;
-
- s->class_name = current_class_name;
- s->class_type = current_class_type;
- s->class_decl = current_class_decl;
- s->function_decl = current_function_decl;
- s->class_bindings = class_binding_level;
- current_class_name = current_class_type = current_class_decl = NULL_TREE;
- current_function_decl = NULL_TREE;
- class_binding_level = (struct binding_level *)0;
-
- s->prev = current_saved_scope;
- s->old_bindings = old_bindings;
- current_saved_scope = s;
- binding_levels_sane();
-}
-
-void
-pop_from_top_level ()
-{
- struct saved_scope *s = current_saved_scope;
- tree t;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- fprintf (stderr, "POP_FROM_TOP_LEVEL\n");
-#endif
-
- binding_levels_sane();
- current_binding_level = s->old_binding_level;
- current_saved_scope = s->prev;
- for (t = s->old_bindings; t; t = TREE_CHAIN (t))
- {
- tree id = TREE_VEC_ELT (t, 0);
- if (id)
- {
- IDENTIFIER_TYPE_VALUE (id) = TREE_VEC_ELT (t, 1);
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2);
- IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
- }
- }
- current_class_name = s->class_name;
- current_class_type = s->class_type;
- current_class_decl = s->class_decl;
- if (current_class_type)
- C_C_D = CLASSTYPE_INST_VAR (current_class_type);
- else
- C_C_D = NULL_TREE;
- current_function_decl = s->function_decl;
- class_binding_level = s->class_bindings;
- free (s);
- binding_levels_sane();
-}
-
-/* Push a definition of struct, union or enum tag "name".
- "type" should be the type node.
- We assume that the tag "name" is not already defined.
-
- Note that the definition may really be just a forward reference.
- In that case, the TYPE_SIZE will be a NULL_TREE.
-
- C++ gratuitously puts all these tags in the name space. */
-
-/* When setting the IDENTIFIER_TYPE_VALUE field of an identifier ID,
- record the shadowed value for this binding contour. TYPE is
- the type that ID maps to. */
-void
-set_identifier_type_value (id, type)
- tree id;
- tree type;
-{
- if (current_binding_level != global_binding_level)
- {
- tree old_type_value = IDENTIFIER_TYPE_VALUE (id);
- current_binding_level->type_shadowed
- = tree_cons (id, old_type_value, current_binding_level->type_shadowed);
- }
- else if (class_binding_level)
- {
- tree old_type_value = IDENTIFIER_TYPE_VALUE (id);
- class_binding_level->type_shadowed
- = tree_cons (id, old_type_value, class_binding_level->type_shadowed);
- }
- SET_IDENTIFIER_TYPE_VALUE (id, type);
-}
-
-/*
- * local values can need to be shadowed too, but it only happens
- * explicitly from pushdecl, in support of nested enums.
- */
-void
-set_identifier_local_value (id, type)
- tree id;
- tree type;
-{
- if (current_binding_level != global_binding_level)
- {
- tree old_local_value = IDENTIFIER_LOCAL_VALUE (id);
- current_binding_level->shadowed
- = tree_cons (id, old_local_value, current_binding_level->shadowed);
- }
- else if (class_binding_level)
- {
- tree old_local_value = IDENTIFIER_LOCAL_VALUE (id);
- class_binding_level->shadowed
- = tree_cons (id, old_local_value, class_binding_level->shadowed);
- }
- IDENTIFIER_LOCAL_VALUE (id) = type;
-}
-
-/* Subroutine "set_nested_typename" builds the nested-typename of
- the type decl in question. (Argument CLASSNAME can actually be
- a function as well, if that's the smallest containing scope.) */
-
-static void
-set_nested_typename (decl, classname, name, type)
- tree decl, classname, name, type;
-{
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136);
- if (classname != NULL_TREE)
- {
- char *buf;
- my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137);
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138);
- buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname)
- + IDENTIFIER_LENGTH (name));
- sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
- IDENTIFIER_POINTER (name));
- DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
- SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type);
- }
- else
- DECL_NESTED_TYPENAME (decl) = name;
-}
-
-#if 0 /* not yet, should get fixed properly later */
-/* Create a TYPE_DECL node with the correct DECL_ASSEMBLER_NAME.
- Other routines shouldn't use build_decl directly; they'll produce
- incorrect results with `-g' unless they duplicate this code.
-
- This is currently needed mainly for dbxout.c, but we can make
- use of it in cp-method.c later as well. */
-tree
-make_type_decl (name, type)
- tree name, type;
-{
- tree decl, id;
- decl = build_decl (TYPE_DECL, name, type);
- if (TYPE_NAME (type) == name)
- /* Class/union/enum definition, or a redundant typedef for same. */
- {
- id = get_identifier (build_overload_name (type, 1, 1));
- DECL_ASSEMBLER_NAME (decl) = id;
- }
- else if (TYPE_NAME (type) != NULL_TREE)
- /* Explicit typedef, or implicit typedef for template expansion. */
- DECL_ASSEMBLER_NAME (decl) = DECL_ASSEMBLER_NAME (TYPE_NAME (type));
- else
- {
- /* Typedef for unnamed struct; some other situations.
- TYPE_NAME is null; what's right here? */
- }
- return decl;
-}
-
-#endif
-void
-pushtag (name, type)
- tree name, type;
-{
- register struct binding_level *b;
-
- if (class_binding_level)
- b = class_binding_level;
- else
- {
- b = current_binding_level;
- while (b->tag_transparent) b = b->level_chain;
- }
-
- if (b == global_binding_level)
- b->tags = perm_tree_cons (name, type, b->tags);
- else
- b->tags = saveable_tree_cons (name, type, b->tags);
-
- if (name)
- {
- /* Record the identifier as the type's name if it has none. */
-
- if (TYPE_NAME (type) == NULL_TREE)
- TYPE_NAME (type) = name;
-
- /* Do C++ gratuitous typedefing. */
- if (IDENTIFIER_TYPE_VALUE (name) != type
- && (TREE_CODE (type) != RECORD_TYPE
- || class_binding_level == (struct binding_level *)0
- || !CLASSTYPE_DECLARED_EXCEPTION (type)))
- {
- register tree d;
- if (current_class_type == NULL_TREE
- || TYPE_SIZE (current_class_type) != NULL_TREE)
- {
- if (current_lang_name == lang_name_cplusplus)
- d = lookup_nested_type (type, current_class_type ? TYPE_NAME (current_class_type) : NULL_TREE);
- else
- d = NULL_TREE;
-
- if (d == NULL_TREE)
- {
-#if 0 /* not yet, should get fixed properly later */
- d = make_type_decl (name, type);
- DECL_ASSEMBLER_NAME (d) = get_identifier (build_overload_name (type, 1, 1));
-#else
- d = build_decl (TYPE_DECL, name, type);
- DECL_ASSEMBLER_NAME (d) = get_identifier (build_overload_name (type, 1, 1));
-#endif
- /* mark the binding layer marker as internal. (mrs) */
- DECL_SOURCE_LINE (d) = 0;
- set_identifier_type_value (name, type);
- }
- else
- d = TYPE_NAME (d);
-
- /* If it is anonymous, then we are called from pushdecl,
- and we don't want to infinitely recurse. Also, if the
- name is already in scope, we don't want to push it
- again--pushdecl is only for pushing new decls. */
- if (! ANON_AGGRNAME_P (name)
- && TYPE_NAME (type)
- && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL
- || lookup_name (name, 1) != TYPE_NAME (type)))
- {
- if (class_binding_level)
- d = pushdecl_class_level (d);
- else
- d = pushdecl (d);
- }
- }
- else
- {
- /* Make nested declarations go into class-level scope. */
- d = build_lang_field_decl (TYPE_DECL, name, type);
- set_identifier_type_value (name, type);
- d = pushdecl_class_level (d);
- }
- if (ANON_AGGRNAME_P (name))
- DECL_IGNORED_P (d) = 1;
- TYPE_NAME (type) = d;
-
- if ((current_class_type == NULL_TREE
- && current_function_decl == NULL_TREE)
- || current_lang_name != lang_name_cplusplus)
- /* Non-nested class. */
- DECL_NESTED_TYPENAME (d) = name;
- else if (current_function_decl != NULL_TREE)
- {
- /* Function-nested class. */
- set_nested_typename (d, DECL_ASSEMBLER_NAME (current_function_decl),
- name, type);
- /* This builds the links for classes nested in fn scope. */
- DECL_CONTEXT (d) = current_function_decl;
- }
- else if (TYPE_SIZE (current_class_type) == NULL_TREE)
- {
- /* Class-nested class. */
- set_nested_typename (d, DECL_NESTED_TYPENAME (TYPE_NAME (current_class_type)),
- name, type);
- /* This builds the links for classes nested in type scope. */
- DECL_CONTEXT (d) = current_class_type;
- DECL_CLASS_CONTEXT (d) = current_class_type;
- }
- }
- if (b->parm_flag == 2)
- {
- TREE_NONLOCAL_FLAG (type) = 1;
- IDENTIFIER_CLASS_VALUE (name) = TYPE_NAME (type);
- if (TYPE_SIZE (current_class_type) == NULL_TREE)
- CLASSTYPE_TAGS (current_class_type) = b->tags;
- }
- }
-
- if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
- /* Use the canonical TYPE_DECL for this node. */
- TYPE_STUB_DECL (type) = TYPE_NAME (type);
- else
- {
- /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE
- will be the tagged type we just added to the current
- binding level. This fake NULL-named TYPE_DECL node helps
- dwarfout.c to know when it needs to output a
- representation of a tagged type, and it also gives us a
- convenient place to record the "scope start" address for
- the tagged type. */
-
-#if 0 /* not yet, should get fixed properly later */
- TYPE_STUB_DECL (type) = pushdecl (make_type_decl (NULL, type));
-#else
- TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
-#endif
- }
-}
-
-/* Counter used to create anonymous type names. */
-static int anon_cnt = 0;
-
-/* Return an IDENTIFIER which can be used as a name for
- anonymous structs and unions. */
-tree
-make_anon_name ()
-{
- char buf[32];
-
- sprintf (buf, ANON_AGGRNAME_FORMAT, anon_cnt++);
- return get_identifier (buf);
-}
-
-/* Clear the TREE_PURPOSE slot of tags which have anonymous typenames.
- This keeps dbxout from getting confused. */
-void
-clear_anon_tags ()
-{
- register struct binding_level *b;
- register tree tags;
- static int last_cnt = 0;
-
- /* Fast out if no new anon names were declared. */
- if (last_cnt == anon_cnt)
- return;
-
- b = current_binding_level;
- while (b->tag_transparent)
- b = b->level_chain;
- tags = b->tags;
- while (tags)
- {
- /* A NULL purpose means we have already processed all tags
- from here to the end of the list. */
- if (TREE_PURPOSE (tags) == NULL_TREE)
- break;
- if (ANON_AGGRNAME_P (TREE_PURPOSE (tags)))
- TREE_PURPOSE (tags) = NULL_TREE;
- tags = TREE_CHAIN (tags);
- }
- last_cnt = anon_cnt;
-}
-
-/* Subroutine of duplicate_decls: return truthvalue of whether
- or not types of these decls match. */
-static int
-decls_match (newdecl, olddecl)
- tree newdecl, olddecl;
-{
- int types_match;
-
- if (TREE_CODE (newdecl) == FUNCTION_DECL && TREE_CODE (olddecl) == FUNCTION_DECL)
- {
- tree f1 = TREE_TYPE (newdecl);
- tree f2 = TREE_TYPE (olddecl);
- tree p1 = TYPE_ARG_TYPES (f1);
- tree p2 = TYPE_ARG_TYPES (f2);
-
- /* When we parse a static member function definition,
- we put together a FUNCTION_DECL which thinks its type
- is METHOD_TYPE. Change that to FUNCTION_TYPE, and
- proceed. */
- if (TREE_CODE (f1) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (olddecl))
- revert_static_member_fn (&f1, &newdecl, &p1);
- else if (TREE_CODE (f2) == METHOD_TYPE
- && DECL_STATIC_FUNCTION_P (newdecl))
- revert_static_member_fn (&f2, &olddecl, &p2);
-
- /* Here we must take care of the case where new default
- parameters are specified. Also, warn if an old
- declaration becomes ambiguous because default
- parameters may cause the two to be ambiguous. */
- if (TREE_CODE (f1) != TREE_CODE (f2))
- {
- if (TREE_CODE (f1) == OFFSET_TYPE)
- compiler_error_with_decl (newdecl, "`%s' redeclared as member function");
- else
- compiler_error_with_decl (newdecl, "`%s' redeclared as non-member function");
- return 0;
- }
-
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)),
- TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 1))
- types_match = compparms (p1, p2, 1);
- else types_match = 0;
- }
- else
- {
- if (TREE_TYPE (newdecl) == error_mark_node)
- types_match = TREE_TYPE (olddecl) == error_mark_node;
- else if (TREE_TYPE (olddecl) == NULL_TREE)
- types_match = TREE_TYPE (newdecl) == NULL_TREE;
- else
- types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1);
- }
-
- return types_match;
-}
-
-/* Handle when a new declaration NEWDECL has the same name as an old
- one OLDDECL in the same binding contour. Prints an error message
- if appropriate.
-
- If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
- Otherwise, return 0. */
-
-static int
-duplicate_decls (newdecl, olddecl)
- register tree newdecl, olddecl;
-{
- extern struct obstack permanent_obstack;
- unsigned olddecl_uid = DECL_UID (olddecl);
- int olddecl_friend = 0, types_match;
- int new_defines_function;
- register unsigned saved_old_decl_uid;
- register int saved_old_decl_friend_p;
-
- if (TREE_CODE (olddecl) == TREE_LIST
- && TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- /* If a new decl finds a list of old decls, then
- we assume that the new decl has C linkage, and
- that the old decls have C++ linkage. In this case,
- we must look through the list to see whether
- there is an ambiguity or not. */
- tree olddecls = olddecl;
-
- /* If the overload list is empty, just install the decl. */
- if (TREE_VALUE (olddecls) == NULL_TREE)
- {
- TREE_VALUE (olddecls) = newdecl;
- return 1;
- }
-
- while (olddecls)
- {
- if (decls_match (newdecl, TREE_VALUE (olddecls)))
- {
- if (TREE_CODE (newdecl) == VAR_DECL)
- ;
- else if (DECL_LANGUAGE (newdecl)
- != DECL_LANGUAGE (TREE_VALUE (olddecls)))
- {
- error_with_decl (newdecl, "declaration of `%s' with different language linkage");
- error_with_decl (TREE_VALUE (olddecls), "previous declaration here");
- }
- types_match = 1;
- break;
- }
- olddecls = TREE_CHAIN (olddecls);
- }
- if (olddecls)
- olddecl = TREE_VALUE (olddecl);
- else
- return 1;
- }
- else
- {
- if (TREE_CODE (olddecl) != TREE_LIST)
- olddecl_friend = DECL_LANG_SPECIFIC (olddecl) && DECL_FRIEND_P (olddecl);
- types_match = decls_match (newdecl, olddecl);
- }
-
- if ((TREE_TYPE (newdecl) && TREE_CODE (TREE_TYPE (newdecl)) == ERROR_MARK)
- || (TREE_TYPE (olddecl) && TREE_CODE (TREE_TYPE (olddecl)) == ERROR_MARK))
- types_match = 0;
-
- /* If this decl has linkage, and the old one does too, maybe no error. */
- if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
- {
- error_with_decl (newdecl, "`%s' redeclared as different kind of symbol");
- if (TREE_CODE (olddecl) == TREE_LIST)
- olddecl = TREE_VALUE (olddecl);
- error_with_decl (olddecl, "previous declaration of `%s'");
-
- /* New decl is completely inconsistent with the old one =>
- tell caller to replace the old one. */
-
- return 0;
- }
-
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- /* Now that functions must hold information normally held
- by field decls, there is extra work to do so that
- declaration information does not get destroyed during
- definition. */
- if (DECL_VINDEX (olddecl))
- DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl);
- if (DECL_CONTEXT (olddecl))
- DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
- if (DECL_CLASS_CONTEXT (olddecl))
- DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl);
- if (DECL_CHAIN (newdecl) == NULL_TREE)
- DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
- if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
- DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
- }
-
- if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
- && IDENTIFIER_IMPLICIT_DECL (DECL_ASSEMBLER_NAME (newdecl)) == olddecl)
- /* If -traditional, avoid error for redeclaring fcn
- after implicit decl. */
- ;
- else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN (olddecl))
- {
- if (!types_match)
- {
- error_with_decl (newdecl, "declaration of `%s'");
- error_with_decl (olddecl, "conflicts with built-in declaration `%s'");
- }
- }
- else if (!types_match)
- {
- tree oldtype = TREE_TYPE (olddecl);
- tree newtype = TREE_TYPE (newdecl);
- int give_error = 0;
-
- /* Already complained about this, so don't do so again. */
- if (current_class_type == NULL_TREE
- || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
- {
- give_error = 1;
- error_with_decl (newdecl, "conflicting types for `%s'");
- }
-
- /* Check for function type mismatch
- involving an empty arglist vs a nonempty one. */
- if (TREE_CODE (olddecl) == FUNCTION_DECL
- && comptypes (TREE_TYPE (oldtype),
- TREE_TYPE (newtype), 1)
- && ((TYPE_ARG_TYPES (oldtype) == NULL_TREE
- && DECL_INITIAL (olddecl) == NULL_TREE)
- || (TYPE_ARG_TYPES (newtype) == NULL_TREE
- && DECL_INITIAL (newdecl) == NULL_TREE)))
- {
- /* Classify the problem further. */
- register tree t = TYPE_ARG_TYPES (oldtype);
- if (t == NULL_TREE)
- t = TYPE_ARG_TYPES (newtype);
- for (; t; t = TREE_CHAIN (t))
- {
- register tree type = TREE_VALUE (t);
-
- if (TREE_CHAIN (t) == NULL_TREE && type != void_type_node)
- {
- error ("A parameter list with an ellipsis can't match");
- error ("an empty parameter name list declaration.");
- break;
- }
-
- if (TYPE_MAIN_VARIANT (type) == float_type_node
- || C_PROMOTING_INTEGER_TYPE_P (type))
- {
- error ("An argument type that has a default promotion");
- error ("can't match an empty parameter name list declaration.");
- break;
- }
- }
- }
- if (give_error)
- error_with_decl (olddecl, "previous declaration of `%s'");
-
- /* There is one thing GNU C++ cannot tolerate: a constructor
- which takes the type of object being constructed.
- Farm that case out here. */
- if (TREE_CODE (newdecl) == FUNCTION_DECL
- && DECL_CONSTRUCTOR_P (newdecl))
- {
- tree tmp = TREE_CHAIN (TYPE_ARG_TYPES (newtype));
-
- if (tmp != NULL_TREE
- && (TYPE_MAIN_VARIANT (TREE_VALUE (tmp))
- == TYPE_METHOD_BASETYPE (newtype)))
- {
- tree parm = TREE_CHAIN (DECL_ARGUMENTS (newdecl));
- tree argtypes
- = hash_tree_chain (build_reference_type (TREE_VALUE (tmp)),
- TREE_CHAIN (tmp));
-
- DECL_ARG_TYPE (parm)
- = TREE_TYPE (parm)
- = TYPE_REFERENCE_TO (TREE_VALUE (tmp));
-
- TREE_TYPE (newdecl) = newtype
- = build_cplus_method_type (TYPE_METHOD_BASETYPE (newtype),
- TREE_TYPE (newtype), argtypes);
- error ("constructor cannot take as argument the type being constructed");
- SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl), current_class_type);
- }
- }
- }
- else
- {
- char *errmsg = redeclaration_error_message (newdecl, olddecl);
- if (errmsg)
- {
- error_with_decl (newdecl, errmsg);
- if (DECL_NAME (olddecl) != NULL_TREE)
- error_with_decl (olddecl,
- (DECL_INITIAL (olddecl)
- && current_binding_level == global_binding_level)
- ? "`%s' previously defined here"
- : "`%s' previously declared here");
- }
- else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_INITIAL (olddecl) != NULL_TREE
- && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
- && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
- {
- /* Prototype decl follows defn w/o prototype. */
- warning_with_decl (newdecl, "prototype for `%s'");
- warning_with_decl (olddecl,
- "follows non-prototype definition here");
- }
-
- /* These bits are logically part of the type. */
- if (pedantic
- && (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
- || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)))
- error_with_decl (newdecl, "type qualifiers for `%s' conflict with previous decl");
- }
-
- /* Deal with C++: must preserve virtual function table size. */
- if (TREE_CODE (olddecl) == TYPE_DECL)
- {
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (newdecl))
- && TYPE_LANG_SPECIFIC (TREE_TYPE (olddecl)))
- {
- CLASSTYPE_VSIZE (TREE_TYPE (newdecl))
- = CLASSTYPE_VSIZE (TREE_TYPE (olddecl));
- CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (newdecl))
- = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (olddecl));
- }
- /* why assert here? Just because debugging information is
- messed up? (mrs) */
- /* it happens on something like:
- typedef struct Thing {
- Thing();
- int x;
- } Thing;
- */
-#if 0
- my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl), 139);
-#endif
- }
-
- /* Special handling ensues if new decl is a function definition. */
- new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL
- && DECL_INITIAL (newdecl) != NULL_TREE);
-
- /* Optionally warn about more than one declaration for the same name,
- but don't warn about a function declaration followed by a definition. */
- if (warn_redundant_decls
- && DECL_SOURCE_LINE (olddecl) != 0
- && !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE))
- {
- warning_with_decl (newdecl, "redundant redeclaration of `%s' in same scope");
- warning_with_decl (olddecl, "previous declaration of `%s'");
- }
-
- /* Copy all the DECL_... slots specified in the new decl
- except for any that we copy here from the old type. */
-
- if (types_match)
- {
- /* Automatically handles default parameters. */
- tree oldtype = TREE_TYPE (olddecl);
- /* Merge the data types specified in the two decls. */
- tree newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
-
- if (TREE_CODE (newdecl) == VAR_DECL)
- DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
- /* Do this after calling `common_type' so that default
- parameters don't confuse us. */
- else if (TREE_CODE (newdecl) == FUNCTION_DECL
- && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
- != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
- {
- tree ctype = NULL_TREE;
- ctype = DECL_CLASS_CONTEXT (newdecl);
- TREE_TYPE (newdecl) = build_exception_variant (ctype, newtype,
- TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
- TREE_TYPE (olddecl) = build_exception_variant (ctype, newtype,
- TYPE_RAISES_EXCEPTIONS (oldtype));
-
- if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE(olddecl), 0))
- {
- error_with_decl (newdecl, "declaration of `%s' raises different exceptions...");
- error_with_decl (olddecl, "...from previous declaration here");
- }
- }
- TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
-
- /* Lay the type out, unless already done. */
- if (oldtype != TREE_TYPE (newdecl))
- {
- if (TREE_TYPE (newdecl) != error_mark_node)
- layout_type (TREE_TYPE (newdecl));
- if (TREE_CODE (newdecl) != FUNCTION_DECL
- && TREE_CODE (newdecl) != TYPE_DECL
- && TREE_CODE (newdecl) != CONST_DECL)
- layout_decl (newdecl, 0);
- }
- else
- {
- /* Since the type is OLDDECL's, make OLDDECL's size go with. */
- DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
- }
-
- /* Merge the type qualifiers. */
- if (TREE_READONLY (newdecl))
- TREE_READONLY (olddecl) = 1;
- if (TREE_THIS_VOLATILE (newdecl))
- TREE_THIS_VOLATILE (olddecl) = 1;
-
- /* Merge the initialization information. */
- if (DECL_INITIAL (newdecl) == NULL_TREE)
- DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
- /* Keep the old rtl since we can safely use it, unless it's the
- call to abort() used for abstract virtuals. */
- if ((DECL_LANG_SPECIFIC (olddecl)
- && !DECL_ABSTRACT_VIRTUAL_P (olddecl))
- || DECL_RTL (olddecl) != DECL_RTL (abort_fndecl))
- DECL_RTL (newdecl) = DECL_RTL (olddecl);
- }
- /* If cannot merge, then use the new type and qualifiers,
- and don't preserve the old rtl. */
- else
- {
- /* Clean out any memory we had of the old declaration. */
- tree oldstatic = value_member (olddecl, static_aggregates);
- if (oldstatic)
- TREE_VALUE (oldstatic) = error_mark_node;
-
- TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
- TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
- TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
- TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
- }
-
- /* Merge the storage class information. */
- if (DECL_EXTERNAL (newdecl))
- {
- TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
- DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
-
- /* For functions, static overrides non-static. */
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
- /* This is since we don't automatically
- copy the attributes of NEWDECL into OLDDECL. */
- TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
- /* If this clears `static', clear it in the identifier too. */
- if (! TREE_PUBLIC (olddecl))
- TREE_PUBLIC (DECL_ASSEMBLER_NAME (olddecl)) = 0;
- }
- else
- TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
- }
- else
- {
- TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
- /* A `const' which was not declared `extern' and is
- in static storage is invisible. */
- if (TREE_CODE (newdecl) == VAR_DECL
- && TREE_READONLY (newdecl) && TREE_STATIC (newdecl)
- && ! DECL_THIS_EXTERN (newdecl))
- TREE_PUBLIC (newdecl) = 0;
- TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
- }
-
- /* If either decl says `inline', this fn is inline,
- unless its definition was passed already. */
- if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
- DECL_INLINE (olddecl) = 1;
- DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
-
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- if (new_defines_function)
- /* If defining a function declared with other language
- linkage, use the previously declared language linkage. */
- DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
- else
- {
- /* If redeclaring a builtin function, and not a definition,
- it stays built in. */
- if (DECL_BUILT_IN (olddecl))
- {
- DECL_BUILT_IN (newdecl) = 1;
- DECL_SET_FUNCTION_CODE (newdecl, DECL_FUNCTION_CODE (olddecl));
- /* If we're keeping the built-in definition, keep the rtl,
- regardless of declaration matches. */
- DECL_RTL (newdecl) = DECL_RTL (olddecl);
- }
- else
- DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
-
- DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
- if (DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl))
- /* Previously saved insns go together with
- the function's previous definition. */
- DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
- /* Don't clear out the arguments if we're redefining a function. */
- if (DECL_ARGUMENTS (olddecl))
- DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
- }
- }
-
- /* Now preserve various other info from the definition. */
- TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
- TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
-
- /* Don't really know how much of the language-specific
- values we should copy from old to new. */
-#if 1
- if (DECL_LANG_SPECIFIC (olddecl))
- DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
-#endif
-
- /* We are about to copy the contexts of newdecl into olddecl, so save a
- few tidbits of information from olddecl that we may need to restore
- after the copying takes place. */
-
- saved_old_decl_uid = DECL_UID (olddecl);
- saved_old_decl_friend_p
- = DECL_LANG_SPECIFIC (olddecl) ? DECL_FRIEND_P (olddecl) : 0;
-
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- int function_size;
- struct lang_decl *ol = DECL_LANG_SPECIFIC (olddecl);
- struct lang_decl *nl = DECL_LANG_SPECIFIC (newdecl);
-
- function_size = sizeof (struct tree_decl);
-
- bcopy ((char *) newdecl + sizeof (struct tree_common),
- (char *) olddecl + sizeof (struct tree_common),
- function_size - sizeof (struct tree_common));
-
- if ((char *)newdecl + ((function_size + sizeof (struct lang_decl)
- + obstack_alignment_mask (&permanent_obstack))
- & ~ obstack_alignment_mask (&permanent_obstack))
- == obstack_next_free (&permanent_obstack))
- {
- DECL_MAIN_VARIANT (newdecl) = olddecl;
- DECL_LANG_SPECIFIC (olddecl) = ol;
- bcopy ((char *)nl, (char *)ol, sizeof (struct lang_decl));
-
- obstack_free (&permanent_obstack, newdecl);
- }
- else if (LANG_DECL_PERMANENT (ol))
- {
- if (DECL_MAIN_VARIANT (olddecl) == olddecl)
- {
- /* Save these lang_decls that would otherwise be lost. */
- extern tree free_lang_decl_chain;
- tree free_lang_decl = (tree) ol;
- TREE_CHAIN (free_lang_decl) = free_lang_decl_chain;
- free_lang_decl_chain = free_lang_decl;
- }
- else
- {
- /* Storage leak. */
- }
- }
- }
- else
- {
- bcopy ((char *) newdecl + sizeof (struct tree_common),
- (char *) olddecl + sizeof (struct tree_common),
- sizeof (struct tree_decl) - sizeof (struct tree_common)
- + tree_code_length [(int)TREE_CODE (newdecl)] * sizeof (char *));
- }
-
- DECL_UID (olddecl) = olddecl_uid;
- if (olddecl_friend)
- DECL_FRIEND_P (olddecl) = 1;
-
- /* Restore some pieces of information which were originally in olddecl. */
-
- DECL_UID (olddecl) = saved_old_decl_uid;
- if (DECL_LANG_SPECIFIC (olddecl))
- DECL_FRIEND_P (olddecl) |= saved_old_decl_friend_p;
-
- return 1;
-}
-
-void
-adjust_type_value (id)
- tree id;
-{
- tree t;
-
- if (current_binding_level != global_binding_level)
- {
- if (current_binding_level != class_binding_level)
- {
- t = IDENTIFIER_LOCAL_VALUE (id);
- if (t && TREE_CODE (t) == TYPE_DECL)
- {
- set_it:
- SET_IDENTIFIER_TYPE_VALUE (id, TREE_TYPE (t));
- return;
- }
- }
- else
- my_friendly_abort (7);
-
- if (current_class_type)
- {
- t = IDENTIFIER_CLASS_VALUE (id);
- if (t && TREE_CODE (t) == TYPE_DECL)
- goto set_it;
- }
- }
-
- t = IDENTIFIER_GLOBAL_VALUE (id);
- if (t && TREE_CODE (t) == TYPE_DECL)
- goto set_it;
- if (t && TREE_CODE (t) == TEMPLATE_DECL)
- SET_IDENTIFIER_TYPE_VALUE (id, NULL_TREE);
-}
-
-/* Record a decl-node X as belonging to the current lexical scope.
- Check for errors (such as an incompatible declaration for the same
- name already seen in the same scope).
-
- Returns either X or an old decl for the same name.
- If an old decl is returned, it may have been smashed
- to agree with what X says. */
-
-tree
-pushdecl (x)
- tree x;
-{
- register tree t;
-#if 0 /* not yet, should get fixed properly later */
- register tree name;
-#else
- register tree name = DECL_ASSEMBLER_NAME (x);
-#endif
- register struct binding_level *b = current_binding_level;
-
-#if 0
- static int nglobals; int len;
-
- len = list_length (global_binding_level->names);
- if (len < nglobals)
- my_friendly_abort (8);
- else if (len > nglobals)
- nglobals = len;
-#endif
-
- /* Don't change DECL_CONTEXT of virtual methods. */
- if (x != current_function_decl
- && (TREE_CODE (x) != FUNCTION_DECL
- || !DECL_VIRTUAL_P (x)))
- DECL_CONTEXT (x) = current_function_decl;
- /* A local declaration for a function doesn't constitute nesting. */
- if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0)
- DECL_CONTEXT (x) = 0;
-
-#if 0 /* not yet, should get fixed properly later */
- /* For functions and class static data, we currently look up the encoded
- form of the name. For types, we want the real name. The former will
- probably be changed soon, according to MDT. */
- if (TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
- name = DECL_ASSEMBLER_NAME (x);
- else
- name = DECL_NAME (x);
-#else
- /* Type are looked up using the DECL_NAME, as that is what the rest of the
- compiler wants to use. */
- if (TREE_CODE (x) == TYPE_DECL)
- name = DECL_NAME (x);
-#endif
-
- if (name)
- {
- char *file;
- int line;
-
- t = lookup_name_current_level (name);
- if (t == error_mark_node)
- {
- /* error_mark_node is 0 for a while during initialization! */
- t = NULL_TREE;
- error_with_decl (x, "`%s' used prior to declaration");
- }
-
- if (t != NULL_TREE)
- {
- if (TREE_CODE (t) == PARM_DECL)
- {
- if (DECL_CONTEXT (t) == NULL_TREE)
- fatal ("parse errors have confused me too much");
- }
- file = DECL_SOURCE_FILE (t);
- line = DECL_SOURCE_LINE (t);
- }
-
- if (t != NULL_TREE && TREE_CODE (t) != TREE_CODE (x))
- {
- if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL)
- {
- /* We do nothing special here, because C++ does such nasty
- things with TYPE_DECLs. Instead, just let the TYPE_DECL
- get shadowed, and know that if we need to find a TYPE_DECL
- for a given name, we can look in the IDENTIFIER_TYPE_VALUE
- slot of the identifier. */
- ;
- }
- else if (duplicate_decls (x, t))
- return t;
- }
- else if (t != NULL_TREE && duplicate_decls (x, t))
- {
- /* If this decl is `static' and an `extern' was seen previously,
- that is erroneous. But don't complain if -traditional,
- since traditional compilers don't complain.
-
- Note that this does not apply to the C++ case of declaring
- a variable `extern const' and then later `const'. */
- if (!flag_traditional && TREE_PUBLIC (name)
- && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x) && ! DECL_INLINE (x))
- {
- /* Due to interference in memory reclamation (X may be
- obstack-deallocated at this point), we must guard against
- one really special case. */
- if (current_function_decl == x)
- current_function_decl = t;
- if (IDENTIFIER_IMPLICIT_DECL (name))
- warning ("`%s' was declared implicitly `extern' and later `static'",
- lang_printable_name (t));
- else
- warning ("`%s' was declared `extern' and later `static'",
- lang_printable_name (t));
- warning_with_file_and_line (file, line,
- "previous declaration of `%s'",
- lang_printable_name (t));
- }
- return t;
- }
-
- /* If declaring a type as a typedef, and the type has no known
- typedef name, install this TYPE_DECL as its typedef name.
-
- C++: If it had an anonymous aggregate or enum name,
- give it a `better' one. */
- if (TREE_CODE (x) == TYPE_DECL)
- {
- tree name = TYPE_NAME (TREE_TYPE (x));
-
- if (name == NULL_TREE || TREE_CODE (name) != TYPE_DECL)
- {
- /* If these are different names, and we're at the global
- binding level, make two equivalent definitions. */
- name = x;
- if (global_bindings_p ())
- TYPE_NAME (TREE_TYPE (x)) = x;
- }
- else
- {
- tree tname = DECL_NAME (name);
- if (global_bindings_p () && ANON_AGGRNAME_P (tname))
- {
- /* do gratuitous C++ typedefing, and make sure that
- we access this type either through TREE_TYPE field
- or via the tags list. */
- TYPE_NAME (TREE_TYPE (x)) = x;
- pushtag (tname, TREE_TYPE (x));
- }
- }
- my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140);
- if (DECL_NAME (name) && !DECL_NESTED_TYPENAME (name))
- set_nested_typename (x, current_class_name, DECL_NAME (name),
- TREE_TYPE (x));
- if (TYPE_NAME (TREE_TYPE (x)) && TYPE_IDENTIFIER (TREE_TYPE (x)))
- set_identifier_type_value (DECL_NAME (x), TREE_TYPE (x));
-/* was using TYPE_IDENTIFIER (TREE_TYPE (x)) */
- }
-
- /* Multiple external decls of the same identifier ought to match. */
-
- if (DECL_EXTERNAL (x) && IDENTIFIER_GLOBAL_VALUE (name) != NULL_TREE
- && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
- || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name)))
- /* We get warnings about inline functions where they are defined.
- Avoid duplicate warnings where they are used. */
- && !DECL_INLINE (x))
- {
- if (! comptypes (TREE_TYPE (x),
- TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)), 1))
- {
- warning_with_decl (x,
- "type mismatch with previous external decl");
- warning_with_decl (IDENTIFIER_GLOBAL_VALUE (name),
- "previous external decl of `%s'");
- }
- }
-
- /* In PCC-compatibility mode, extern decls of vars with no current decl
- take effect at top level no matter where they are. */
- if (flag_traditional && DECL_EXTERNAL (x)
- && lookup_name (name, 0) == NULL_TREE)
- b = global_binding_level;
-
- /* This name is new in its binding level.
- Install the new declaration and return it. */
- if (b == global_binding_level)
- {
- /* Install a global value. */
-
- /* Rule for VAR_DECLs, but not for other kinds of _DECLs:
- A `const' which was not declared `extern' is invisible. */
- if (TREE_CODE (x) == VAR_DECL
- && TREE_READONLY (x) && ! DECL_THIS_EXTERN (x))
- TREE_PUBLIC (x) = 0;
-
- /* If the first global decl has external linkage,
- warn if we later see static one. */
- if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
- TREE_PUBLIC (name) = 1;
-
- /* Don't install a TYPE_DECL if we already have another
- sort of _DECL with that name. */
- if (TREE_CODE (x) != TYPE_DECL
- || t == NULL_TREE
- || TREE_CODE (t) == TYPE_DECL)
-#if 0
- /* This has not be thoroughly tested yet. */
- /* It allows better dwarf debugging. */
- IDENTIFIER_GLOBAL_VALUE (name)
- = TREE_CODE_CLASS (TREE_CODE (x)) == 'd'
- ? x : build_decl (TYPE_DECL, NULL, TREE_TYPE (x));
-#else
- IDENTIFIER_GLOBAL_VALUE (name) = x;
-#endif
-
- /* Don't forget if the function was used via an implicit decl. */
- if (IDENTIFIER_IMPLICIT_DECL (name)
- && TREE_USED (IDENTIFIER_IMPLICIT_DECL (name)))
- TREE_USED (x) = 1;
-
- /* Don't forget if its address was taken in that way. */
- if (IDENTIFIER_IMPLICIT_DECL (name)
- && TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name)))
- TREE_ADDRESSABLE (x) = 1;
-
- /* Warn about mismatches against previous implicit decl. */
- if (IDENTIFIER_IMPLICIT_DECL (name) != NULL_TREE
- /* If this real decl matches the implicit, don't complain. */
- && ! (TREE_CODE (x) == FUNCTION_DECL
- && TREE_TYPE (TREE_TYPE (x)) == integer_type_node))
- warning ("`%s' was previously implicitly declared to return `int'",
- lang_printable_name (x));
-
- /* If this decl is `static' and an `extern' was seen previously,
- that is erroneous. Don't do this for TYPE_DECLs. */
- if (TREE_PUBLIC (name)
- && TREE_CODE (x) != TYPE_DECL
- && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x))
- {
- if (IDENTIFIER_IMPLICIT_DECL (name))
- warning ("`%s' was declared implicitly `extern' and later `static'",
- lang_printable_name (x));
- else
- warning ("`%s' was declared `extern' and later `static'",
- lang_printable_name (x));
- }
- }
- else
- {
- /* Here to install a non-global value. */
- tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
- tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
- set_identifier_local_value (name, x);
-
- /* If this is an extern function declaration, see if we
- have a global definition or declaration for the function. */
- if (oldlocal == NULL_TREE
- && DECL_EXTERNAL (x) && !DECL_INLINE (x)
- && oldglobal != NULL_TREE
- && TREE_CODE (x) == FUNCTION_DECL
- && TREE_CODE (oldglobal) == FUNCTION_DECL)
- {
- /* We have one. Their types must agree. */
- if (! comptypes (TREE_TYPE (x), TREE_TYPE (oldglobal), 1))
- warning_with_decl (x, "extern declaration of `%s' doesn't match global one");
- else
- {
- /* Inner extern decl is inline if global one is.
- Copy enough to really inline it. */
- if (DECL_INLINE (oldglobal))
- {
- DECL_INLINE (x) = DECL_INLINE (oldglobal);
- DECL_INITIAL (x) = (current_function_decl == oldglobal
- ? NULL_TREE : DECL_INITIAL (oldglobal));
- DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal);
- DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
- DECL_RESULT (x) = DECL_RESULT (oldglobal);
- TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
- DECL_ABSTRACT_ORIGIN (x) = oldglobal;
- }
- /* Inner extern decl is built-in if global one is. */
- if (DECL_BUILT_IN (oldglobal))
- {
- DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal);
- DECL_SET_FUNCTION_CODE (x, DECL_FUNCTION_CODE (oldglobal));
- }
- /* Keep the arg types from a file-scope fcn defn. */
- if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != NULL_TREE
- && DECL_INITIAL (oldglobal)
- && TYPE_ARG_TYPES (TREE_TYPE (x)) == NULL_TREE)
- TREE_TYPE (x) = TREE_TYPE (oldglobal);
- }
- }
- /* If we have a local external declaration,
- and no file-scope declaration has yet been seen,
- then if we later have a file-scope decl it must not be static. */
- if (oldlocal == NULL_TREE
- && oldglobal == NULL_TREE
- && DECL_EXTERNAL (x)
- && TREE_PUBLIC (x))
- {
- TREE_PUBLIC (name) = 1;
- }
-
- if (DECL_FROM_INLINE (x))
- /* Inline decls shadow nothing. */;
-
- /* Warn if shadowing an argument at the top level of the body. */
- else if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
- && TREE_CODE (oldlocal) == PARM_DECL
- && TREE_CODE (x) != PARM_DECL)
- {
- /* Go to where the parms should be and see if we
- find them there. */
- struct binding_level *b = current_binding_level->level_chain;
-
- if (cleanup_label)
- b = b->level_chain;
-
- /* ARM $8.3 */
- if (b->parm_flag == 1)
- pedwarn ("declaration of `%s' shadows a parameter",
- IDENTIFIER_POINTER (name));
- }
- /* Maybe warn if shadowing something else. */
- else if (warn_shadow && !DECL_EXTERNAL (x)
- /* No shadow warnings for internally generated vars. */
- && DECL_SOURCE_LINE (x) != 0
- /* No shadow warnings for vars made for inlining. */
- && ! DECL_FROM_INLINE (x))
- {
- char *warnstring = NULL;
-
- if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
- warnstring = "declaration of `%s' shadows a parameter";
- else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE)
- warnstring = "declaration of `%s' shadows a member of `this'";
- else if (oldlocal != NULL_TREE)
- warnstring = "declaration of `%s' shadows previous local";
- else if (oldglobal != NULL_TREE)
- warnstring = "declaration of `%s' shadows global declaration";
-
- if (warnstring)
- warning (warnstring, IDENTIFIER_POINTER (name));
- }
-
- /* If storing a local value, there may already be one (inherited).
- If so, record it for restoration when this binding level ends. */
- if (oldlocal != NULL_TREE)
- b->shadowed = tree_cons (name, oldlocal, b->shadowed);
- }
-
- /* Keep count of variables in this level with incomplete type. */
- if (TREE_CODE (x) != TEMPLATE_DECL
- && TREE_CODE (x) != CPLUS_CATCH_DECL
- && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
- && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
- {
- if (++b->n_incomplete == 0)
- error ("too many incomplete variables at this point");
- }
- }
-
- if (TREE_CODE (x) == TYPE_DECL && name != NULL_TREE)
- {
- adjust_type_value (name);
- if (current_class_name)
- {
- if (!DECL_NESTED_TYPENAME (x))
- set_nested_typename (x, current_class_name, DECL_NAME (x),
- TREE_TYPE (x));
- adjust_type_value (DECL_NESTED_TYPENAME (x));
- }
- }
-
- /* Put decls on list in reverse order.
- We will reverse them later if necessary. */
- TREE_CHAIN (x) = b->names;
- b->names = x;
- if (! (b != global_binding_level || TREE_PERMANENT (x)))
- my_friendly_abort (124);
-
- return x;
-}
-
-/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
- if appropriate. */
-tree
-pushdecl_top_level (x)
- tree x;
-{
- register tree t;
- register struct binding_level *b = current_binding_level;
-
- current_binding_level = global_binding_level;
- t = pushdecl (x);
- current_binding_level = b;
- if (class_binding_level)
- b = class_binding_level;
- /* Now, the type_shadowed stack may screw us. Munge it so it does
- what we want. */
- if (TREE_CODE (x) == TYPE_DECL)
- {
- tree name = DECL_NAME (x);
- tree newval;
- tree *ptr = (tree *)0;
- for (; b != global_binding_level; b = b->level_chain)
- {
- tree shadowed = b->type_shadowed;
- for (; shadowed; shadowed = TREE_CHAIN (shadowed))
- if (TREE_PURPOSE (shadowed) == name)
- {
- ptr = &TREE_VALUE (shadowed);
- /* Can't break out of the loop here because sometimes
- a binding level will have duplicate bindings for
- PT names. It's gross, but I haven't time to fix it. */
- }
- }
- newval = TREE_TYPE (x);
- if (ptr == (tree *)0)
- {
- /* @@ This shouldn't be needed. My test case "zstring.cc" trips
- up here if this is changed to an assertion. --KR */
- SET_IDENTIFIER_TYPE_VALUE (name, newval);
- }
- else
- {
-#if 0
- /* Disabled this 11/10/92, since there are many cases which
- behave just fine when *ptr doesn't satisfy either of these.
- For example, nested classes declared as friends of their enclosing
- class will not meet this criteria. (bpk) */
- my_friendly_assert (*ptr == NULL_TREE || *ptr == newval, 141);
-#endif
- *ptr = newval;
- }
- }
- return t;
-}
-
-/* Like push_overloaded_decl, only it places X in GLOBAL_BINDING_LEVEL,
- if appropriate. */
-void
-push_overloaded_decl_top_level (x, forget)
- tree x;
- int forget;
-{
- struct binding_level *b = current_binding_level;
-
- current_binding_level = global_binding_level;
- push_overloaded_decl (x, forget);
- current_binding_level = b;
-}
-
-/* Make the declaration of X appear in CLASS scope. */
-tree
-pushdecl_class_level (x)
- tree x;
-{
- /* Don't use DECL_ASSEMBLER_NAME here! Everything that looks in class
- scope looks for the pre-mangled name. */
- register tree name = DECL_NAME (x);
-
- if (name)
- {
- tree oldclass = IDENTIFIER_CLASS_VALUE (name);
- if (oldclass)
- class_binding_level->class_shadowed
- = tree_cons (name, oldclass, class_binding_level->class_shadowed);
- IDENTIFIER_CLASS_VALUE (name) = x;
- obstack_ptr_grow (&decl_obstack, x);
- if (TREE_CODE (x) == TYPE_DECL && !DECL_NESTED_TYPENAME (x))
- set_nested_typename (x, current_class_name, name, TREE_TYPE (x));
- }
- return x;
-}
-
-/* Tell caller how to interpret a TREE_LIST which contains
- chains of FUNCTION_DECLS. */
-int
-overloaded_globals_p (list)
- tree list;
-{
- my_friendly_assert (TREE_CODE (list) == TREE_LIST, 142);
-
- /* Don't commit caller to seeing them as globals. */
- if (TREE_NONLOCAL_FLAG (list))
- return -1;
- /* Do commit caller to seeing them as globals. */
- if (TREE_CODE (TREE_PURPOSE (list)) == IDENTIFIER_NODE)
- return 1;
- /* Do commit caller to not seeing them as globals. */
- return 0;
-}
-
-/* DECL is a FUNCTION_DECL which may have other definitions already in place.
- We get around this by making IDENTIFIER_GLOBAL_VALUE (DECL_NAME (DECL))
- point to a list of all the things that want to be referenced by that name.
- It is then up to the users of that name to decide what to do with that
- list.
-
- DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
- slot. It is dealt with the same way.
-
- The value returned may be a previous declaration if we guessed wrong
- about what language DECL should belong to (C or C++). Otherwise,
- it's always DECL (and never something that's not a _DECL). */
-tree
-push_overloaded_decl (decl, forgettable)
- tree decl;
- int forgettable;
-{
- tree orig_name = DECL_NAME (decl);
- tree glob = IDENTIFIER_GLOBAL_VALUE (orig_name);
-
- DECL_OVERLOADED (decl) = 1;
- if (glob)
- {
- if (TREE_CODE (glob) != TREE_LIST)
- {
- if (DECL_LANGUAGE (decl) == lang_c)
- {
- if (TREE_CODE (glob) == FUNCTION_DECL)
- {
- if (DECL_LANGUAGE (glob) == lang_c)
- {
- error_with_decl (decl, "C-language function `%s' overloaded here");
- error_with_decl (glob, "Previous C-language version of this function was `%s'");
- }
- }
- else
- my_friendly_abort (9);
- }
- if (forgettable
- && ! flag_traditional
- && TREE_PERMANENT (glob) == 1
- && !global_bindings_p ())
- overloads_to_forget = tree_cons (orig_name, glob, overloads_to_forget);
- /* We cache the value of builtin functions as ADDR_EXPRs
- in the name space. Convert it to some kind of _DECL after
- remembering what to forget. */
- if (TREE_CODE (glob) == ADDR_EXPR)
- glob = TREE_OPERAND (glob, 0);
-
- if (TREE_CODE (glob) == FUNCTION_DECL
- && DECL_LANGUAGE (glob) != DECL_LANGUAGE (decl)
- && comptypes (TREE_TYPE (glob), TREE_TYPE (decl), 1))
- {
- if (current_lang_stack == current_lang_base)
- {
- DECL_LANGUAGE (decl) = DECL_LANGUAGE (glob);
- return glob;
- }
- else
- {
- error_with_decl (decl, "conflicting language contexts for declaration of `%s';");
- error_with_decl (glob, "conflicts with previous declaration here");
- }
- }
- if (pedantic && TREE_CODE (glob) == VAR_DECL)
- {
- my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (glob)) == 'd', 143);
- error_with_decl (glob, "non-function declaration `%s'");
- error_with_decl (decl, "conflicts with function declaration `%s'");
- }
- glob = tree_cons (orig_name, glob, NULL_TREE);
- glob = tree_cons (TREE_PURPOSE (glob), decl, glob);
- IDENTIFIER_GLOBAL_VALUE (orig_name) = glob;
- TREE_TYPE (glob) = unknown_type_node;
- return decl;
- }
-
- if (TREE_VALUE (glob) == NULL_TREE)
- {
- TREE_VALUE (glob) = decl;
- return decl;
- }
- if (TREE_CODE (decl) != TEMPLATE_DECL)
- {
- tree name = DECL_ASSEMBLER_NAME (decl);
- tree tmp;
-
- for (tmp = glob; tmp; tmp = TREE_CHAIN (tmp))
- {
- if (TREE_CODE (TREE_VALUE (tmp)) == FUNCTION_DECL
- && DECL_LANGUAGE (TREE_VALUE (tmp)) != DECL_LANGUAGE (decl)
- && comptypes (TREE_TYPE (TREE_VALUE (tmp)), TREE_TYPE (decl),
- 1))
- {
- error_with_decl (decl,
- "conflicting language contexts for declaration of `%s';");
- error_with_decl (TREE_VALUE (tmp),
- "conflicts with previous declaration here");
- }
- if (TREE_CODE (TREE_VALUE (tmp)) != TEMPLATE_DECL
- && DECL_ASSEMBLER_NAME (TREE_VALUE (tmp)) == name)
- return decl;
- }
- }
- }
- if (DECL_LANGUAGE (decl) == lang_c)
- {
- tree decls = glob;
- while (decls && DECL_LANGUAGE (TREE_VALUE (decls)) == lang_cplusplus)
- decls = TREE_CHAIN (decls);
- if (decls)
- {
- error_with_decl (decl, "C-language function `%s' overloaded here");
- error_with_decl (TREE_VALUE (decls), "Previous C-language version of this function was `%s'");
- }
- }
-
- if (forgettable
- && ! flag_traditional
- && (glob == NULL_TREE || TREE_PERMANENT (glob) == 1)
- && !global_bindings_p ()
- && !pseudo_global_level_p ())
- overloads_to_forget = tree_cons (orig_name, glob, overloads_to_forget);
- glob = tree_cons (orig_name, decl, glob);
- IDENTIFIER_GLOBAL_VALUE (orig_name) = glob;
- TREE_TYPE (glob) = unknown_type_node;
- return decl;
-}
-
-/* Generate an implicit declaration for identifier FUNCTIONID
- as a function of type int (). Print a warning if appropriate. */
-
-tree
-implicitly_declare (functionid)
- tree functionid;
-{
- register tree decl;
- int temp = allocation_temporary_p ();
-
- push_obstacks_nochange ();
-
- /* Save the decl permanently so we can warn if definition follows.
- In ANSI C, warn_implicit is usually false, so the saves little space.
- But in C++, it's usually true, hence the extra code. */
- if (temp && (flag_traditional || !warn_implicit
- || current_binding_level == global_binding_level))
- end_temporary_allocation ();
-
- /* We used to reuse an old implicit decl here,
- but this loses with inline functions because it can clobber
- the saved decl chains. */
- decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type);
-
- DECL_EXTERNAL (decl) = 1;
- TREE_PUBLIC (decl) = 1;
-
- /* ANSI standard says implicit declarations are in the innermost block.
- So we record the decl in the standard fashion.
- If flag_traditional is set, pushdecl does it top-level. */
- pushdecl (decl);
- rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
-
- if (warn_implicit
- /* Only one warning per identifier. */
- && IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE)
- {
- pedwarn ("implicit declaration of function `%s'",
- IDENTIFIER_POINTER (functionid));
- }
-
- SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
-
- pop_obstacks ();
-
- return decl;
-}
-
-/* Return zero if the declaration NEWDECL is valid
- when the declaration OLDDECL (assumed to be for the same name)
- has already been seen.
- Otherwise return an error message format string with a %s
- where the identifier should go. */
-
-static char *
-redeclaration_error_message (newdecl, olddecl)
- tree newdecl, olddecl;
-{
- if (TREE_CODE (newdecl) == TYPE_DECL)
- {
- /* Because C++ can put things into name space for free,
- constructs like "typedef struct foo { ... } foo"
- would look like an erroneous redeclaration. */
- if (TREE_TYPE (olddecl) == TREE_TYPE (newdecl))
- return 0;
- else
- return "redefinition of `%s'";
- }
- else if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- /* If this is a pure function, its olddecl will actually be
- the original initialization to `0' (which we force to call
- abort()). Don't complain about redefinition in this case. */
- if (DECL_LANG_SPECIFIC (olddecl) && DECL_ABSTRACT_VIRTUAL_P (olddecl))
- return 0;
-
- /* Declarations of functions can insist on internal linkage
- but they can't be inconsistent with internal linkage,
- so there can be no error on that account.
- However defining the same name twice is no good. */
- if (DECL_INITIAL (olddecl) != NULL_TREE
- && DECL_INITIAL (newdecl) != NULL_TREE
- /* However, defining once as extern inline and a second
- time in another way is ok. */
- && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
- && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
- {
- if (DECL_NAME (olddecl) == NULL_TREE)
- return "`%s' not declared in class";
- else
- return "redefinition of `%s'";
- }
- return 0;
- }
- else if (current_binding_level == global_binding_level)
- {
- /* Objects declared at top level: */
- /* If at least one is a reference, it's ok. */
- if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
- return 0;
- /* Reject two definitions. */
- if (DECL_INITIAL (olddecl) != NULL_TREE
- && DECL_INITIAL (newdecl) != NULL_TREE)
- return "redefinition of `%s'";
- /* Now we have two tentative defs, or one tentative and one real def. */
- /* Insist that the linkage match. */
- if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
- return "conflicting declarations of `%s'";
- return 0;
- }
- else
- {
- /* Objects declared with block scope: */
- /* Reject two definitions, and reject a definition
- together with an external reference. */
- if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
- return "redeclaration of `%s'";
- return 0;
- }
-}
-
-/* Get the LABEL_DECL corresponding to identifier ID as a label.
- Create one if none exists so far for the current function.
- This function is called for both label definitions and label references. */
-
-tree
-lookup_label (id)
- tree id;
-{
- register tree decl = IDENTIFIER_LABEL_VALUE (id);
-
- if ((decl == NULL_TREE
- || DECL_SOURCE_LINE (decl) == 0)
- && (named_label_uses == 0
- || TREE_PURPOSE (named_label_uses) != current_binding_level->names
- || TREE_VALUE (named_label_uses) != decl))
- {
- named_label_uses
- = tree_cons (current_binding_level->names, decl, named_label_uses);
- TREE_TYPE (named_label_uses) = (tree)current_binding_level;
- }
-
- /* Use a label already defined or ref'd with this name. */
- if (decl != NULL_TREE)
- {
- /* But not if it is inherited and wasn't declared to be inheritable. */
- if (DECL_CONTEXT (decl) != current_function_decl
- && ! C_DECLARED_LABEL_FLAG (decl))
- return shadow_label (id);
- return decl;
- }
-
- decl = build_decl (LABEL_DECL, id, void_type_node);
-
- /* A label not explicitly declared must be local to where it's ref'd. */
- DECL_CONTEXT (decl) = current_function_decl;
-
- DECL_MODE (decl) = VOIDmode;
-
- /* Say where one reference is to the label,
- for the sake of the error if it is not defined. */
- DECL_SOURCE_LINE (decl) = lineno;
- DECL_SOURCE_FILE (decl) = input_filename;
-
- SET_IDENTIFIER_LABEL_VALUE (id, decl);
-
- named_labels = tree_cons (NULL_TREE, decl, named_labels);
- TREE_VALUE (named_label_uses) = decl;
-
- return decl;
-}
-
-/* Make a label named NAME in the current function,
- shadowing silently any that may be inherited from containing functions
- or containing scopes.
-
- Note that valid use, if the label being shadowed
- comes from another scope in the same function,
- requires calling declare_nonlocal_label right away. */
-
-tree
-shadow_label (name)
- tree name;
-{
- register tree decl = IDENTIFIER_LABEL_VALUE (name);
-
- if (decl != NULL_TREE)
- {
- shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
- SET_IDENTIFIER_LABEL_VALUE (name, 0);
- SET_IDENTIFIER_LABEL_VALUE (decl, 0);
- }
-
- return lookup_label (name);
-}
-
-/* Define a label, specifying the location in the source file.
- Return the LABEL_DECL node for the label, if the definition is valid.
- Otherwise return 0. */
-
-tree
-define_label (filename, line, name)
- char *filename;
- int line;
- tree name;
-{
- tree decl = lookup_label (name);
-
- /* After labels, make any new cleanups go into their
- own new (temporary) binding contour. */
- current_binding_level->more_cleanups_ok = 0;
-
- /* If label with this name is known from an outer context, shadow it. */
- if (decl != NULL_TREE && DECL_CONTEXT (decl) != current_function_decl)
- {
- shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
- SET_IDENTIFIER_LABEL_VALUE (name, 0);
- decl = lookup_label (name);
- }
-
- if (DECL_INITIAL (decl) != NULL_TREE)
- {
- error_with_decl (decl, "duplicate label `%s'");
- return 0;
- }
- else
- {
- tree uses, prev;
-
- /* Mark label as having been defined. */
- DECL_INITIAL (decl) = error_mark_node;
- /* Say where in the source. */
- DECL_SOURCE_FILE (decl) = filename;
- DECL_SOURCE_LINE (decl) = line;
-
- for (prev = NULL_TREE, uses = named_label_uses;
- uses;
- prev = uses, uses = TREE_CHAIN (uses))
- if (TREE_VALUE (uses) == decl)
- {
- struct binding_level *b = current_binding_level;
- while (b)
- {
- tree new_decls = b->names;
- tree old_decls = ((tree)b == TREE_TYPE (uses)
- ? TREE_PURPOSE (uses) : NULL_TREE);
- while (new_decls != old_decls)
- {
- if (TREE_CODE (new_decls) == VAR_DECL
- /* Don't complain about crossing initialization
- of internal entities. They can't be accessed,
- and they should be cleaned up
- by the time we get to the label. */
- && DECL_SOURCE_LINE (new_decls) != 0
- && ((DECL_INITIAL (new_decls) != NULL_TREE
- && DECL_INITIAL (new_decls) != error_mark_node)
- || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
- {
- if (IDENTIFIER_ERROR_LOCUS (decl) == NULL_TREE)
- error_with_decl (decl, "invalid jump to label `%s'");
- SET_IDENTIFIER_ERROR_LOCUS (decl, current_function_decl);
- error_with_decl (new_decls, "crosses initialization of `%s'");
- }
- new_decls = TREE_CHAIN (new_decls);
- }
- if ((tree)b == TREE_TYPE (uses))
- break;
- b = b->level_chain;
- }
-
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (uses);
- else
- named_label_uses = TREE_CHAIN (uses);
- }
- current_function_return_value = NULL_TREE;
- return decl;
- }
-}
-
-/* Same, but for CASE labels. If DECL is NULL_TREE, it's the default. */
-/* XXX Note decl is never actually used. (bpk) */
-void
-define_case_label (decl)
- tree decl;
-{
- tree cleanup = last_cleanup_this_contour ();
- if (cleanup)
- {
- static int explained = 0;
- error_with_decl (TREE_PURPOSE (cleanup), "destructor needed for `%s'");
- error ("where case label appears here");
- if (!explained)
- {
- error ("(enclose actions of previous case statements requiring");
- error ("destructors in their own binding contours.)");
- explained = 1;
- }
- }
-
- /* After labels, make any new cleanups go into their
- own new (temporary) binding contour. */
-
- current_binding_level->more_cleanups_ok = 0;
- current_function_return_value = NULL_TREE;
-}
-
-/* Return the list of declarations of the current level.
- Note that this list is in reverse order unless/until
- you nreverse it; and when you do nreverse it, you must
- store the result back using `storedecls' or you will lose. */
-
-tree
-getdecls ()
-{
- return current_binding_level->names;
-}
-
-/* Return the list of type-tags (for structs, etc) of the current level. */
-
-tree
-gettags ()
-{
- return current_binding_level->tags;
-}
-
-/* Store the list of declarations of the current level.
- This is done for the parameter declarations of a function being defined,
- after they are modified in the light of any missing parameters. */
-
-static void
-storedecls (decls)
- tree decls;
-{
- current_binding_level->names = decls;
-}
-
-/* Similarly, store the list of tags of the current level. */
-
-static void
-storetags (tags)
- tree tags;
-{
- current_binding_level->tags = tags;
-}
-
-/* Given NAME, an IDENTIFIER_NODE,
- return the structure (or union or enum) definition for that name.
- Searches binding levels from BINDING_LEVEL up to the global level.
- If THISLEVEL_ONLY is nonzero, searches only the specified context
- (but skips any tag-transparent contexts to find one that is
- meaningful for tags).
- FORM says which kind of type the caller wants;
- it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
- If the wrong kind of type is found, and it's not a template, an error is
- reported. */
-
-static tree
-lookup_tag (form, name, binding_level, thislevel_only)
- enum tree_code form;
- struct binding_level *binding_level;
- tree name;
- int thislevel_only;
-{
- register struct binding_level *level;
-
- for (level = binding_level; level; level = level->level_chain)
- {
- register tree tail;
- if (ANON_AGGRNAME_P (name))
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- /* There's no need for error checking here, because
- anon names are unique throughout the compilation. */
- if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
- return TREE_VALUE (tail);
- }
- else
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- if (TREE_PURPOSE (tail) == name)
- {
- enum tree_code code = TREE_CODE (TREE_VALUE (tail));
- /* Should tighten this up; it'll probably permit
- UNION_TYPE and a struct template, for example. */
- if (code != form
- && !(form != ENUMERAL_TYPE
- && (code == TEMPLATE_DECL
- || code == UNINSTANTIATED_P_TYPE)))
-
- {
- /* Definition isn't the kind we were looking for. */
- error ("`%s' defined as wrong kind of tag",
- IDENTIFIER_POINTER (name));
- }
- return TREE_VALUE (tail);
- }
- }
- if (thislevel_only && ! level->tag_transparent)
- return NULL_TREE;
- if (current_class_type && level->level_chain == global_binding_level)
- {
- /* Try looking in this class's tags before heading into
- global binding level. */
- tree context = current_class_type;
- while (context)
- {
- switch (TREE_CODE_CLASS (TREE_CODE (context)))
- {
- case 't':
- {
- tree these_tags = CLASSTYPE_TAGS (context);
- if (ANON_AGGRNAME_P (name))
- while (these_tags)
- {
- if (TYPE_IDENTIFIER (TREE_VALUE (these_tags))
- == name)
- return TREE_VALUE (tail);
- these_tags = TREE_CHAIN (these_tags);
- }
- else
- while (these_tags)
- {
- if (TREE_PURPOSE (these_tags) == name)
- {
- if (TREE_CODE (TREE_VALUE (these_tags)) != form)
- {
- error ("`%s' defined as wrong kind of tag in class scope",
- IDENTIFIER_POINTER (name));
- }
- return TREE_VALUE (tail);
- }
- these_tags = TREE_CHAIN (these_tags);
- }
- /* If this type is not yet complete, then don't
- look at its context. */
- if (TYPE_SIZE (context) == NULL_TREE)
- goto no_context;
- /* Go to next enclosing type, if any. */
- context = DECL_CONTEXT (TYPE_NAME (context));
- break;
- case 'd':
- context = DECL_CONTEXT (context);
- break;
- default:
- my_friendly_abort (10);
- }
- continue;
- }
- no_context:
- break;
- }
- }
- }
- return NULL_TREE;
-}
-
-void
-set_current_level_tags_transparency (tags_transparent)
- int tags_transparent;
-{
- current_binding_level->tag_transparent = tags_transparent;
-}
-
-/* Given a type, find the tag that was defined for it and return the tag name.
- Otherwise return 0. However, the value can never be 0
- in the cases in which this is used.
-
- C++: If NAME is non-zero, this is the new name to install. This is
- done when replacing anonymous tags with real tag names. */
-
-static tree
-lookup_tag_reverse (type, name)
- tree type;
- tree name;
-{
- register struct binding_level *level;
-
- for (level = current_binding_level; level; level = level->level_chain)
- {
- register tree tail;
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- if (TREE_VALUE (tail) == type)
- {
- if (name)
- TREE_PURPOSE (tail) = name;
- return TREE_PURPOSE (tail);
- }
- }
- }
- return NULL_TREE;
-}
-
-/* Given type TYPE which was not declared in C++ language context,
- attempt to find a name by which it is referred. */
-tree
-typedecl_for_tag (tag)
- tree tag;
-{
- struct binding_level *b = current_binding_level;
-
- if (TREE_CODE (TYPE_NAME (tag)) == TYPE_DECL)
- return TYPE_NAME (tag);
-
- while (b)
- {
- tree decls = b->names;
- while (decls)
- {
- if (TREE_CODE (decls) == TYPE_DECL && TREE_TYPE (decls) == tag)
- break;
- decls = TREE_CHAIN (decls);
- }
- if (decls)
- return decls;
- b = b->level_chain;
- }
- return NULL_TREE;
-}
-
-/* Called when we must retroactively globalize a type we previously
- thought needed to be nested. This happens, for example, when
- a `friend class' declaration is seen for an undefined type. */
-
-static void
-globalize_nested_type (type)
- tree type;
-{
- tree t, prev = NULL_TREE, d = TYPE_NAME (type);
- struct binding_level *b;
-
- my_friendly_assert (TREE_CODE (d) == TYPE_DECL, 144);
- /* If the type value has already been globalized, then we're set. */
- if (IDENTIFIER_GLOBAL_VALUE (DECL_NAME (d)) == d)
- return;
- if (IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (d)))
- {
- /* If this type already made it into the global tags,
- silently return. */
- if (value_member (type, global_binding_level->tags))
- return;
- }
-
- set_identifier_type_value (DECL_NESTED_TYPENAME (d), NULL_TREE);
- DECL_NESTED_TYPENAME (d) = DECL_NAME (d);
- DECL_CONTEXT (d) = NULL_TREE;
- if (class_binding_level)
- b = class_binding_level;
- else
- b = current_binding_level;
- while (b != global_binding_level)
- {
- prev = NULL_TREE;
- if (b->parm_flag == 2)
- for (t = b->tags; t != NULL_TREE; prev = t, t = TREE_CHAIN (t))
- if (TREE_VALUE (t) == type)
- goto found;
- b = b->level_chain;
- }
- /* We failed to find this tag anywhere up the binding chains.
- B is now the global binding level... check there. */
- prev = NULL_TREE;
- if (b->parm_flag == 2)
- for (t = b->tags; t != NULL_TREE; prev = t, t = TREE_CHAIN (t))
- if (TREE_VALUE (t) == type)
- goto foundglobal;
- /* It wasn't in global scope either, so this is an anonymous forward ref
- of some kind; let it happen. */
- return;
-
-foundglobal:
- print_node_brief (stderr, "Tried to globalize already-global type ",
- type, 0);
- my_friendly_abort (11);
-
-found:
- /* Pull the tag out of the nested binding contour. */
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (t);
- else
- b->tags = TREE_CHAIN (t);
-
- set_identifier_type_value (TREE_PURPOSE (t), TREE_VALUE (t));
- global_binding_level->tags
- = perm_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t),
- global_binding_level->tags);
-
- /* Pull the tag out of the class's tags (if there).
- It won't show up if it appears e.g. in a parameter declaration
- or definition of a member function of this type. */
- if (current_class_type != NULL_TREE)
- {
- for (t = CLASSTYPE_TAGS (current_class_type), prev = NULL_TREE;
- t != NULL_TREE;
- prev = t, t = TREE_CHAIN (t))
- if (TREE_VALUE (t) == type)
- break;
-
- if (t != NULL_TREE)
- {
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (t);
- else
- CLASSTYPE_TAGS (current_class_type) = TREE_CHAIN (t);
- }
- }
-
- pushdecl_top_level (d);
-}
-
-static void
-maybe_globalize_type (type)
- tree type;
-{
- if ((((TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE)
- && ! TYPE_BEING_DEFINED (type))
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && TYPE_SIZE (type) == NULL_TREE
- /* This part is gross. We keep calling here with types that
- are instantiations of templates, when that type should is
- global, or doesn't have the type decl established yet,
- so globalizing will fail (because it won't find the type in any
- non-global scope). So we short-circuit that path. */
- && !(TYPE_NAME (type) != NULL_TREE
- && TYPE_IDENTIFIER (type) != NULL_TREE
- && ! IDENTIFIER_HAS_TYPE_VALUE (TYPE_IDENTIFIER (type)))
- )
- globalize_nested_type (type);
-}
-
-/* Lookup TYPE in CONTEXT (a chain of nested types or a FUNCTION_DECL).
- Return the type value, or NULL_TREE if not found. */
-static tree
-lookup_nested_type (type, context)
- tree type;
- tree context;
-{
- if (context == NULL_TREE)
- return NULL_TREE;
- while (context)
- {
- switch (TREE_CODE (context))
- {
- case TYPE_DECL:
- {
- tree ctype = TREE_TYPE (context);
- tree match = value_member (type, CLASSTYPE_TAGS (ctype));
- if (match)
- return TREE_VALUE (match);
- context = DECL_CONTEXT (context);
-
- /* When we have a nested class whose member functions have
- local types (e.g., a set of enums), we'll arrive here
- with the DECL_CONTEXT as the actual RECORD_TYPE node for
- the enclosing class. Instead, we want to make sure we
- come back in here with the TYPE_DECL, not the RECORD_TYPE. */
- if (context && TREE_CODE (context) == RECORD_TYPE)
- context = TREE_CHAIN (context);
- }
- break;
- case FUNCTION_DECL:
- return TYPE_IDENTIFIER (type) ? lookup_name (TYPE_IDENTIFIER (type), 1) : NULL_TREE;
- break;
- default:
- my_friendly_abort (12);
- }
- }
- return NULL_TREE;
-}
-
-/* Look up NAME in the current binding level and its superiors in the
- namespace of variables, functions and typedefs. Return a ..._DECL
- node of some kind representing its definition if there is only one
- such declaration, or return a TREE_LIST with all the overloaded
- definitions if there are many, or return 0 if it is undefined.
-
- If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
- If PREFER_TYPE is = 0, we prefer non-TYPE_DECLs.
- If PREFER_TYPE is < 0, we arbitrate according to lexical context. */
-
-tree
-lookup_name (name, prefer_type)
- tree name;
- int prefer_type;
-{
- register tree val;
-
- if (current_binding_level != global_binding_level
- && IDENTIFIER_LOCAL_VALUE (name))
- val = IDENTIFIER_LOCAL_VALUE (name);
- /* In C++ class fields are between local and global scope,
- just before the global scope. */
- else if (current_class_type)
- {
- val = IDENTIFIER_CLASS_VALUE (name);
- if (val == NULL_TREE
- && TYPE_SIZE (current_class_type) == NULL_TREE
- && CLASSTYPE_LOCAL_TYPEDECLS (current_class_type))
- {
- /* Try to find values from base classes
- if we are presently defining a type.
- We are presently only interested in TYPE_DECLs. */
- val = lookup_field (current_class_type, name, 0, prefer_type < 0);
- if (val == error_mark_node)
- return val;
- if (val && TREE_CODE (val) != TYPE_DECL)
- val = NULL_TREE;
- }
-
- /* yylex() calls this with -2, since we should never start digging for
- the nested name at the point where we haven't even, for example,
- created the COMPONENT_REF or anything like that. */
- if (val == NULL_TREE)
- val = lookup_nested_field (name, prefer_type != -2);
-
- if (val == NULL_TREE)
- val = IDENTIFIER_GLOBAL_VALUE (name);
- }
- else
- val = IDENTIFIER_GLOBAL_VALUE (name);
-
- if (val)
- {
- extern int looking_for_typename;
-
- /* Arbitrate between finding a TYPE_DECL and finding
- other kinds of _DECLs. */
- if (TREE_CODE (val) == TYPE_DECL || looking_for_typename < 0)
- return val;
-
- if (IDENTIFIER_HAS_TYPE_VALUE (name))
- {
- register tree val_as_type = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
-
- if (val == val_as_type || prefer_type > 0
- || looking_for_typename > 0)
- return val_as_type;
- if (prefer_type == 0)
- return val;
- return arbitrate_lookup (name, val, val_as_type);
- }
- if (TREE_TYPE (val) == error_mark_node)
- return error_mark_node;
- }
-
- return val;
-}
-
-/* Similar to `lookup_name' but look only at current binding level. */
-
-tree
-lookup_name_current_level (name)
- tree name;
-{
- register tree t;
-
- if (current_binding_level == global_binding_level)
- return IDENTIFIER_GLOBAL_VALUE (name);
-
- if (IDENTIFIER_LOCAL_VALUE (name) == NULL_TREE)
- return 0;
-
- for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
- if (DECL_NAME (t) == name)
- break;
-
- return t;
-}
-
-/* Arrange for the user to get a source line number, even when the
- compiler is going down in flames, so that she at least has a
- chance of working around problems in the compiler. We used to
- call error(), but that let the segmentation fault continue
- through; now, it's much more passive by asking them to send the
- maintainers mail about the problem. */
-
-static void
-sigsegv (sig)
- int sig;
-{
- signal (SIGSEGV, SIG_DFL);
-#ifdef SIGIOT
- signal (SIGIOT, SIG_DFL);
-#endif
-#ifdef SIGILL
- signal (SIGILL, SIG_DFL);
-#endif
-#ifdef SIGABRT
- signal (SIGABRT, SIG_DFL);
-#endif
- my_friendly_abort (0);
-}
-
-/* Array for holding types considered "built-in". These types
- are output in the module in which `main' is defined. */
-static tree *builtin_type_tdescs_arr;
-static int builtin_type_tdescs_len, builtin_type_tdescs_max;
-
-/* Push the declarations of builtin types into the namespace.
- RID_INDEX, if < RID_MAX is the index of the builtin type
- in the array RID_POINTERS. NAME is the name used when looking
- up the builtin type. TYPE is the _TYPE node for the builtin type. */
-
-static void
-record_builtin_type (rid_index, name, type)
- enum rid rid_index;
- char *name;
- tree type;
-{
- tree rname = NULL_TREE, tname = NULL_TREE;
- tree tdecl;
-
- if ((int) rid_index < (int) RID_MAX)
- rname = ridpointers[(int) rid_index];
- if (name)
- tname = get_identifier (name);
-
- if (tname)
- {
-#if 0 /* not yet, should get fixed properly later */
- tdecl = pushdecl (make_type_decl (tname, type));
-#else
- tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
-#endif
- set_identifier_type_value (tname, NULL_TREE);
- if ((int) rid_index < (int) RID_MAX)
- IDENTIFIER_GLOBAL_VALUE (tname) = tdecl;
- }
- if (rname != NULL_TREE)
- {
- if (tname != NULL_TREE)
- {
- set_identifier_type_value (rname, NULL_TREE);
- IDENTIFIER_GLOBAL_VALUE (rname) = tdecl;
- }
- else
- {
-#if 0 /* not yet, should get fixed properly later */
- tdecl = pushdecl (make_type_decl (rname, type));
-#else
- tdecl = pushdecl (build_decl (TYPE_DECL, rname, type));
-#endif
- set_identifier_type_value (rname, NULL_TREE);
- }
- }
-
- if (flag_dossier)
- {
- if (builtin_type_tdescs_len+5 >= builtin_type_tdescs_max)
- {
- builtin_type_tdescs_max *= 2;
- builtin_type_tdescs_arr
- = (tree *)xrealloc (builtin_type_tdescs_arr,
- builtin_type_tdescs_max * sizeof (tree));
- }
- builtin_type_tdescs_arr[builtin_type_tdescs_len++] = type;
- if (TREE_CODE (type) != POINTER_TYPE)
- {
- builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_pointer_type (type);
- builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_type_variant (TYPE_POINTER_TO (type), 1, 0);
- }
- if (TREE_CODE (type) != VOID_TYPE)
- {
- builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_reference_type (type);
- builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_type_variant (TYPE_REFERENCE_TO (type), 1, 0);
- }
- }
-}
-
-static void
-output_builtin_tdesc_entries ()
-{
- extern struct obstack permanent_obstack;
-
- /* If there's more than one main in this file, don't crash. */
- if (builtin_type_tdescs_arr == 0)
- return;
-
- push_obstacks (&permanent_obstack, &permanent_obstack);
- while (builtin_type_tdescs_len > 0)
- {
- tree type = builtin_type_tdescs_arr[--builtin_type_tdescs_len];
- tree tdesc = build_t_desc (type, 0);
- TREE_ASM_WRITTEN (tdesc) = 0;
- build_t_desc (type, 2);
- }
- free (builtin_type_tdescs_arr);
- builtin_type_tdescs_arr = 0;
- pop_obstacks ();
-}
-
-/* Push overloaded decl, in global scope, with one argument so it
- can be used as a callback from define_function. */
-static void
-push_overloaded_decl_1 (x)
- tree x;
-{
- push_overloaded_decl (x, 0);
-}
-
-/* Create the predefined scalar types of C,
- and some nodes representing standard constants (0, 1, (void *)0).
- Initialize the global binding level.
- Make definitions for built-in primitive functions. */
-
-void
-init_decl_processing ()
-{
- tree decl;
- register tree endlink, int_endlink, double_endlink, ptr_endlink;
- tree fields[20];
- /* Either char* or void*. */
- tree traditional_ptr_type_node;
- /* Data type of memcpy. */
- tree memcpy_ftype;
- int wchar_type_size;
-
- /* Have to make these distinct before we try using them. */
- lang_name_cplusplus = get_identifier ("C++");
- lang_name_c = get_identifier ("C");
-
- /* Initially, C. */
- current_lang_name = lang_name_c;
-
- current_function_decl = NULL_TREE;
- named_labels = NULL_TREE;
- named_label_uses = NULL_TREE;
- current_binding_level = NULL_BINDING_LEVEL;
- free_binding_level = NULL_BINDING_LEVEL;
-
- /* Because most segmentation signals can be traced back into user
- code, catch them and at least give the user a chance of working
- around compiler bugs. */
- signal (SIGSEGV, sigsegv);
-
- /* We will also catch aborts in the back-end through sigsegv and give the
- user a chance to see where the error might be, and to defeat aborts in
- the back-end when there have been errors previously in their code. */
-#ifdef SIGIOT
- signal (SIGIOT, sigsegv);
-#endif
-#ifdef SIGILL
- signal (SIGILL, sigsegv);
-#endif
-#ifdef SIGABRT
- signal (SIGABRT, sigsegv);
-#endif
-
- gcc_obstack_init (&decl_obstack);
- if (flag_dossier)
- {
- builtin_type_tdescs_max = 100;
- builtin_type_tdescs_arr = (tree *)xmalloc (100 * sizeof (tree));
- }
-
- /* Must lay these out before anything else gets laid out. */
- error_mark_node = make_node (ERROR_MARK);
- TREE_PERMANENT (error_mark_node) = 1;
- TREE_TYPE (error_mark_node) = error_mark_node;
- error_mark_list = build_tree_list (error_mark_node, error_mark_node);
- TREE_TYPE (error_mark_list) = error_mark_node;
-
- pushlevel (0); /* make the binding_level structure for global names. */
- global_binding_level = current_binding_level;
-
- this_identifier = get_identifier (THIS_NAME);
- in_charge_identifier = get_identifier (IN_CHARGE_NAME);
-
- /* Define `int' and `char' first so that dbx will output them first. */
-
- integer_type_node = make_signed_type (INT_TYPE_SIZE);
- record_builtin_type (RID_INT, NULL_PTR, integer_type_node);
-
- /* Define `char', which is like either `signed char' or `unsigned char'
- but not the same as either. */
-
- char_type_node =
- (flag_signed_char
- ? make_signed_type (CHAR_TYPE_SIZE)
- : make_unsigned_type (CHAR_TYPE_SIZE));
- record_builtin_type (RID_CHAR, "char", char_type_node);
-
- long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
- record_builtin_type (RID_LONG, "long int", long_integer_type_node);
-
- unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
- record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
-
- long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
- record_builtin_type (RID_MAX, "long unsigned int", long_unsigned_type_node);
- record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
-
- /* `unsigned long' is the standard type for sizeof.
- Traditionally, use a signed type.
- Note that stddef.h uses `unsigned long',
- and this must agree, even of long and int are the same size. */
- if (flag_traditional)
- sizetype = long_integer_type_node;
- else
- sizetype
- = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
-
- ptrdiff_type_node
- = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
-
- TREE_TYPE (TYPE_SIZE (integer_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (char_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (unsigned_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (long_unsigned_type_node)) = sizetype;
- TREE_TYPE (TYPE_SIZE (long_integer_type_node)) = sizetype;
-
- short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
- record_builtin_type (RID_SHORT, "short int", short_integer_type_node);
- long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
- record_builtin_type (RID_MAX, "long long int", long_long_integer_type_node);
- short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
- record_builtin_type (RID_MAX, "short unsigned int", short_unsigned_type_node);
- record_builtin_type (RID_MAX, "unsigned short", short_unsigned_type_node);
- long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
- record_builtin_type (RID_MAX, "long long unsigned int", long_long_unsigned_type_node);
- record_builtin_type (RID_MAX, "long long unsigned", long_long_unsigned_type_node);
-
- /* Define both `signed char' and `unsigned char'. */
- signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
- record_builtin_type (RID_MAX, "signed char", signed_char_type_node);
- unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
- record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node);
-
- /* These are types that type_for_size and type_for_mode use. */
- intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
- intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node));
- intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
- intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
- unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
- unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node));
- unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
- unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
-
- float_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
- record_builtin_type (RID_FLOAT, NULL, float_type_node);
- layout_type (float_type_node);
-
- double_type_node = make_node (REAL_TYPE);
- if (flag_short_double)
- TYPE_PRECISION (double_type_node) = FLOAT_TYPE_SIZE;
- else
- TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
- record_builtin_type (RID_DOUBLE, NULL, double_type_node);
- layout_type (double_type_node);
-
- long_double_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
- record_builtin_type (RID_MAX, "long double", long_double_type_node);
- layout_type (long_double_type_node);
-
- integer_zero_node = build_int_2 (0, 0);
- TREE_TYPE (integer_zero_node) = integer_type_node;
- integer_one_node = build_int_2 (1, 0);
- TREE_TYPE (integer_one_node) = integer_type_node;
- integer_two_node = build_int_2 (2, 0);
- TREE_TYPE (integer_two_node) = integer_type_node;
- integer_three_node = build_int_2 (3, 0);
- TREE_TYPE (integer_three_node) = integer_type_node;
- empty_init_node = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);
-
- /* These are needed by stor-layout.c. */
- size_zero_node = size_int (0);
- size_one_node = size_int (1);
-
- void_type_node = make_node (VOID_TYPE);
- record_builtin_type (RID_VOID, NULL, void_type_node);
- layout_type (void_type_node); /* Uses integer_zero_node. */
- void_list_node = build_tree_list (NULL_TREE, void_type_node);
- TREE_PARMLIST (void_list_node) = 1;
-
- null_pointer_node = build_int_2 (0, 0);
- TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
- layout_type (TREE_TYPE (null_pointer_node));
-
- /* Used for expressions that do nothing, but are not errors. */
- void_zero_node = build_int_2 (0, 0);
- TREE_TYPE (void_zero_node) = void_type_node;
-
- string_type_node = build_pointer_type (char_type_node);
- const_string_type_node = build_pointer_type (build_type_variant (char_type_node, 1, 0));
- record_builtin_type (RID_MAX, NULL, string_type_node);
-
- /* make a type for arrays of 256 characters.
- 256 is picked randomly because we have a type for integers from 0 to 255.
- With luck nothing will ever really depend on the length of this
- array type. */
- char_array_type_node
- = build_array_type (char_type_node, unsigned_char_type_node);
- /* Likewise for arrays of ints. */
- int_array_type_node
- = build_array_type (integer_type_node, unsigned_char_type_node);
-
- /* This is just some anonymous class type. Nobody should ever
- need to look inside this envelope. */
- class_star_type_node = build_pointer_type (make_lang_type (RECORD_TYPE));
-
- default_function_type
- = build_function_type (integer_type_node, NULL_TREE);
- build_pointer_type (default_function_type);
-
- ptr_type_node = build_pointer_type (void_type_node);
- const_ptr_type_node = build_pointer_type (build_type_variant (void_type_node, 1, 0));
- record_builtin_type (RID_MAX, NULL, ptr_type_node);
- endlink = void_list_node;
- int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
- double_endlink = tree_cons (NULL_TREE, double_type_node, endlink);
- ptr_endlink = tree_cons (NULL_TREE, ptr_type_node, endlink);
-
- double_ftype_double
- = build_function_type (double_type_node, double_endlink);
-
- double_ftype_double_double
- = build_function_type (double_type_node,
- tree_cons (NULL_TREE, double_type_node, double_endlink));
-
- int_ftype_int
- = build_function_type (integer_type_node, int_endlink);
-
- long_ftype_long
- = build_function_type (long_integer_type_node,
- tree_cons (NULL_TREE, long_integer_type_node, endlink));
-
- void_ftype_ptr_ptr_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- int_endlink)));
-
- int_ftype_cptr_cptr_sizet
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
-
- void_ftype_ptr_int_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- int_endlink)));
-
- string_ftype_ptr_ptr /* strcpy prototype */
- = build_function_type (string_type_node,
- tree_cons (NULL_TREE, string_type_node,
- tree_cons (NULL_TREE,
- const_string_type_node,
- endlink)));
-
- int_ftype_string_string /* strcmp prototype */
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, const_string_type_node,
- tree_cons (NULL_TREE,
- const_string_type_node,
- endlink)));
-
- sizet_ftype_string /* strlen prototype */
- = build_function_type (sizetype,
- tree_cons (NULL_TREE, const_string_type_node,
- endlink));
-
- traditional_ptr_type_node
- = (flag_traditional ? string_type_node : ptr_type_node);
-
- memcpy_ftype /* memcpy prototype */
- = build_function_type (traditional_ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
-
-#ifdef VTABLE_USES_MASK
- /* This is primarily for virtual function definition. We
- declare an array of `void *', which can later be
- converted to the appropriate function pointer type.
- To do pointers to members, we need a mask which can
- distinguish an index value into a virtual function table
- from an address. */
- vtbl_mask = build_int_2 (~((HOST_WIDE_INT) VINDEX_MAX - 1), -1);
-#endif
-
- vtbl_type_node
- = build_array_type (ptr_type_node, NULL_TREE);
- layout_type (vtbl_type_node);
- vtbl_type_node = build_type_variant (vtbl_type_node, 1, 0);
- record_builtin_type (RID_MAX, NULL, vtbl_type_node);
-
- builtin_function ("__builtin_constant_p", int_ftype_int,
- BUILT_IN_CONSTANT_P, NULL_PTR);
-
- builtin_function ("__builtin_alloca",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)),
- BUILT_IN_ALLOCA, "alloca");
-#if 0
- builtin_function ("alloca",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)),
- BUILT_IN_ALLOCA, NULL_PTR);
-#endif
-
- builtin_function ("__builtin_abs", int_ftype_int,
- BUILT_IN_ABS, NULL_PTR);
- builtin_function ("__builtin_fabs", double_ftype_double,
- BUILT_IN_FABS, NULL_PTR);
- builtin_function ("__builtin_labs", long_ftype_long,
- BUILT_IN_LABS, NULL_PTR);
- builtin_function ("__builtin_ffs", int_ftype_int,
- BUILT_IN_FFS, NULL_PTR);
- builtin_function ("__builtin_fsqrt", double_ftype_double,
- BUILT_IN_FSQRT, NULL_PTR);
- builtin_function ("__builtin_sin", double_ftype_double,
- BUILT_IN_SIN, "sin");
- builtin_function ("__builtin_cos", double_ftype_double,
- BUILT_IN_COS, "cos");
- builtin_function ("__builtin_saveregs",
- build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_SAVEREGS, NULL_PTR);
-/* EXPAND_BUILTIN_VARARGS is obsolete. */
-#if 0
- builtin_function ("__builtin_varargs",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink)),
- BUILT_IN_VARARGS, NULL_PTR);
-#endif
- builtin_function ("__builtin_classify_type", default_function_type,
- BUILT_IN_CLASSIFY_TYPE, NULL_PTR);
- builtin_function ("__builtin_next_arg",
- build_function_type (ptr_type_node, endlink),
- BUILT_IN_NEXT_ARG, NULL_PTR);
- builtin_function ("__builtin_args_info",
- build_function_type (integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink)),
- BUILT_IN_ARGS_INFO, NULL_PTR);
-
- /* Currently under experimentation. */
- builtin_function ("__builtin_memcpy", memcpy_ftype,
- BUILT_IN_MEMCPY, "memcpy");
- builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet,
- BUILT_IN_MEMCMP, "memcmp");
- builtin_function ("__builtin_strcmp", int_ftype_string_string,
- BUILT_IN_STRCMP, "strcmp");
- builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
- BUILT_IN_STRCPY, "strcpy");
- builtin_function ("__builtin_strlen", sizet_ftype_string,
- BUILT_IN_STRLEN, "strlen");
-
- if (!flag_no_builtin)
- {
-#if 0 /* These do not work well with libg++. */
- builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR);
- builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, NULL_PTR);
- builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR);
-#endif
- builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR);
- builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP,
- NULL_PTR);
- builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, NULL_PTR);
- builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, NULL_PTR);
- builtin_function ("strlen", sizet_ftype_string, BUILT_IN_STRLEN, NULL_PTR);
- builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR);
- builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR);
- }
-
-#if 0
- /* Support for these has not been written in either expand_builtin
- or build_function_call. */
- builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, 0);
- builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, 0);
- builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, 0);
- builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, 0);
- builtin_function ("__builtin_fmod", double_ftype_double_double, BUILT_IN_FMOD, 0);
- builtin_function ("__builtin_frem", double_ftype_double_double, BUILT_IN_FREM, 0);
- builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET, 0);
- builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, 0);
- builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, 0);
-#endif
-
- /* C++ extensions */
-
- unknown_type_node = make_node (UNKNOWN_TYPE);
-#if 0 /* not yet, should get fixed properly later */
- pushdecl (make_type_decl (get_identifier ("unknown type"),
- unknown_type_node));
-#else
- decl = pushdecl (build_decl (TYPE_DECL, get_identifier ("unknown type"),
- unknown_type_node));
- /* Make sure the "unknown type" typedecl gets ignored for debug info. */
- DECL_IGNORED_P (decl) = 1;
-#endif
- TYPE_SIZE (unknown_type_node) = TYPE_SIZE (void_type_node);
- TYPE_ALIGN (unknown_type_node) = 1;
- TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node);
- /* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
- TREE_TYPE (unknown_type_node) = unknown_type_node;
- /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same result. */
- TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
- TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
-
- /* This is special for C++ so functions can be overloaded. */
- wchar_type_node
- = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE)));
- wchar_type_size = TYPE_PRECISION (wchar_type_node);
- signed_wchar_type_node = make_signed_type (wchar_type_size);
- unsigned_wchar_type_node = make_unsigned_type (wchar_type_size);
- wchar_type_node
- = TREE_UNSIGNED (wchar_type_node)
- ? unsigned_wchar_type_node
- : signed_wchar_type_node;
- record_builtin_type (RID_WCHAR, "__wchar_t", wchar_type_node);
-
- /* This is for wide string constants. */
- wchar_array_type_node
- = build_array_type (wchar_type_node, unsigned_char_type_node);
-
- /* This is a hack that should go away when we deliver the
- real gc code. */
- if (flag_gc)
- {
- builtin_function ("__gc_main", default_function_type, NOT_BUILT_IN, 0);
- pushdecl (lookup_name (get_identifier ("__gc_main"), 0));
- }
-
- /* Simplify life by making a "vtable_entry_type". Give its
- fields names so that the debugger can use them. */
-
- vtable_entry_type = make_lang_type (RECORD_TYPE);
- fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier (VTABLE_DELTA_NAME), short_integer_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier (VTABLE_INDEX_NAME), short_integer_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier (VTABLE_PFN_NAME), ptr_type_node);
- finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2,
- double_type_node);
-
- /* Make this part of an invisible union. */
- fields[3] = copy_node (fields[2]);
- TREE_TYPE (fields[3]) = short_integer_type_node;
- DECL_NAME (fields[3]) = get_identifier (VTABLE_DELTA2_NAME);
- DECL_MODE (fields[3]) = TYPE_MODE (short_integer_type_node);
- DECL_SIZE (fields[3]) = TYPE_SIZE (short_integer_type_node);
- TREE_UNSIGNED (fields[3]) = 0;
- TREE_CHAIN (fields[2]) = fields[3];
- vtable_entry_type = build_type_variant (vtable_entry_type, 1, 0);
- record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
-
- if (flag_dossier)
- {
- /* Must build __t_desc type. Currently, type descriptors look like this:
-
- struct __t_desc
- {
- const char *name;
- int size;
- int bits;
- struct __t_desc *points_to;
- int ivars_count, meths_count;
- struct __i_desc *ivars[];
- struct __m_desc *meths[];
- struct __t_desc *parents[];
- struct __t_desc *vbases[];
- int offsets[];
- };
-
- ...as per Linton's paper. */
-
- __t_desc_type_node = make_lang_type (RECORD_TYPE);
- __i_desc_type_node = make_lang_type (RECORD_TYPE);
- __m_desc_type_node = make_lang_type (RECORD_TYPE);
- __t_desc_array_type = build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE);
- __i_desc_array_type = build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE);
- __m_desc_array_type = build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE);
-
- fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
- string_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("size"),
- unsigned_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("bits"),
- unsigned_type_node);
- fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("points_to"),
- TYPE_POINTER_TO (__t_desc_type_node));
- fields[4] = build_lang_field_decl (FIELD_DECL,
- get_identifier ("ivars_count"),
- integer_type_node);
- fields[5] = build_lang_field_decl (FIELD_DECL,
- get_identifier ("meths_count"),
- integer_type_node);
- fields[6] = build_lang_field_decl (FIELD_DECL, get_identifier ("ivars"),
- build_pointer_type (__i_desc_array_type));
- fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("meths"),
- build_pointer_type (__m_desc_array_type));
- fields[8] = build_lang_field_decl (FIELD_DECL, get_identifier ("parents"),
- build_pointer_type (__t_desc_array_type));
- fields[9] = build_lang_field_decl (FIELD_DECL, get_identifier ("vbases"),
- build_pointer_type (__t_desc_array_type));
- fields[10] = build_lang_field_decl (FIELD_DECL, get_identifier ("offsets"),
- build_pointer_type (integer_type_node));
- finish_builtin_type (__t_desc_type_node, "__t_desc", fields, 10, integer_type_node);
-
- /* ivar descriptors look like this:
-
- struct __i_desc
- {
- const char *name;
- int offset;
- struct __t_desc *type;
- };
- */
-
- fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
- string_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("offset"),
- integer_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
- TYPE_POINTER_TO (__t_desc_type_node));
- finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2, integer_type_node);
-
- /* method descriptors look like this:
-
- struct __m_desc
- {
- const char *name;
- int vindex;
- struct __t_desc *vcontext;
- struct __t_desc *return_type;
- void (*address)();
- short parm_count;
- short required_parms;
- struct __t_desc *parm_types[];
- };
- */
-
- fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
- string_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("vindex"),
- integer_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("vcontext"),
- TYPE_POINTER_TO (__t_desc_type_node));
- fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("return_type"),
- TYPE_POINTER_TO (__t_desc_type_node));
- fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("address"),
- build_pointer_type (default_function_type));
- fields[5] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_count"),
- short_integer_type_node);
- fields[6] = build_lang_field_decl (FIELD_DECL, get_identifier ("required_parms"),
- short_integer_type_node);
- fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"),
- build_pointer_type (build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE)));
- finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7, integer_type_node);
- }
-
- /* Now, C++. */
- current_lang_name = lang_name_cplusplus;
- if (flag_dossier)
- {
- int i = builtin_type_tdescs_len;
- while (i > 0)
- {
- tree tdesc = build_t_desc (builtin_type_tdescs_arr[--i], 0);
- TREE_ASM_WRITTEN (tdesc) = 1;
- TREE_PUBLIC (TREE_OPERAND (tdesc, 0)) = 1;
- }
- }
-
- auto_function (ansi_opname[(int) NEW_EXPR],
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, sizetype,
- void_list_node)),
- NOT_BUILT_IN);
- auto_function (ansi_opname[(int) DELETE_EXPR],
- build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- void_list_node)),
- NOT_BUILT_IN);
-
- abort_fndecl
- = define_function ("abort",
- build_function_type (void_type_node, void_list_node),
- NOT_BUILT_IN, 0, 0);
-
- unhandled_exception_fndecl
- = define_function ("__unhandled_exception",
- build_function_type (void_type_node, NULL_TREE),
- NOT_BUILT_IN, 0, 0);
-
- /* Perform other language dependent initializations. */
- init_class_processing ();
- init_init_processing ();
- init_search_processing ();
-
- if (flag_handle_exceptions)
- {
- if (flag_handle_exceptions == 2)
- /* Too much trouble to inline all the trys needed for this. */
- flag_this_is_variable = 2;
- init_exception_processing ();
- }
- if (flag_gc)
- init_gc_processing ();
- if (flag_no_inline)
- flag_inline_functions = 0, flag_default_inline = 0;
- if (flag_cadillac)
- init_cadillac ();
-
- /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
- declare_function_name ();
-
- /* Warnings about failure to return values are too valuable to forego. */
- warn_return_type = 1;
-}
-
-/* Make a definition for a builtin function named NAME and whose data type
- is TYPE. TYPE should be a function type with argument types.
- FUNCTION_CODE tells later passes how to compile calls to this function.
- See tree.h for its possible values.
-
- If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. */
-
-tree
-define_function (name, type, function_code, pfn, library_name)
- char *name;
- tree type;
- enum built_in_function function_code;
- void (*pfn)();
- char *library_name;
-{
- tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
- DECL_EXTERNAL (decl) = 1;
- TREE_PUBLIC (decl) = 1;
-
- /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
- we cannot change DECL_ASSEMBLER_NAME until we have installed this
- function in the namespace. */
- if (pfn) (*pfn) (decl);
- if (library_name)
- DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
- make_function_rtl (decl);
- if (function_code != NOT_BUILT_IN)
- {
- DECL_BUILT_IN (decl) = 1;
- DECL_SET_FUNCTION_CODE (decl, function_code);
- }
- return decl;
-}
-
-/* Called when a declaration is seen that contains no names to declare.
- If its type is a reference to a structure, union or enum inherited
- from a containing scope, shadow that tag name for the current scope
- with a forward reference.
- If its type defines a new named structure or union
- or defines an enum, it is valid but we need not do anything here.
- Otherwise, it is an error.
-
- C++: may have to grok the declspecs to learn about static,
- complain for anonymous unions. */
-
-void
-shadow_tag (declspecs)
- tree declspecs;
-{
- int found_tag = 0;
- int warned = 0;
- register tree link;
- register enum tree_code code, ok_code = ERROR_MARK;
- register tree t = NULL_TREE;
-
- for (link = declspecs; link; link = TREE_CHAIN (link))
- {
- register tree value = TREE_VALUE (link);
-
- code = TREE_CODE (value);
- if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
- /* Used to test also that TYPE_SIZE (value) != 0.
- That caused warning for `struct foo;' at top level in the file. */
- {
- register tree name = TYPE_NAME (value);
-
- if (name == NULL_TREE)
- name = lookup_tag_reverse (value, NULL_TREE);
-
- if (name && TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
-
- if (class_binding_level)
- t = lookup_tag (code, name, class_binding_level, 1);
- else
- t = lookup_tag (code, name, current_binding_level, 1);
-
- if (t == NULL_TREE)
- {
- push_obstacks (&permanent_obstack, &permanent_obstack);
- if (IS_AGGR_TYPE_CODE (code))
- t = make_lang_type (code);
- else
- t = make_node (code);
- pushtag (name, t);
- pop_obstacks ();
- ok_code = code;
- break;
- }
- else if (name != NULL_TREE || code == ENUMERAL_TYPE)
- ok_code = code;
-
- if (ok_code != ERROR_MARK)
- found_tag++;
- else
- {
- if (!warned)
- pedwarn ("useless keyword or type name in declaration");
- warned = 1;
- }
- }
- }
-
- /* This is where the variables in an anonymous union are
- declared. An anonymous union declaration looks like:
- union { ... } ;
- because there is no declarator after the union, the parser
- sends that declaration here. */
- if (ok_code == UNION_TYPE
- && t != NULL_TREE
- && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (TYPE_NAME (t)))
- || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
- {
- /* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
- function members. */
- if (TYPE_FIELDS (t))
- {
- tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, NULL_TREE);
- finish_anon_union (decl);
- }
- else
- error ("anonymous union cannot have a function member");
- }
- else if (ok_code == RECORD_TYPE
- && found_tag == 1
- && TYPE_LANG_SPECIFIC (t)
- && CLASSTYPE_DECLARED_EXCEPTION (t))
- {
- if (TYPE_SIZE (t))
- error_with_aggr_type (t, "redeclaration of exception `%s'");
- else
- {
- tree ename, decl;
-
- push_obstacks (&permanent_obstack, &permanent_obstack);
-
- pushclass (t, 0);
- finish_exception (t, NULL_TREE);
-
- ename = TYPE_NAME (t);
- if (TREE_CODE (ename) == TYPE_DECL)
- ename = DECL_NAME (ename);
- decl = build_lang_field_decl (VAR_DECL, ename, t);
- finish_exception_decl (current_class_name, decl);
- end_exception_decls ();
-
- pop_obstacks ();
- }
- }
- else if (!warned && found_tag > 1)
- warning ("multiple types in one declaration");
-}
-
-/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
-
-tree
-groktypename (typename)
- tree typename;
-{
- if (TREE_CODE (typename) != TREE_LIST)
- return typename;
- return grokdeclarator (TREE_VALUE (typename),
- TREE_PURPOSE (typename),
- TYPENAME, 0, NULL_TREE);
-}
-
-/* Decode a declarator in an ordinary declaration or data definition.
- This is called as soon as the type information and variable name
- have been parsed, before parsing the initializer if any.
- Here we create the ..._DECL node, fill in its type,
- and put it on the list of decls for the current context.
- The ..._DECL node is returned as the value.
-
- Exception: for arrays where the length is not specified,
- the type is left null, to be filled in by `finish_decl'.
-
- Function definitions do not come here; they go to start_function
- instead. However, external and forward declarations of functions
- do go through here. Structure field declarations are done by
- grokfield and not through here. */
-
-/* Set this to zero to debug not using the temporary obstack
- to parse initializers. */
-int debug_temp_inits = 1;
-
-tree
-start_decl (declarator, declspecs, initialized, raises)
- tree declspecs, declarator;
- int initialized;
- tree raises;
-{
- register tree decl;
- register tree type, tem;
- tree context;
- extern int have_extern_spec;
- extern int used_extern_spec;
-
- int init_written = initialized;
-
- /* This should only be done once on the top most decl. */
- if (have_extern_spec && !used_extern_spec)
- {
- declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
- used_extern_spec = 1;
- }
-
- decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises);
- if (decl == NULL_TREE || decl == void_type_node)
- return NULL_TREE;
-
- type = TREE_TYPE (decl);
-
- /* Don't lose if destructors must be executed at file-level. */
- if (TREE_STATIC (decl)
- && TYPE_NEEDS_DESTRUCTOR (type)
- && !TREE_PERMANENT (decl))
- {
- push_obstacks (&permanent_obstack, &permanent_obstack);
- decl = copy_node (decl);
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree itype = TYPE_DOMAIN (type);
- if (itype && ! TREE_PERMANENT (itype))
- {
- itype = build_index_type (copy_to_permanent (TYPE_MAX_VALUE (itype)));
- type = build_cplus_array_type (TREE_TYPE (type), itype);
- TREE_TYPE (decl) = type;
- }
- }
- pop_obstacks ();
- }
-
- /* Interesting work for this is done in `finish_exception_decl'. */
- if (TREE_CODE (type) == RECORD_TYPE
- && CLASSTYPE_DECLARED_EXCEPTION (type))
- return decl;
-
- /* Corresponding pop_obstacks is done in `finish_decl'. */
- push_obstacks_nochange ();
-
- context
- = (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
- ? DECL_CLASS_CONTEXT (decl)
- : DECL_CONTEXT (decl);
-
- if (processing_template_decl)
- {
- tree d;
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- /* Declarator is a call_expr; extract arguments from it, since
- grokdeclarator didn't do it. */
- tree args;
- args = copy_to_permanent (last_function_parms);
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- {
- tree t = TREE_TYPE (decl);
- tree decl;
-
- t = TYPE_METHOD_BASETYPE (t); /* type method belongs to */
- if (TREE_CODE (t) != UNINSTANTIATED_P_TYPE)
- {
- t = build_pointer_type (t); /* base type of `this' */
-#if 1
- /* I suspect this is wrong. */
- t = build_type_variant (t, flag_this_is_variable <= 0,
- 0); /* type of `this' */
-#else
- t = build_type_variant (t, 0, 0); /* type of `this' */
-#endif
- t = build (PARM_DECL, t, this_identifier);
- TREE_CHAIN (t) = args;
- args = t;
- }
- }
- DECL_ARGUMENTS (decl) = args;
- }
- d = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), TREE_TYPE (decl));
- TREE_PUBLIC (d) = TREE_PUBLIC (decl) = 0;
- TREE_STATIC (d) = TREE_STATIC (decl);
- DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl)
- && !(context && !DECL_THIS_EXTERN (decl)));
- DECL_TEMPLATE_RESULT (d) = decl;
- DECL_OVERLOADED (d) = 1;
- decl = d;
- }
-
- if (context && TYPE_SIZE (context) != NULL_TREE)
- {
- /* If it was not explicitly declared `extern',
- revoke any previous claims of DECL_EXTERNAL. */
- if (DECL_THIS_EXTERN (decl) == 0)
- DECL_EXTERNAL (decl) = 0;
- if (DECL_LANG_SPECIFIC (decl))
- DECL_IN_AGGR_P (decl) = 0;
- pushclass (context, 2);
- }
-
- /* If this type of object needs a cleanup, and control may
- jump past it, make a new binding level so that it is cleaned
- up only when it is initialized first. */
- if (TYPE_NEEDS_DESTRUCTOR (type)
- && current_binding_level->more_cleanups_ok == 0)
- pushlevel_temporary (1);
-
- if (initialized)
- /* Is it valid for this decl to have an initializer at all?
- If not, set INITIALIZED to zero, which will indirectly
- tell `finish_decl' to ignore the initializer once it is parsed. */
- switch (TREE_CODE (decl))
- {
- case TYPE_DECL:
- /* typedef foo = bar means give foo the same type as bar.
- We haven't parsed bar yet, so `finish_decl' will fix that up.
- Any other case of an initialization in a TYPE_DECL is an error. */
- if (pedantic || list_length (declspecs) > 1)
- {
- error ("typedef `%s' is initialized",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- initialized = 0;
- }
- break;
-
- case FUNCTION_DECL:
- error ("function `%s' is initialized like a variable",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- initialized = 0;
- break;
-
- default:
- /* Don't allow initializations for incomplete types
- except for arrays which might be completed by the initialization. */
- if (TYPE_SIZE (type) != NULL_TREE)
- ; /* A complete type is ok. */
- else if (TREE_CODE (type) != ARRAY_TYPE)
- {
- error ("variable `%s' has initializer but incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- initialized = 0;
- }
- else if (TYPE_SIZE (TREE_TYPE (type)) == NULL_TREE)
- {
- error ("elements of array `%s' have incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- initialized = 0;
- }
- }
-
- if (!initialized
- && TREE_CODE (decl) != TYPE_DECL
- && TREE_CODE (decl) != TEMPLATE_DECL
- && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl))
- {
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- error ("aggregate `%s' has incomplete type and cannot be initialized",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- /* Change the type so that assemble_variable will give
- DECL an rtl we can live with: (mem (const_int 0)). */
- TREE_TYPE (decl) = error_mark_node;
- type = error_mark_node;
- }
- else
- {
- /* If any base type in the hierarchy of TYPE needs a constructor,
- then we set initialized to 1. This way any nodes which are
- created for the purposes of initializing this aggregate
- will live as long as it does. This is necessary for global
- aggregates which do not have their initializers processed until
- the end of the file. */
- initialized = TYPE_NEEDS_CONSTRUCTING (type);
- }
- }
-
- if (initialized)
- {
- if (current_binding_level != global_binding_level
- && DECL_EXTERNAL (decl))
- warning ("declaration of `%s' has `extern' and is initialized",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- DECL_EXTERNAL (decl) = 0;
- if (current_binding_level == global_binding_level)
- TREE_STATIC (decl) = 1;
-
- /* Tell `pushdecl' this is an initialized decl
- even though we don't yet have the initializer expression.
- Also tell `finish_decl' it may store the real initializer. */
- DECL_INITIAL (decl) = error_mark_node;
- }
-
- /* Add this decl to the current binding level, but not if it
- comes from another scope, e.g. a static member variable.
- TEM may equal DECL or it may be a previous decl of the same name. */
- if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE)
- || (TREE_CODE (decl) == TEMPLATE_DECL && !global_bindings_p ())
- || TREE_CODE (type) == LANG_TYPE)
- tem = decl;
- else
- {
- tem = pushdecl (decl);
- if (TREE_CODE (tem) == TREE_LIST)
- {
- tree tem2 = value_member (decl, tem);
- if (tem2 != NULL_TREE)
- tem = TREE_VALUE (tem2);
- else
- {
- while (tem && ! decls_match (decl, TREE_VALUE (tem)))
- tem = TREE_CHAIN (tem);
- if (tem == NULL_TREE)
- tem = decl;
- else
- tem = TREE_VALUE (tem);
- }
- }
- }
-
-#if 0
- /* We don't do this yet for GNU C++. */
- /* For a local variable, define the RTL now. */
- if (current_binding_level != global_binding_level
- /* But not if this is a duplicate decl
- and we preserved the rtl from the previous one
- (which may or may not happen). */
- && DECL_RTL (tem) == NULL_RTX)
- {
- if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE)
- expand_decl (tem);
- else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
- && DECL_INITIAL (tem) != NULL_TREE)
- expand_decl (tem);
- }
-#endif
-
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_OVERLOADED (decl))
- /* @@ Also done in start_function. */
- tem = push_overloaded_decl (tem, 1);
- else if (TREE_CODE (decl) == TEMPLATE_DECL)
- {
- tree result = DECL_TEMPLATE_RESULT (decl);
- if (DECL_CONTEXT (result) != NULL_TREE)
- {
- tree type;
- type = DECL_CONTEXT (result);
- my_friendly_assert (TREE_CODE (type) == UNINSTANTIATED_P_TYPE, 145);
- if (/* TREE_CODE (result) == VAR_DECL */ 1)
- {
-#if 0
- tree tmpl = UPT_TEMPLATE (type);
-
- fprintf (stderr, "%s:%d: adding ", __FILE__, __LINE__);
- print_node_brief (stderr, "", DECL_NAME (tem), 0);
- fprintf (stderr, " to class %s\n",
- IDENTIFIER_POINTER (DECL_NAME (tmpl)));
- DECL_TEMPLATE_MEMBERS (tmpl)
- = perm_tree_cons (DECL_NAME (tem), tem,
- DECL_TEMPLATE_MEMBERS (tmpl));
-#endif
- return tem;
- }
- my_friendly_abort (13);
- }
- else if (TREE_CODE (result) == FUNCTION_DECL)
- tem = push_overloaded_decl (tem, 0);
- else if (TREE_CODE (result) == VAR_DECL
- || TREE_CODE (result) == TYPE_DECL)
- {
- error ("invalid template `%s'",
- IDENTIFIER_POINTER (DECL_NAME (result)));
- return NULL_TREE;
- }
- else
- my_friendly_abort (14);
- }
-
- if (init_written
- && ! (TREE_CODE (tem) == PARM_DECL
- || (TREE_READONLY (tem)
- && (TREE_CODE (tem) == VAR_DECL
- || TREE_CODE (tem) == FIELD_DECL))))
- {
- /* When parsing and digesting the initializer,
- use temporary storage. Do this even if we will ignore the value. */
- if (current_binding_level == global_binding_level && debug_temp_inits)
- {
- if (TYPE_NEEDS_CONSTRUCTING (type) || TREE_CODE (type) == REFERENCE_TYPE)
- /* In this case, the initializer must lay down in permanent
- storage, since it will be saved until `finish_file' is run. */
- ;
- else
- temporary_allocation ();
- }
- }
-
- if (flag_cadillac)
- cadillac_start_decl (tem);
-
- return tem;
-}
-
-static void
-make_temporary_for_reference (decl, ctor_call, init, cleanupp)
- tree decl, ctor_call, init;
- tree *cleanupp;
-{
- tree type = TREE_TYPE (decl);
- tree target_type = TREE_TYPE (type);
- tree tmp, tmp_addr;
-
- if (ctor_call)
- {
- tmp_addr = TREE_VALUE (TREE_OPERAND (ctor_call, 1));
- if (TREE_CODE (tmp_addr) == NOP_EXPR)
- tmp_addr = TREE_OPERAND (tmp_addr, 0);
- my_friendly_assert (TREE_CODE (tmp_addr) == ADDR_EXPR, 146);
- tmp = TREE_OPERAND (tmp_addr, 0);
- }
- else
- {
- tmp = get_temp_name (target_type,
- current_binding_level == global_binding_level);
- tmp_addr = build_unary_op (ADDR_EXPR, tmp, 0);
- }
-
- TREE_TYPE (tmp_addr) = build_pointer_type (target_type);
- DECL_INITIAL (decl) = convert (TYPE_POINTER_TO (target_type), tmp_addr);
- TREE_TYPE (DECL_INITIAL (decl)) = type;
- if (TYPE_NEEDS_CONSTRUCTING (target_type))
- {
- if (current_binding_level == global_binding_level)
- {
- /* lay this variable out now. Otherwise `output_addressed_constants'
- gets confused by its initializer. */
- make_decl_rtl (tmp, NULL_PTR, 1);
- static_aggregates = perm_tree_cons (init, tmp, static_aggregates);
- }
- else
- {
- if (ctor_call != NULL_TREE)
- init = ctor_call;
- else
- init = build_method_call (tmp, constructor_name (target_type),
- build_tree_list (NULL_TREE, init),
- NULL_TREE, LOOKUP_NORMAL);
- DECL_INITIAL (decl) = build (COMPOUND_EXPR, type, init,
- DECL_INITIAL (decl));
- *cleanupp = maybe_build_cleanup (tmp);
- }
- }
- else
- {
- DECL_INITIAL (tmp) = init;
- TREE_STATIC (tmp) = current_binding_level == global_binding_level;
- finish_decl (tmp, init, 0, 0);
- }
- if (TREE_STATIC (tmp))
- preserve_initializer ();
-}
-
-/* Handle initialization of references.
- These three arguments from from `finish_decl', and have the
- same meaning here that they do there. */
-/* quotes on semantics can be found in ARM 8.4.3. */
-static void
-grok_reference_init (decl, type, init, cleanupp)
- tree decl, type, init;
- tree *cleanupp;
-{
- char *errstr = NULL;
- int is_reference;
- tree tmp;
- tree this_ptr_type, actual_init;
-
- if (init == NULL_TREE)
- {
- if (DECL_LANG_SPECIFIC (decl) == 0
- || DECL_IN_AGGR_P (decl) == 0)
- {
- error ("variable declared as reference not initialized");
- if (TREE_CODE (decl) == VAR_DECL)
- SET_DECL_REFERENCE_SLOT (decl, error_mark_node);
- }
- return;
- }
-
- if (TREE_CODE (init) == TREE_LIST)
- init = build_compound_expr (init);
- is_reference = TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE;
- tmp = is_reference ? convert_from_reference (init) : init;
-
- if (is_reference)
- {
- if (! comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
- TYPE_MAIN_VARIANT (TREE_TYPE (tmp)), 0))
- errstr = "initialization of `%s' from dissimilar reference type";
- else if (TYPE_READONLY (TREE_TYPE (type))
- >= TYPE_READONLY (TREE_TYPE (TREE_TYPE (init))))
- {
- is_reference = 0;
- init = tmp;
- }
- }
- else
- {
- if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
- && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
- {
- /* Note: default conversion is only called in very
- special cases. */
- init = default_conversion (init);
- }
- if (TREE_CODE (TREE_TYPE (type)) == TREE_CODE (TREE_TYPE (init)))
- {
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
- TYPE_MAIN_VARIANT (TREE_TYPE (init)), 0))
- {
- /* This section implements ANSI C++ June 5 1992 WP 8.4.3.5. */
-
- /* A reference to a volatile T cannot be initialized with
- a const T, and vice-versa. */
- if (TYPE_VOLATILE (TREE_TYPE (type)) && TREE_READONLY (init))
- errstr = "cannot initialize a reference to a volatile T with a const T";
- else if (TYPE_READONLY (TREE_TYPE (type)) && TREE_THIS_VOLATILE (init))
- errstr = "cannot initialize a reference to a const T with a volatile T";
- /* A reference to a plain T can be initialized only with
- a plain T. */
- else if (!TYPE_VOLATILE (TREE_TYPE (type))
- && !TYPE_READONLY (TREE_TYPE (type)))
- {
- if (TREE_READONLY (init))
- errstr = "cannot initialize a reference to T with a const T";
- else if (TREE_THIS_VOLATILE (init))
- errstr = "cannot initialize a reference to T with a volatile T";
- }
- }
- else
- init = convert (TREE_TYPE (type), init);
- }
- else if (init != error_mark_node
- && ! comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
- TYPE_MAIN_VARIANT (TREE_TYPE (init)), 0))
- errstr = "invalid type conversion for reference";
- }
-
- if (errstr)
- {
- /* Things did not go smoothly; look for operator& type conversion. */
- if (IS_AGGR_TYPE (TREE_TYPE (tmp)))
- {
- tmp = build_type_conversion (CONVERT_EXPR, type, init, 0);
- if (tmp != NULL_TREE)
- {
- init = tmp;
- if (tmp == error_mark_node)
- errstr = "ambiguous pointer conversion";
- else
- errstr = NULL;
- is_reference = 1;
- }
- else
- {
- tmp = build_type_conversion (CONVERT_EXPR, TREE_TYPE (type), init, 0);
- if (tmp != NULL_TREE)
- {
- init = tmp;
- if (tmp == error_mark_node)
- errstr = "ambiguous pointer conversion";
- else
- errstr = NULL;
- is_reference = 0;
- }
- }
- }
- /* Look for constructor. */
- else if (IS_AGGR_TYPE (TREE_TYPE (type))
- && TYPE_HAS_CONSTRUCTOR (TREE_TYPE (type)))
- {
- tmp = get_temp_name (TREE_TYPE (type),
- current_binding_level == global_binding_level);
- tmp = build_method_call (tmp, constructor_name (TREE_TYPE (type)),
- build_tree_list (NULL_TREE, init),
- NULL_TREE, LOOKUP_NORMAL);
- if (tmp == NULL_TREE || tmp == error_mark_node)
- {
- if (TREE_CODE (decl) == VAR_DECL)
- SET_DECL_REFERENCE_SLOT (decl, error_mark_node);
- error_with_decl (decl, "constructor failed to build reference initializer");
- return;
- }
- make_temporary_for_reference (decl, tmp, init, cleanupp);
- goto done;
- }
- }
-
- if (errstr)
- {
- error_with_decl (decl, errstr);
- if (TREE_CODE (decl) == VAR_DECL)
- SET_DECL_REFERENCE_SLOT (decl, error_mark_node);
- return;
- }
-
- /* In the case of initialization, it is permissible
- to assign one reference to another. */
- this_ptr_type = build_pointer_type (TREE_TYPE (type));
-
- if (is_reference)
- {
- if (TREE_SIDE_EFFECTS (init))
- DECL_INITIAL (decl) = save_expr (init);
- else
- DECL_INITIAL (decl) = init;
- }
- else if (lvalue_p (init))
- {
- tmp = build_unary_op (ADDR_EXPR, init, 0);
- if (TREE_CODE (tmp) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (tmp, 0)) == WITH_CLEANUP_EXPR)
- {
- /* Associate the cleanup with the reference so that we
- don't get burned by "aggressive" cleanup policy. */
- *cleanupp = TREE_OPERAND (TREE_OPERAND (tmp, 0), 2);
- TREE_OPERAND (TREE_OPERAND (tmp, 0), 2) = error_mark_node;
- }
- if (IS_AGGR_TYPE (TREE_TYPE (this_ptr_type)))
- DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), tmp);
- else
- DECL_INITIAL (decl) = convert (this_ptr_type, tmp);
-
- DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
- if (DECL_INITIAL (decl) == current_class_decl)
- DECL_INITIAL (decl) = copy_node (current_class_decl);
- TREE_TYPE (DECL_INITIAL (decl)) = type;
- }
- else if ((actual_init = unary_complex_lvalue (ADDR_EXPR, init)))
- {
- /* The initializer for this decl goes into its
- DECL_REFERENCE_SLOT. Make sure that we can handle
- multiple evaluations without ill effect. */
- if (TREE_CODE (actual_init) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (actual_init, 0)) == TARGET_EXPR)
- actual_init = save_expr (actual_init);
- DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), actual_init);
- DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
- TREE_TYPE (DECL_INITIAL (decl)) = type;
- }
- else if (TYPE_READONLY (TREE_TYPE (type)))
- /* Section 8.4.3 allows us to make a temporary for
- the initialization of const&. */
- make_temporary_for_reference (decl, NULL_TREE, init, cleanupp);
- else
- {
- error_with_decl (decl, "type mismatch in initialization of `%s' (use `const')");
- DECL_INITIAL (decl) = error_mark_node;
- }
-
- done:
- /* ?? Can this be optimized in some cases to
- hand back the DECL_INITIAL slot?? */
- if (TYPE_SIZE (TREE_TYPE (type)))
- {
- init = convert_from_reference (decl);
- if (TREE_PERMANENT (decl))
- init = copy_to_permanent (init);
- SET_DECL_REFERENCE_SLOT (decl, init);
- }
-
- if (TREE_STATIC (decl) && ! TREE_CONSTANT (DECL_INITIAL (decl)))
- {
- expand_static_init (decl, DECL_INITIAL (decl));
- DECL_INITIAL (decl) = NULL_TREE;
- }
-}
-
-/* Finish processing of a declaration;
- install its line number and initial value.
- If the length of an array type is not known before,
- it must be determined now, from the initial value, or it is an error.
-
- Call `pop_obstacks' iff NEED_POP is nonzero.
-
- For C++, `finish_decl' must be fairly evasive: it must keep initializers
- for aggregates that have constructors alive on the permanent obstack,
- so that the global initializing functions can be written at the end.
-
- INIT0 holds the value of an initializer that should be allowed to escape
- the normal rules.
-
- For functions that take default parameters, DECL points to its
- "maximal" instantiation. `finish_decl' must then also declared its
- subsequently lower and lower forms of instantiation, checking for
- ambiguity as it goes. This can be sped up later. */
-
-void
-finish_decl (decl, init, asmspec_tree, need_pop)
- tree decl, init;
- tree asmspec_tree;
- int need_pop;
-{
- register tree type;
- tree cleanup = NULL_TREE, ttype;
- int was_incomplete;
- int temporary = allocation_temporary_p ();
- char *asmspec = NULL;
- int was_readonly = 0;
-
- /* If this is 0, then we did not change obstacks. */
- if (! decl)
- {
- if (init)
- error ("assignment (not initialization) in declaration");
- return;
- }
-
- if (asmspec_tree)
- {
- asmspec = TREE_STRING_POINTER (asmspec_tree);
- /* Zero out old RTL, since we will rewrite it. */
- DECL_RTL (decl) = NULL_RTX;
- }
-
- /* If the type of the thing we are declaring either has
- a constructor, or has a virtual function table pointer,
- AND its initialization was accepted by `start_decl',
- then we stayed on the permanent obstack through the
- declaration, otherwise, changed obstacks as GCC would. */
-
- type = TREE_TYPE (decl);
-
- was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
-
- /* Take care of TYPE_DECLs up front. */
- if (TREE_CODE (decl) == TYPE_DECL)
- {
- if (init && DECL_INITIAL (decl))
- {
- /* typedef foo = bar; store the type of bar as the type of foo. */
- TREE_TYPE (decl) = type = TREE_TYPE (init);
- DECL_INITIAL (decl) = init = NULL_TREE;
- }
- if (IS_AGGR_TYPE (type) && DECL_NAME (decl))
- {
- if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
- warning ("shadowing previous type declaration of `%s'",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- set_identifier_type_value (DECL_NAME (decl), type);
- CLASSTYPE_GOT_SEMICOLON (type) = 1;
- }
- GNU_xref_decl (current_function_decl, decl);
- rest_of_decl_compilation (decl, NULL_PTR,
- DECL_CONTEXT (decl) == NULL_TREE, 0);
- goto finish_end;
- }
- if (type != error_mark_node && IS_AGGR_TYPE (type)
- && CLASSTYPE_DECLARED_EXCEPTION (type))
- {
- finish_exception_decl (NULL_TREE, decl);
- CLASSTYPE_GOT_SEMICOLON (type) = 1;
- goto finish_end;
- }
- if (TREE_CODE (decl) != FUNCTION_DECL)
- {
- ttype = target_type (type);
-#if 0 /* WTF? -KR
- Leave this out until we can figure out why it was
- needed/desirable in the first place. Then put a comment
- here explaining why. Or just delete the code if no ill
- effects arise. */
- if (TYPE_NAME (ttype)
- && TREE_CODE (TYPE_NAME (ttype)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (ttype)))
- {
- tree old_id = TYPE_IDENTIFIER (ttype);
- char *newname = (char *)alloca (IDENTIFIER_LENGTH (old_id) + 2);
- /* Need to preserve template data for UPT nodes. */
- tree old_template = IDENTIFIER_TEMPLATE (old_id);
- newname[0] = '_';
- bcopy (IDENTIFIER_POINTER (old_id), newname + 1,
- IDENTIFIER_LENGTH (old_id) + 1);
- old_id = get_identifier (newname);
- lookup_tag_reverse (ttype, old_id);
- TYPE_IDENTIFIER (ttype) = old_id;
- IDENTIFIER_TEMPLATE (old_id) = old_template;
- }
-#endif
- }
-
- if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
- && TYPE_NEEDS_CONSTRUCTING (type))
- {
-
- /* Currently, GNU C++ puts constants in text space, making them
- impossible to initialize. In the future, one would hope for
- an operating system which understood the difference between
- initialization and the running of a program. */
- was_readonly = 1;
- TREE_READONLY (decl) = 0;
- }
-
- if (TREE_CODE (decl) == FIELD_DECL)
- {
- if (init && init != error_mark_node)
- my_friendly_assert (TREE_PERMANENT (init), 147);
-
- if (asmspec)
- {
- /* This must override the asm specifier which was placed
- by grokclassfn. Lay this out fresh.
-
- @@ Should emit an error if this redefines an asm-specified
- @@ name, or if we have already used the function's name. */
- DECL_RTL (TREE_TYPE (decl)) = NULL_RTX;
- DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
- make_decl_rtl (decl, asmspec, 0);
- }
- }
- /* If `start_decl' didn't like having an initialization, ignore it now. */
- else if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
- init = NULL_TREE;
- else if (DECL_EXTERNAL (decl))
- ;
- else if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- grok_reference_init (decl, type, init, &cleanup);
- init = NULL_TREE;
- }
-
- GNU_xref_decl (current_function_decl, decl);
-
- if (TREE_CODE (decl) == FIELD_DECL || DECL_EXTERNAL (decl))
- ;
- else if (TREE_CODE (decl) == CONST_DECL)
- {
- my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148);
-
- DECL_INITIAL (decl) = init;
-
- /* This will keep us from needing to worry about our obstacks. */
- my_friendly_assert (init != NULL_TREE, 149);
- init = NULL_TREE;
- }
- else if (init)
- {
- if (TYPE_NEEDS_CONSTRUCTING (type))
- {
- if (TREE_CODE (type) == ARRAY_TYPE)
- init = digest_init (type, init, (tree *) 0);
- else if (TREE_CODE (init) == CONSTRUCTOR
- && CONSTRUCTOR_ELTS (init) != NULL_TREE)
- {
- error_with_decl (decl, "`%s' must be initialized by constructor, not by `{...}'");
- init = error_mark_node;
- }
-#if 0
- /* fix this in `build_functional_cast' instead.
- Here's the trigger code:
-
- struct ostream
- {
- ostream ();
- ostream (int, char *);
- ostream (char *);
- operator char *();
- ostream (void *);
- operator void *();
- operator << (int);
- };
- int buf_size = 1024;
- static char buf[buf_size];
- const char *debug(int i) {
- char *b = &buf[0];
- ostream o = ostream(buf_size, b);
- o << i;
- return buf;
- }
- */
-
- else if (TREE_CODE (init) == TARGET_EXPR
- && TREE_CODE (TREE_OPERAND (init, 1) == NEW_EXPR))
- {
- /* User wrote something like `foo x = foo (args)' */
- my_friendly_assert (TREE_CODE (TREE_OPERAND (init, 0)) == VAR_DECL, 150);
- my_friendly_assert (DECL_NAME (TREE_OPERAND (init, 0)) == NULL_TREE, 151);
-
- /* User wrote exactly `foo x = foo (args)' */
- if (TYPE_MAIN_VARIANT (type) == TREE_TYPE (init))
- {
- init = build (CALL_EXPR, TREE_TYPE (init),
- TREE_OPERAND (TREE_OPERAND (init, 1), 0),
- TREE_OPERAND (TREE_OPERAND (init, 1), 1), 0);
- TREE_SIDE_EFFECTS (init) = 1;
- }
- }
-#endif
-
- /* We must hide the initializer so that expand_decl
- won't try to do something it does not understand. */
- if (current_binding_level == global_binding_level)
- {
- tree value = digest_init (type, empty_init_node, (tree *) 0);
- DECL_INITIAL (decl) = value;
- }
- else
- DECL_INITIAL (decl) = error_mark_node;
- }
- else
- {
- if (TREE_CODE (init) != TREE_VEC)
- init = store_init_value (decl, init);
-
- if (init)
- /* Don't let anyone try to initialize this variable
- until we are ready to do so. */
- DECL_INITIAL (decl) = error_mark_node;
- }
- }
- else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
- && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
- {
- tree ctype = type;
- while (TREE_CODE (ctype) == ARRAY_TYPE)
- ctype = TREE_TYPE (ctype);
- if (! TYPE_NEEDS_CONSTRUCTOR (ctype))
- {
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype))
- error_with_decl (decl, "structure `%s' with uninitialized const members");
- if (CLASSTYPE_REF_FIELDS_NEED_INIT (ctype))
- error_with_decl (decl, "structure `%s' with uninitialized reference members");
- }
-
- if (TREE_CODE (decl) == VAR_DECL
- && !TYPE_NEEDS_CONSTRUCTING (type)
- && (TYPE_READONLY (type) || TREE_READONLY (decl)))
- error_with_decl (decl, "uninitialized const `%s'");
-
- /* Initialize variables in need of static initialization
- with `empty_init_node' to keep assemble_variable from putting them
- in the wrong program space. (Common storage is okay for non-public
- uninitialized data; the linker can't match it with storage from other
- files, and we may save some disk space.) */
- if (flag_pic == 0
- && TREE_STATIC (decl)
- && TREE_PUBLIC (decl)
- && ! DECL_EXTERNAL (decl)
- && TREE_CODE (decl) == VAR_DECL
- && TYPE_NEEDS_CONSTRUCTING (type)
- && (DECL_INITIAL (decl) == NULL_TREE
- || DECL_INITIAL (decl) == error_mark_node))
- {
- tree value = digest_init (type, empty_init_node, (tree *) 0);
- DECL_INITIAL (decl) = value;
- }
- }
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_CODE (type) != REFERENCE_TYPE
- && (TYPE_READONLY (type) || TREE_READONLY (decl)))
- {
- /* ``Unless explicitly declared extern, a const object does not have
- external linkage and must be initialized. ($8.4; $12.1)'' ARM 7.1.6
- However, if it's `const int foo = 1; const int foo;', don't complain
- about the second decl, since it does have an initializer before. */
- if (! DECL_INITIAL (decl) && (!pedantic || !current_class_type))
- error_with_decl (decl, "uninitialized const `%s'");
- }
-
- /* For top-level declaration, the initial value was read in
- the temporary obstack. MAXINDEX, rtl, etc. to be made below
- must go in the permanent obstack; but don't discard the
- temporary data yet. */
-
- if (current_binding_level == global_binding_level && temporary)
- end_temporary_allocation ();
-
- /* Deduce size of array from initialization, if not already known. */
-
- if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_DOMAIN (type) == NULL_TREE
- && TREE_CODE (decl) != TYPE_DECL)
- {
- int do_default
- = (TREE_STATIC (decl)
- /* Even if pedantic, an external linkage array
- may have incomplete type at first. */
- ? pedantic && DECL_EXTERNAL (decl)
- : !DECL_EXTERNAL (decl));
- tree initializer = init ? init : DECL_INITIAL (decl);
- int failure = complete_array_type (type, initializer, do_default);
-
- if (failure == 1)
- error_with_decl (decl, "initializer fails to determine size of `%s'");
-
- if (failure == 2)
- {
- if (do_default)
- error_with_decl (decl, "array size missing in `%s'");
- else if (!pedantic && TREE_STATIC (decl))
- DECL_EXTERNAL (decl) = 1;
- }
-
- if (pedantic && TYPE_DOMAIN (type) != NULL_TREE
- && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
- integer_zero_node))
- error_with_decl (decl, "zero-size array `%s'");
-
- layout_decl (decl, 0);
- }
-
- if (TREE_CODE (decl) == VAR_DECL)
- {
- if (TREE_STATIC (decl) && DECL_SIZE (decl) == NULL_TREE)
- {
- /* A static variable with an incomplete type:
- that is an error if it is initialized or `static'.
- Otherwise, let it through, but if it is not `extern'
- then it may cause an error message later. */
- if (!DECL_EXTERNAL (decl) || DECL_INITIAL (decl) != NULL_TREE)
- error_with_decl (decl, "storage size of `%s' isn't known");
- init = NULL_TREE;
- }
- else if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
- {
- /* An automatic variable with an incomplete type: that is an error.
- Don't talk about array types here, since we took care of that
- message in grokdeclarator. */
- error_with_decl (decl, "storage size of `%s' isn't known");
- TREE_TYPE (decl) = error_mark_node;
- }
- else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
- /* Let debugger know it should output info for this type. */
- note_debug_info_needed (ttype);
-
- if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
- && DECL_SIZE (decl) != NULL_TREE
- && ! TREE_CONSTANT (DECL_SIZE (decl)))
- error_with_decl (decl, "storage size of `%s' isn't constant");
-
- if (!DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type))
- {
- int yes = suspend_momentary ();
-
- /* If INIT comes from a functional cast, use the cleanup
- we built for that. Otherwise, make our own cleanup. */
- if (init && TREE_CODE (init) == WITH_CLEANUP_EXPR
- && comptypes (TREE_TYPE (decl), TREE_TYPE (init), 1))
- {
- cleanup = TREE_OPERAND (init, 2);
- init = TREE_OPERAND (init, 0);
- current_binding_level->have_cleanups = 1;
- current_binding_level->more_exceptions_ok = 0;
- }
- else
- cleanup = maybe_build_cleanup (decl);
- resume_momentary (yes);
- }
- }
- /* PARM_DECLs get cleanups, too. */
- else if (TREE_CODE (decl) == PARM_DECL && TYPE_NEEDS_DESTRUCTOR (type))
- {
- if (temporary)
- end_temporary_allocation ();
- cleanup = maybe_build_cleanup (decl);
- if (temporary)
- resume_temporary_allocation ();
- }
-
- /* Output the assembler code and/or RTL code for variables and functions,
- unless the type is an undefined structure or union.
- If not, it will get done when the type is completed. */
-
- if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == RESULT_DECL)
- {
- int toplev = current_binding_level == global_binding_level;
- int was_temp
- = ((flag_traditional
- || (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)))
- && allocation_temporary_p ());
-
- if (was_temp)
- end_temporary_allocation ();
-
- /* If we are in need of a cleanup, get out of any implicit
- handlers that have been established so far. */
- if (cleanup && current_binding_level->parm_flag == 3)
- {
- pop_implicit_try_blocks (decl);
- current_binding_level->more_exceptions_ok = 0;
- }
-
- if (TREE_CODE (decl) == VAR_DECL
- && current_binding_level != global_binding_level
- && ! TREE_STATIC (decl)
- && type_needs_gc_entry (type))
- DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index);
-
- if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
- make_decl_rtl (decl, NULL_PTR, toplev);
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_READONLY (decl)
- && DECL_INITIAL (decl) != NULL_TREE
- && DECL_INITIAL (decl) != error_mark_node
- && DECL_INITIAL (decl) != empty_init_node)
- {
- DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
-
- if (asmspec)
- DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
-
- if (! toplev
- && TREE_STATIC (decl)
- && ! TREE_SIDE_EFFECTS (decl)
- && ! TREE_PUBLIC (decl)
- && ! DECL_EXTERNAL (decl)
- && ! TYPE_NEEDS_DESTRUCTOR (type)
- && DECL_MODE (decl) != BLKmode)
- {
- /* If this variable is really a constant, then fill its DECL_RTL
- slot with something which won't take up storage.
- If something later should take its address, we can always give
- it legitimate RTL at that time. */
- DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
- store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0);
- TREE_ASM_WRITTEN (decl) = 1;
- }
- else if (toplev)
- {
- /* Keep GCC from complaining that this variable
- is defined but never used. */
- TREE_USED (decl) = 1;
- /* If this is a static const, change its apparent linkage
- if it belongs to a #pragma interface. */
- if (TREE_STATIC (decl) && !interface_unknown)
- {
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = interface_only;
- }
- make_decl_rtl (decl, asmspec, toplev);
- }
- else
- rest_of_decl_compilation (decl, asmspec, toplev, 0);
- }
- else if (TREE_CODE (decl) == VAR_DECL
- && DECL_LANG_SPECIFIC (decl)
- && DECL_IN_AGGR_P (decl))
- {
- if (TREE_STATIC (decl))
- if (init == NULL_TREE
-#ifdef DEFAULT_STATIC_DEFS
- /* If this code is dead, then users must
- explicitly declare static member variables
- outside the class def'n as well. */
- && TYPE_NEEDS_CONSTRUCTING (type)
-#endif
- )
- {
- DECL_EXTERNAL (decl) = 1;
- make_decl_rtl (decl, asmspec, 1);
- }
- else
- rest_of_decl_compilation (decl, asmspec, toplev, 0);
- else
- /* Just a constant field. Should not need any rtl. */
- goto finish_end0;
- }
- else
- rest_of_decl_compilation (decl, asmspec, toplev, 0);
-
- if (was_temp)
- resume_temporary_allocation ();
-
- if (type != error_mark_node
- && TYPE_LANG_SPECIFIC (type)
- && CLASSTYPE_ABSTRACT_VIRTUALS (type))
- abstract_virtuals_error (decl, type);
- else if ((TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
- && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
- && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (type)))
- abstract_virtuals_error (decl, TREE_TYPE (type));
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- /* C++: Handle overloaded functions with default parameters. */
- if (DECL_OVERLOADED (decl))
- {
- tree parmtypes = TYPE_ARG_TYPES (type);
- tree prev = NULL_TREE;
- tree original_name = DECL_NAME (decl);
- struct lang_decl *tmp_lang_decl = DECL_LANG_SPECIFIC (decl);
- /* All variants will share an uncollectible lang_decl. */
- copy_decl_lang_specific (decl);
-
- while (parmtypes && parmtypes != void_list_node)
- {
- if (TREE_PURPOSE (parmtypes))
- {
- tree fnname, fndecl;
- tree *argp = prev
- ? & TREE_CHAIN (prev)
- : & TYPE_ARG_TYPES (type);
-
- *argp = NULL_TREE;
- fnname = build_decl_overload (original_name, TYPE_ARG_TYPES (type), 0);
- *argp = parmtypes;
- fndecl = build_decl (FUNCTION_DECL, fnname, type);
- DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl);
- TREE_PUBLIC (fndecl) = TREE_PUBLIC (decl);
- DECL_INLINE (fndecl) = DECL_INLINE (decl);
- /* Keep G++ from thinking this function is unused.
- It is only used to speed up search in name space. */
- TREE_USED (fndecl) = 1;
- TREE_ASM_WRITTEN (fndecl) = 1;
- DECL_INITIAL (fndecl) = NULL_TREE;
- DECL_LANG_SPECIFIC (fndecl) = DECL_LANG_SPECIFIC (decl);
- fndecl = pushdecl (fndecl);
- DECL_INITIAL (fndecl) = error_mark_node;
- DECL_RTL (fndecl) = DECL_RTL (decl);
- }
- prev = parmtypes;
- parmtypes = TREE_CHAIN (parmtypes);
- }
- DECL_LANG_SPECIFIC (decl) = tmp_lang_decl;
- }
- }
- else if (DECL_EXTERNAL (decl))
- ;
- else if (TREE_STATIC (decl) && type != error_mark_node)
- {
- /* Cleanups for static variables are handled by `finish_file'. */
- if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE)
- expand_static_init (decl, init);
- else if (TYPE_NEEDS_DESTRUCTOR (type))
- static_aggregates = perm_tree_cons (NULL_TREE, decl,
- static_aggregates);
-
- /* Make entry in appropriate vector. */
- if (flag_gc && type_needs_gc_entry (type))
- build_static_gc_entry (decl, type);
- }
- else if (current_binding_level != global_binding_level)
- {
- /* This is a declared decl which must live until the
- end of the binding contour. It may need a cleanup. */
-
- /* Recompute the RTL of a local array now
- if it used to be an incomplete type. */
- if (was_incomplete && ! TREE_STATIC (decl))
- {
- /* If we used it already as memory, it must stay in memory. */
- TREE_ADDRESSABLE (decl) = TREE_USED (decl);
- /* If it's still incomplete now, no init will save it. */
- if (DECL_SIZE (decl) == NULL_TREE)
- DECL_INITIAL (decl) = NULL_TREE;
- expand_decl (decl);
- }
- else if (! TREE_ASM_WRITTEN (decl)
- && (TYPE_SIZE (type) != NULL_TREE
- || TREE_CODE (type) == ARRAY_TYPE))
- {
- /* Do this here, because we did not expand this decl's
- rtl in start_decl. */
- if (DECL_RTL (decl) == NULL_RTX)
- expand_decl (decl);
- else if (cleanup)
- {
- expand_decl_cleanup (NULL_TREE, cleanup);
- /* Cleanup used up here. */
- cleanup = NULL_TREE;
- }
- }
-
- if (DECL_SIZE (decl) && type != error_mark_node)
- {
- /* Compute and store the initial value. */
- expand_decl_init (decl);
-
- if (init || TYPE_NEEDS_CONSTRUCTING (type))
- {
- emit_line_note (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
- expand_aggr_init (decl, init, 0);
- }
-
- /* Set this to 0 so we can tell whether an aggregate
- which was initialized was ever used. */
- if (TYPE_NEEDS_CONSTRUCTING (type))
- TREE_USED (decl) = 0;
-
- /* Store the cleanup, if there was one. */
- if (cleanup)
- {
- if (! expand_decl_cleanup (decl, cleanup))
- error_with_decl (decl, "parser lost in parsing declaration of `%s'");
- }
- }
- }
- finish_end0:
-
- /* Undo call to `pushclass' that was done in `start_decl'
- due to initialization of qualified member variable.
- I.e., Foo::x = 10; */
- {
- tree context = DECL_CONTEXT (decl);
- if (context
- && TREE_CODE_CLASS (TREE_CODE (context)) == 't'
- && (TREE_CODE (decl) == VAR_DECL
- /* We also have a pushclass done that we need to undo here
- if we're at top level and declare a method. */
- || (TREE_CODE (decl) == FUNCTION_DECL
- /* If size hasn't been set, we're still defining it,
- and therefore inside the class body; don't pop
- the binding level.. */
- && TYPE_SIZE (context) != NULL_TREE
- /* The binding level gets popped elsewhere for a
- friend declaration inside another class. */
- && TYPE_IDENTIFIER (context) == current_class_name
- )))
- popclass (1);
- }
- }
-
- finish_end:
-
- if (need_pop)
- {
- /* Resume permanent allocation, if not within a function. */
- /* The corresponding push_obstacks_nochange is in start_decl,
- start_method, groktypename, and in grokfield. */
- pop_obstacks ();
- }
-
- if (was_readonly)
- TREE_READONLY (decl) = 1;
-
- if (flag_cadillac)
- cadillac_finish_decl (decl);
-}
-
-static void
-expand_static_init (decl, init)
- tree decl;
- tree init;
-{
- tree oldstatic = value_member (decl, static_aggregates);
- if (oldstatic)
- {
- if (TREE_PURPOSE (oldstatic))
- error_with_decl (decl, "multiple initializations given for `%s'");
- }
- else if (current_binding_level != global_binding_level)
- {
- /* Emit code to perform this initialization but once. */
- tree temp;
-
- /* Remember this information until end of file. */
- push_obstacks (&permanent_obstack, &permanent_obstack);
-
- /* Emit code to perform this initialization but once. */
- temp = get_temp_name (integer_type_node, 1);
- rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
- expand_start_cond (build_binary_op (EQ_EXPR, temp,
- integer_zero_node, 1), 0);
- expand_assignment (temp, integer_one_node, 0, 0);
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
- {
- expand_aggr_init (decl, init, 0);
- do_pending_stack_adjust ();
- }
- else
- expand_assignment (decl, init, 0, 0);
- expand_end_cond ();
- if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
- {
- static_aggregates = perm_tree_cons (temp, decl, static_aggregates);
- TREE_STATIC (static_aggregates) = 1;
- }
-
- /* Resume old (possibly temporary) allocation. */
- pop_obstacks ();
- }
- else
- {
- /* This code takes into account memory allocation
- policy of `start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING
- does not hold for this object, then we must make permanent
- the storage currently in the temporary obstack. */
- if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
- preserve_initializer ();
- static_aggregates = perm_tree_cons (init, decl, static_aggregates);
- }
-}
-
-/* Make TYPE a complete type based on INITIAL_VALUE.
- Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
- 2 if there was no information (in which case assume 1 if DO_DEFAULT). */
-
-int
-complete_array_type (type, initial_value, do_default)
- tree type, initial_value;
- int do_default;
-{
- register tree maxindex = NULL_TREE;
- int value = 0;
-
- if (initial_value)
- {
- /* Note MAXINDEX is really the maximum index,
- one less than the size. */
- if (TREE_CODE (initial_value) == STRING_CST)
- maxindex = build_int_2 (TREE_STRING_LENGTH (initial_value) - 1, 0);
- else if (TREE_CODE (initial_value) == CONSTRUCTOR)
- {
- register int nelts
- = list_length (CONSTRUCTOR_ELTS (initial_value));
- maxindex = build_int_2 (nelts - 1, 0);
- }
- else
- {
- /* Make an error message unless that happened already. */
- if (initial_value != error_mark_node)
- value = 1;
-
- /* Prevent further error messages. */
- maxindex = build_int_2 (1, 0);
- }
- }
-
- if (!maxindex)
- {
- if (do_default)
- maxindex = build_int_2 (1, 0);
- value = 2;
- }
-
- if (maxindex)
- {
- TYPE_DOMAIN (type) = build_index_type (maxindex);
- if (!TREE_TYPE (maxindex))
- TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
- }
-
- /* Lay out the type now that we can get the real answer. */
-
- layout_type (type);
-
- return value;
-}
-
-/* Return zero if something is declared to be a member of type
- CTYPE when in the context of CUR_TYPE. STRING is the error
- message to print in that case. Otherwise, quietly return 1. */
-static int
-member_function_or_else (ctype, cur_type, string)
- tree ctype, cur_type;
- char *string;
-{
- if (ctype && ctype != cur_type)
- {
- error (string, TYPE_NAME_STRING (ctype));
- return 0;
- }
- return 1;
-}
-
-/* Subroutine of `grokdeclarator'. */
-
-/* CTYPE is class type, or null if non-class.
- TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
- or METHOD_TYPE.
- DECLARATOR is the function's name.
- VIRTUALP is truthvalue of whether the function is virtual or not.
- FLAGS are to be passed through to `grokclassfn'.
- QUALS are qualifiers indicating whether the function is `const'
- or `volatile'.
- RAISES is a list of exceptions that this function can raise.
- CHECK is 1 if we must find this method in CTYPE, 0 if we should
- not look, and -1 if we should not call `grokclassfn' at all. */
-static tree
-grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publicp)
- tree ctype, type;
- tree declarator;
- int virtualp;
- enum overload_flags flags;
- tree quals, raises;
- int check, publicp;
-{
- tree cname, decl;
- int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
-
- if (ctype)
- cname = TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL
- ? TYPE_IDENTIFIER (ctype) : TYPE_NAME (ctype);
- else
- cname = NULL_TREE;
-
- if (raises)
- {
- type = build_exception_variant (ctype, type, raises);
- raises = TYPE_RAISES_EXCEPTIONS (type);
- }
- decl = build_lang_decl (FUNCTION_DECL, declarator, type);
- /* propagate volatile out from type to decl */
- if (TYPE_VOLATILE (type))
- TREE_THIS_VOLATILE (decl) = 1;
-
- /* Should probably propagate const out from type to decl I bet (mrs). */
- if (staticp)
- {
- DECL_STATIC_FUNCTION_P (decl) = 1;
- DECL_CONTEXT (decl) = ctype;
- DECL_CLASS_CONTEXT (decl) = ctype;
- }
-
- if (publicp)
- TREE_PUBLIC (decl) = 1;
-
- DECL_EXTERNAL (decl) = 1;
- if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("functions cannot have method qualifiers");
- quals = NULL_TREE;
- }
-
- /* Only two styles of delete's are valid. */
- if (declarator == ansi_opname[(int) DELETE_EXPR])
- {
- tree args = TYPE_ARG_TYPES (type);
- int style1, style2;
-
- if (ctype && args && TREE_CODE (type) == METHOD_TYPE)
- /* remove this */
- args = TREE_CHAIN (args);
-
- style1 = type_list_equal (args,
- tree_cons (NULL_TREE, ptr_type_node,
- void_list_node));
- style2 = style1 != 0 ? 0 :
- type_list_equal (args,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, sizetype,
- void_list_node)));
-
- if (ctype == NULL_TREE)
- {
- if (! style1)
- /* ANSI C++ June 5 1992 WP 12.5.5.2 */
- error ("global operator delete must be declared as taking a single argument of type void*");
- }
- else
- if (! style1 && ! style2)
- /* ANSI C++ June 5 1992 WP 12.5.4.1 */
- error ("operator delete cannot be overloaded");
- }
- else if (DECL_NAME (decl) == ansi_opname[(int) POSTINCREMENT_EXPR]
- || DECL_NAME (decl) == ansi_opname[(int) POSTDECREMENT_EXPR])
- {
- /* According to ARM $13.4.7, postfix operator++ must take an int as
- its second argument. */
- tree parmtypes, argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
-
- if (argtypes)
- {
- parmtypes = TREE_CHAIN (argtypes);
- if (parmtypes != NULL_TREE
- && TREE_VALUE (parmtypes) != void_type_node
- && TREE_VALUE (parmtypes) != integer_type_node)
- error ("postfix operator%s may only take `int' as its argument",
- POSTINCREMENT_EXPR ? "++" : "--");
- }
- }
-
- /* Caller will do the rest of this. */
- if (check < 0)
- return decl;
-
- if (flags == NO_SPECIAL && ctype && constructor_name (cname) == declarator)
- {
- tree tmp;
- /* Just handle constructors here. We could do this
- inside the following if stmt, but I think
- that the code is more legible by breaking this
- case out. See comments below for what each of
- the following calls is supposed to do. */
- DECL_CONSTRUCTOR_P (decl) = 1;
-
- grokclassfn (ctype, declarator, decl, flags, quals);
- if (check)
- check_classfn (ctype, declarator, decl);
- grok_ctor_properties (ctype, decl);
- if (check == 0)
- {
- /* FIXME: this should only need to look at IDENTIFIER_GLOBAL_VALUE. */
- tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
- if (tmp == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
- else if (TREE_CODE (tmp) != TREE_CODE (decl))
- error_with_decl (decl, "inconsistent declarations for `%s'");
- else
- {
- duplicate_decls (decl, tmp);
- decl = tmp;
- /* avoid creating circularities. */
- DECL_CHAIN (decl) = NULL_TREE;
- }
- make_decl_rtl (decl, NULL_PTR, 1);
- }
- }
- else
- {
- tree tmp;
-
- /* Function gets the ugly name, field gets the nice one.
- This call may change the type of the function (because
- of default parameters)! */
- if (ctype != NULL_TREE)
- grokclassfn (ctype, cname, decl, flags, quals);
-
- if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
- grok_op_properties (decl, virtualp);
-
- if (ctype != NULL_TREE && check)
- check_classfn (ctype, cname, decl);
-
- if (ctype == NULL_TREE || check)
- return decl;
-
- /* Now install the declaration of this function so that
- others may find it (esp. its DECL_FRIENDLIST).
- Pretend we are at top level, we will get true
- reference later, perhaps.
-
- FIXME: This should only need to look at IDENTIFIER_GLOBAL_VALUE. */
- tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
- if (tmp == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
- else if (TREE_CODE (tmp) != TREE_CODE (decl))
- error_with_decl (decl, "inconsistent declarations for `%s'");
- else
- {
- duplicate_decls (decl, tmp);
- decl = tmp;
- /* avoid creating circularities. */
- DECL_CHAIN (decl) = NULL_TREE;
- }
- make_decl_rtl (decl, NULL_PTR, 1);
-
- /* If this declaration supersedes the declaration of
- a method declared virtual in the base class, then
- mark this field as being virtual as well. */
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype));
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)) || flag_all_virtual == 1)
- {
- tmp = get_first_matching_virtual (base_binfo, decl,
- flags == DTOR_FLAG);
- if (tmp)
- {
- /* The TMP we really want is the one from the deepest
- baseclass on this path, taking care not to
- duplicate if we have already found it (via another
- path to its virtual baseclass. */
- if (staticp)
- {
- error_with_decl (decl, "method `%s' may not be declared static");
- error_with_decl (tmp, "(since `%s' declared virtual in base class.)");
- break;
- }
- virtualp = 1;
-
- if ((TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (base_binfo))
- || TYPE_USES_MULTIPLE_INHERITANCE (ctype))
- && BINFO_TYPE (base_binfo) != DECL_CONTEXT (tmp))
- tmp = get_first_matching_virtual (TYPE_BINFO (DECL_CONTEXT (tmp)),
- decl, flags == DTOR_FLAG);
- if (value_member (tmp, DECL_VINDEX (decl)) == NULL_TREE)
- {
- /* The argument types may have changed... */
- tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
- tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
-
- argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
- TREE_CHAIN (argtypes));
- /* But the return type has not. */
- type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
- if (raises)
- {
- type = build_exception_variant (ctype, type, raises);
- raises = TYPE_RAISES_EXCEPTIONS (type);
- }
- TREE_TYPE (decl) = type;
- DECL_VINDEX (decl)
- = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
- }
- }
- }
- }
- }
- if (virtualp)
- {
- if (DECL_VINDEX (decl) == NULL_TREE)
- DECL_VINDEX (decl) = error_mark_node;
- IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
- if (ctype && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype)
- /* If this function is derived from a template, don't
- make it public. This shouldn't be here, but there's
- no good way to override the interface pragmas for one
- function or class only. Bletch. */
- && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (ctype)) == NULL_TREE
- && (write_virtuals == 2
- || (write_virtuals == 3
- && ! CLASSTYPE_INTERFACE_UNKNOWN (ctype))))
- TREE_PUBLIC (decl) = 1;
- }
- }
- return decl;
-}
-
-static tree
-grokvardecl (type, declarator, specbits, initialized)
- tree type;
- tree declarator;
- RID_BIT_TYPE specbits;
- int initialized;
-{
- tree decl;
-
- /* This implements the "one definition rule" for global variables.
- Note that declarator can come in as null when we're doing work
- on an anonymous union. */
- if (declarator && IDENTIFIER_GLOBAL_VALUE (declarator)
- && current_binding_level == global_binding_level
- && TREE_STATIC (IDENTIFIER_GLOBAL_VALUE (declarator))
- && (! (specbits & RIDBIT (RID_EXTERN))
- || initialized))
- {
- error ("redefinition of `%s'", IDENTIFIER_POINTER (declarator));
- error_with_decl (IDENTIFIER_GLOBAL_VALUE (declarator),
- "previously defined here");
- }
-
- if (TREE_CODE (type) == OFFSET_TYPE)
- {
- /* If you declare a static member so that it
- can be initialized, the code will reach here. */
- tree field = lookup_field (TYPE_OFFSET_BASETYPE (type),
- declarator, 0, 0);
- if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
- {
- tree basetype = TYPE_OFFSET_BASETYPE (type);
- error ("`%s' is not a static member of class `%s'",
- IDENTIFIER_POINTER (declarator),
- TYPE_NAME_STRING (basetype));
- type = TREE_TYPE (type);
- decl = build_lang_field_decl (VAR_DECL, declarator, type);
- DECL_CONTEXT (decl) = basetype;
- DECL_CLASS_CONTEXT (decl) = basetype;
- }
- else
- {
- tree f_type = TREE_TYPE (field);
- tree o_type = TREE_TYPE (type);
-
- if (TYPE_SIZE (f_type) == NULL_TREE)
- {
- if (TREE_CODE (f_type) != TREE_CODE (o_type)
- || (TREE_CODE (f_type) == ARRAY_TYPE
- && TREE_TYPE (f_type) != TREE_TYPE (o_type)))
- error ("redeclaration of type for `%s'",
- IDENTIFIER_POINTER (declarator));
- else if (TYPE_SIZE (o_type) != NULL_TREE)
- TREE_TYPE (field) = type;
- }
- else if (f_type != o_type)
- error ("redeclaration of type for `%s'",
- IDENTIFIER_POINTER (declarator));
- decl = field;
- if (initialized && DECL_INITIAL (decl)
- /* Complain about multiply-initialized
- member variables, but don't be faked
- out if initializer is faked up from `empty_init_node'. */
- && (TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
- || CONSTRUCTOR_ELTS (DECL_INITIAL (decl)) != NULL_TREE))
- error_with_aggr_type (DECL_CONTEXT (decl),
- "multiple initializations of static member `%s::%s'",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- }
- }
- else decl = build_decl (VAR_DECL, declarator, type);
-
- if (specbits & RIDBIT (RID_EXTERN))
- {
- DECL_THIS_EXTERN (decl) = 1;
- DECL_EXTERNAL (decl) = !initialized;
- }
-
- /* In class context, static means one per class,
- public visibility, and static storage. */
- if (DECL_FIELD_CONTEXT (decl) != NULL_TREE
- && IS_AGGR_TYPE (DECL_FIELD_CONTEXT (decl)))
- {
- TREE_PUBLIC (decl) = 1;
- TREE_STATIC (decl) = 1;
- DECL_EXTERNAL (decl) = !initialized;
- }
- /* At top level, either `static' or no s.c. makes a definition
- (perhaps tentative), and absence of `static' makes it public. */
- else if (current_binding_level == global_binding_level)
- {
- TREE_PUBLIC (decl) = ! (specbits & RIDBIT (RID_STATIC));
- TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
- }
- /* Not at top level, only `static' makes a static definition. */
- else
- {
- TREE_STATIC (decl) = !! (specbits & RIDBIT (RID_STATIC));
- TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
- }
- return decl;
-}
-
-/* Given declspecs and a declarator,
- determine the name and type of the object declared
- and construct a ..._DECL node for it.
- (In one case we can return a ..._TYPE node instead.
- For invalid input we sometimes return 0.)
-
- DECLSPECS is a chain of tree_list nodes whose value fields
- are the storage classes and type specifiers.
-
- DECL_CONTEXT says which syntactic context this declaration is in:
- NORMAL for most contexts. Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL.
- FUNCDEF for a function definition. Like NORMAL but a few different
- error messages in each case. Return value may be zero meaning
- this definition is too screwy to try to parse.
- MEMFUNCDEF for a function definition. Like FUNCDEF but prepares to
- handle member functions (which have FIELD context).
- Return value may be zero meaning this definition is too screwy to
- try to parse.
- PARM for a parameter declaration (either within a function prototype
- or before a function body). Make a PARM_DECL, or return void_type_node.
- TYPENAME if for a typename (in a cast or sizeof).
- Don't make a DECL node; just return the ..._TYPE node.
- FIELD for a struct or union field; make a FIELD_DECL.
- BITFIELD for a field with specified width.
- INITIALIZED is 1 if the decl has an initializer.
-
- In the TYPENAME case, DECLARATOR is really an absolute declarator.
- It may also be so in the PARM case, for a prototype where the
- argument type is specified but not the name.
-
- This function is where the complicated C meanings of `static'
- and `extern' are interpreted.
-
- For C++, if there is any monkey business to do, the function which
- calls this one must do it, i.e., prepending instance variables,
- renaming overloaded function names, etc.
-
- Note that for this C++, it is an error to define a method within a class
- which does not belong to that class.
-
- Except in the case where SCOPE_REFs are implicitly known (such as
- methods within a class being redundantly qualified),
- declarations which involve SCOPE_REFs are returned as SCOPE_REFs
- (class_name::decl_name). The caller must also deal with this.
-
- If a constructor or destructor is seen, and the context is FIELD,
- then the type gains the attribute TREE_HAS_x. If such a declaration
- is erroneous, NULL_TREE is returned.
-
- QUALS is used only for FUNCDEF and MEMFUNCDEF cases. For a member
- function, these are the qualifiers to give to the `this' pointer.
-
- May return void_type_node if the declarator turned out to be a friend.
- See grokfield for details. */
-
-enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
-
-tree
-grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
- tree declspecs;
- tree declarator;
- enum decl_context decl_context;
- int initialized;
- tree raises;
-{
- extern int current_class_depth;
-
- RID_BIT_TYPE specbits = 0;
- int nclasses = 0;
- tree spec;
- tree type = NULL_TREE;
- int longlong = 0;
- int constp;
- int volatilep;
- int virtualp, friendp, inlinep, staticp;
- int explicit_int = 0;
- int explicit_char = 0;
- tree typedef_decl = NULL_TREE;
- char *name;
- tree typedef_type = NULL_TREE;
- int funcdef_flag = 0;
- enum tree_code innermost_code = ERROR_MARK;
- int bitfield = 0;
- int size_varies = 0;
- /* Set this to error_mark_node for FIELD_DECLs we could not handle properly.
- All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */
- tree init = NULL_TREE;
-
- /* Keep track of what sort of function is being processed
- so that we can warn about default return values, or explicit
- return values which do not match prescribed defaults. */
- enum return_types return_type = return_normal;
-
- tree dname = NULL_TREE;
- tree ctype = current_class_type;
- tree ctor_return_type = NULL_TREE;
- enum overload_flags flags = NO_SPECIAL;
- int seen_scope_ref = 0;
- tree quals = NULL_TREE;
-
- if (decl_context == FUNCDEF)
- funcdef_flag = 1, decl_context = NORMAL;
- else if (decl_context == MEMFUNCDEF)
- funcdef_flag = -1, decl_context = FIELD;
- else if (decl_context == BITFIELD)
- bitfield = 1, decl_context = FIELD;
-
- if (flag_traditional && allocation_temporary_p ())
- end_temporary_allocation ();
-
- /* Look inside a declarator for the name being declared
- and get it as a string, for an error message. */
- {
- tree type, last = NULL_TREE;
- register tree decl = declarator;
- name = NULL;
-
- /* If we see something of the form `aggr_type xyzzy (a, b, c)'
- it is either an old-style function declaration or a call to
- a constructor. The following conditional makes recognizes this
- case as being a call to a constructor. Too bad if it is not. */
-
- /* For Doug Lea, also grok `aggr_type xyzzy (a, b, c)[10][10][10]'. */
- while (decl && TREE_CODE (decl) == ARRAY_REF)
- {
- last = decl;
- decl = TREE_OPERAND (decl, 0);
- }
-
- if (decl && declspecs
- && TREE_CODE (decl) == CALL_EXPR
- && TREE_OPERAND (decl, 0)
- && (TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
- || TREE_CODE (TREE_OPERAND (decl, 0)) == SCOPE_REF))
- {
- type = TREE_CODE (TREE_VALUE (declspecs)) == IDENTIFIER_NODE
- ? lookup_name (TREE_VALUE (declspecs), 1) :
- (IS_AGGR_TYPE (TREE_VALUE (declspecs))
- ? TYPE_NAME (TREE_VALUE (declspecs)) : NULL_TREE);
-
- if (type && TREE_CODE (type) == TYPE_DECL
- && IS_AGGR_TYPE (TREE_TYPE (type))
- && parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
- {
- if (decl_context == FIELD
- && TREE_CHAIN (TREE_OPERAND (decl, 1)))
- {
- /* That was an initializer list. */
- sorry ("initializer lists for field declarations");
- decl = TREE_OPERAND (decl, 0);
- if (last)
- {
- TREE_OPERAND (last, 0) = decl;
- decl = declarator;
- }
- declarator = decl;
- init = error_mark_node;
- goto bot;
- }
- else
- {
- init = TREE_OPERAND (decl, 1);
- if (last)
- {
- TREE_OPERAND (last, 0) = TREE_OPERAND (decl, 0);
- if (pedantic && init)
- {
- error ("arrays cannot take initializers");
- init = error_mark_node;
- }
- }
- else
- declarator = TREE_OPERAND (declarator, 0);
- decl = start_decl (declarator, declspecs, 1, NULL_TREE);
- finish_decl (decl, init, NULL_TREE, 1);
- return 0;
- }
- }
-
- if (parmlist_is_random (TREE_OPERAND (decl, 1)))
- {
- decl = TREE_OPERAND (decl, 0);
- if (TREE_CODE (decl) == SCOPE_REF)
- {
- if (TREE_COMPLEXITY (decl))
- my_friendly_abort (15);
- decl = TREE_OPERAND (decl, 1);
- }
- if (TREE_CODE (decl) == IDENTIFIER_NODE)
- name = IDENTIFIER_POINTER (decl);
- if (name)
- error ("bad parameter list specification for function `%s'",
- name);
- else
- error ("bad parameter list specification for function");
- return void_type_node;
- }
- bot:
- ;
- }
- else
- /* It didn't look like we thought it would, leave the ARRAY_REFs on. */
- decl = declarator;
-
- while (decl)
- switch (TREE_CODE (decl))
- {
- case COND_EXPR:
- ctype = NULL_TREE;
- decl = TREE_OPERAND (decl, 0);
- break;
-
- case BIT_NOT_EXPR: /* for C++ destructors! */
- {
- tree name = TREE_OPERAND (decl, 0);
- tree rename = NULL_TREE;
-
- my_friendly_assert (flags == NO_SPECIAL, 152);
- flags = DTOR_FLAG;
- return_type = return_dtor;
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
- if (ctype == NULL_TREE)
- {
- if (current_class_type == NULL_TREE)
- {
- error ("destructors must be member functions");
- flags = NO_SPECIAL;
- }
- else
- {
- tree t = constructor_name (current_class_name);
- if (t != name)
- rename = t;
- }
- }
- else
- {
- tree t = constructor_name (ctype);
- if (t != name)
- rename = t;
- }
-
- if (rename)
- {
- error ("destructor `%s' must match class name `%s'",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (rename));
- TREE_OPERAND (decl, 0) = rename;
- }
- decl = name;
- }
- break;
-
- case ADDR_EXPR: /* C++ reference declaration */
- /* fall through */
- case ARRAY_REF:
- case INDIRECT_REF:
- ctype = NULL_TREE;
- innermost_code = TREE_CODE (decl);
- decl = TREE_OPERAND (decl, 0);
- break;
-
- case CALL_EXPR:
- innermost_code = TREE_CODE (decl);
- decl = TREE_OPERAND (decl, 0);
- if (decl_context == FIELD && ctype == NULL_TREE)
- ctype = current_class_type;
- if (ctype != NULL_TREE
- && decl != NULL_TREE && flags != DTOR_FLAG
- && decl == constructor_name (ctype))
- {
- return_type = return_ctor;
- ctor_return_type = ctype;
- }
- ctype = NULL_TREE;
- break;
-
- case IDENTIFIER_NODE:
- dname = decl;
- name = IDENTIFIER_POINTER (decl);
- decl = NULL_TREE;
- break;
-
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- /* Parse error puts this typespec where
- a declarator should go. */
- error ("declarator name missing");
- dname = TYPE_NAME (decl);
- if (dname && TREE_CODE (dname) == TYPE_DECL)
- dname = DECL_NAME (dname);
- name = dname ? IDENTIFIER_POINTER (dname) : "<nameless>";
- declspecs = temp_tree_cons (NULL_TREE, decl, declspecs);
- decl = NULL_TREE;
- break;
-
- case TYPE_EXPR:
- if (ctype == NULL_TREE)
- {
- /* ANSI C++ June 5 1992 WP 12.3.2 only describes
- conversion functions in terms of being declared
- as a member function. */
- error ("operator `%s' must be declared as a member",
- IDENTIFIER_POINTER (TREE_VALUE (TREE_TYPE (decl))));
- return NULL_TREE;
- }
-
- ctype = NULL_TREE;
- my_friendly_assert (flags == NO_SPECIAL, 154);
- flags = TYPENAME_FLAG;
- name = "operator <typename>";
- /* Go to the absdcl. */
- decl = TREE_OPERAND (decl, 0);
- return_type = return_conversion;
- break;
-
- /* C++ extension */
- case SCOPE_REF:
- if (seen_scope_ref == 1)
- error ("multiple `::' terms in declarator invalid");
- seen_scope_ref += 1;
- {
- /* Perform error checking, and convert class names to types.
- We may call grokdeclarator multiple times for the same
- tree structure, so only do the conversion once. In this
- case, we have exactly what we want for `ctype'. */
- tree cname = TREE_OPERAND (decl, 0);
- if (cname == NULL_TREE)
- ctype = NULL_TREE;
- /* Can't use IS_AGGR_TYPE because CNAME might not be a type. */
- else if (IS_AGGR_TYPE_CODE (TREE_CODE (cname))
- || TREE_CODE (cname) == UNINSTANTIATED_P_TYPE)
- ctype = cname;
- else if (! is_aggr_typedef (cname, 1))
- {
- TREE_OPERAND (decl, 0) = NULL_TREE;
- }
- /* Must test TREE_OPERAND (decl, 1), in case user gives
- us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */
- else if (TREE_OPERAND (decl, 1)
- && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
- {
- TREE_OPERAND (decl, 0) = IDENTIFIER_TYPE_VALUE (cname);
- }
- else if (ctype == NULL_TREE)
- {
- ctype = IDENTIFIER_TYPE_VALUE (cname);
- TREE_OPERAND (decl, 0) = ctype;
- }
- else if (TREE_COMPLEXITY (decl) == current_class_depth)
- TREE_OPERAND (decl, 0) = ctype;
- else
- {
- if (! UNIQUELY_DERIVED_FROM_P (IDENTIFIER_TYPE_VALUE (cname), ctype))
- {
- error ("type `%s' is not derived from type `%s'",
- IDENTIFIER_POINTER (cname),
- TYPE_NAME_STRING (ctype));
- TREE_OPERAND (decl, 0) = NULL_TREE;
- }
- else
- {
- ctype = IDENTIFIER_TYPE_VALUE (cname);
- TREE_OPERAND (decl, 0) = ctype;
- }
- }
-
- decl = TREE_OPERAND (decl, 1);
- if (ctype)
- {
- if (TREE_CODE (decl) == IDENTIFIER_NODE
- && constructor_name (ctype) == decl)
- {
- return_type = return_ctor;
- ctor_return_type = ctype;
- }
- else if (TREE_CODE (decl) == BIT_NOT_EXPR
- && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
- && constructor_name (ctype) == TREE_OPERAND (decl, 0))
- {
- return_type = return_dtor;
- ctor_return_type = ctype;
- flags = DTOR_FLAG;
- decl = TREE_OPERAND (decl, 0);
- }
- }
- }
- break;
-
- case ERROR_MARK:
- decl = NULL_TREE;
- break;
-
- default:
- my_friendly_abort (155);
- }
- if (name == NULL)
- name = "type name";
- }
-
- /* A function definition's declarator must have the form of
- a function declarator. */
-
- if (funcdef_flag && innermost_code != CALL_EXPR)
- return 0;
-
- /* Anything declared one level down from the top level
- must be one of the parameters of a function
- (because the body is at least two levels down). */
-
- /* This heuristic cannot be applied to C++ nodes! Fixed, however,
- by not allowing C++ class definitions to specify their parameters
- with xdecls (must be spec.d in the parmlist).
-
- Since we now wait to push a class scope until we are sure that
- we are in a legitimate method context, we must set oldcname
- explicitly (since current_class_name is not yet alive). */
-
- if (decl_context == NORMAL
- && current_binding_level->level_chain == global_binding_level)
- decl_context = PARM;
-
- /* Look through the decl specs and record which ones appear.
- Some typespecs are defined as built-in typenames.
- Others, the ones that are modifiers of other types,
- are represented by bits in SPECBITS: set the bits for
- the modifiers that appear. Storage class keywords are also in SPECBITS.
-
- If there is a typedef name or a type, store the type in TYPE.
- This includes builtin typedefs such as `int'.
-
- Set EXPLICIT_INT if the type is `int' or `char' and did not
- come from a user typedef.
-
- Set LONGLONG if `long' is mentioned twice.
-
- For C++, constructors and destructors have their own fast treatment. */
-
- for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
- {
- register int i;
- register tree id = TREE_VALUE (spec);
-
- /* Certain parse errors slip through. For example,
- `int class;' is not caught by the parser. Try
- weakly to recover here. */
- if (TREE_CODE (spec) != TREE_LIST)
- return 0;
-
- if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- if (id == ridpointers[(int) RID_INT])
- {
- if (type)
- error ("extraneous `int' ignored");
- else
- {
- explicit_int = 1;
- type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
- }
- goto found;
- }
- if (id == ridpointers[(int) RID_CHAR])
- {
- if (type)
- error ("extraneous `char' ignored");
- else
- {
- explicit_char = 1;
- type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
- }
- goto found;
- }
- if (id == ridpointers[(int) RID_WCHAR])
- {
- if (type)
- error ("extraneous `__wchar_t' ignored");
- else
- {
- type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
- }
- goto found;
- }
- /* C++ aggregate types. */
- if (IDENTIFIER_HAS_TYPE_VALUE (id))
- {
- if (type)
- error ("multiple declarations `%s' and `%s'",
- IDENTIFIER_POINTER (type),
- IDENTIFIER_POINTER (id));
- else
- type = IDENTIFIER_TYPE_VALUE (id);
- goto found;
- }
-
- for (i = (int) RID_FIRST_MODIFIER; i < (int) RID_MAX; i++)
- {
- if (ridpointers[i] == id)
- {
- if (i == (int) RID_LONG && (specbits & RIDBIT (i)))
- {
- if (pedantic)
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
- else if (longlong)
- error ("`long long long' is too long for GCC");
- else
- longlong = 1;
- }
- else if (specbits & RIDBIT (i))
- warning ("duplicate `%s'", IDENTIFIER_POINTER (id));
- specbits |= RIDBIT (i);
- goto found;
- }
- }
- }
- if (type)
- error ("two or more data types in declaration of `%s'", name);
- else if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- register tree t = lookup_name (id, 1);
- if (!t || TREE_CODE (t) != TYPE_DECL)
- error ("`%s' fails to be a typedef or built in type",
- IDENTIFIER_POINTER (id));
- else
- {
- type = TREE_TYPE (t);
- typedef_decl = t;
- }
- }
- else if (TREE_CODE (id) != ERROR_MARK)
- /* Can't change CLASS nodes into RECORD nodes here! */
- type = id;
-
- found: {}
- }
-
- typedef_type = type;
-
- /* No type at all: default to `int', and set EXPLICIT_INT
- because it was not a user-defined typedef. */
-
- if (type == NULL_TREE)
- {
- explicit_int = -1;
- if (return_type == return_dtor)
- type = void_type_node;
- else if (return_type == return_ctor)
- type = TYPE_POINTER_TO (ctor_return_type);
- else
- {
- if (funcdef_flag && explicit_warn_return_type
- && return_type == return_normal
- && ! (specbits & (RIDBIT (RID_SIGNED) | RIDBIT (RID_UNSIGNED)
- | RIDBIT (RID_LONG) | RIDBIT (RID_SHORT))))
- warn_about_return_type = 1;
- /* Save warning until we know what is really going on. */
- type = integer_type_node;
- }
- }
- else if (return_type == return_dtor)
- {
- error ("return type specification for destructor invalid");
- type = void_type_node;
- }
- else if (return_type == return_ctor)
- {
- error ("return type specification for constructor invalid");
- type = TYPE_POINTER_TO (ctor_return_type);
- }
- else if ((specbits & RIDBIT (RID_FRIEND))
- && IS_AGGR_TYPE (type)
- && ! TYPE_BEING_DEFINED (type)
- && TYPE_SIZE (type) == NULL_TREE
- && ! ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))
- && current_function_decl == NULL_TREE
- && decl_context != PARM)
- {
- /* xref_tag will make friend class declarations look like
- nested class declarations. Retroactively change that
- if the type has not yet been defined.
-
- ??? ANSI C++ doesn't say what to do in this case yet. */
- globalize_nested_type (type);
- }
-
- ctype = NULL_TREE;
-
- /* Now process the modifiers that were specified
- and check for invalid combinations. */
-
- /* Long double is a special combination. */
-
- if ((specbits & RIDBIT (RID_LONG))
- && TYPE_MAIN_VARIANT (type) == double_type_node)
- {
- specbits &= ~ RIDBIT (RID_LONG);
- type = build_type_variant (long_double_type_node, TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- }
-
- /* Check all other uses of type modifiers. */
-
- if (specbits & (RIDBIT (RID_UNSIGNED) | RIDBIT (RID_SIGNED)
- | RIDBIT (RID_LONG) | RIDBIT (RID_SHORT)))
- {
- int ok = 0;
-
- if (TREE_CODE (type) == REAL_TYPE)
- error ("short, signed or unsigned invalid for `%s'", name);
- else if (TREE_CODE (type) != INTEGER_TYPE || type == wchar_type_node)
- error ("long, short, signed or unsigned invalid for `%s'", name);
- else if ((specbits & RIDBIT (RID_LONG))
- && (specbits & RIDBIT (RID_SHORT)))
- error ("long and short specified together for `%s'", name);
- else if (((specbits & RIDBIT (RID_LONG))
- || (specbits & RIDBIT (RID_SHORT)))
- && explicit_char)
- error ("long or short specified with char for `%s'", name);
- else if (((specbits & RIDBIT (RID_LONG))
- || (specbits & RIDBIT (RID_SHORT)))
- && TREE_CODE (type) == REAL_TYPE)
- error ("long or short specified with floating type for `%s'", name);
- else if ((specbits & RIDBIT (RID_SIGNED))
- && (specbits & RIDBIT (RID_UNSIGNED)))
- error ("signed and unsigned given together for `%s'", name);
- else
- {
- ok = 1;
- if (!explicit_int && !explicit_char && pedantic)
- {
- pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
- name);
- if (flag_pedantic_errors)
- ok = 0;
- }
- }
-
- /* Discard the type modifiers if they are invalid. */
- if (! ok)
- {
- specbits &= ~ (RIDBIT (RID_UNSIGNED) | RIDBIT (RID_SIGNED)
- | RIDBIT (RID_LONG) | RIDBIT (RID_SHORT));
- longlong = 0;
- }
- }
-
- /* Decide whether an integer type is signed or not.
- Optionally treat bitfields as signed by default. */
- if ((specbits & RIDBIT (RID_UNSIGNED))
- /* Traditionally, all bitfields are unsigned. */
- || (bitfield && flag_traditional)
- || (bitfield && ! flag_signed_bitfields
- && (explicit_int || explicit_char
- /* A typedef for plain `int' without `signed'
- can be controlled just like plain `int'. */
- || ! (typedef_decl != NULL_TREE
- && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
- && TREE_CODE (type) != ENUMERAL_TYPE
- && !(specbits & RIDBIT (RID_SIGNED))))
- {
- if (longlong)
- type = long_long_unsigned_type_node;
- else if (specbits & RIDBIT (RID_LONG))
- type = long_unsigned_type_node;
- else if (specbits & RIDBIT (RID_SHORT))
- type = short_unsigned_type_node;
- else if (type == char_type_node)
- type = unsigned_char_type_node;
- else if (typedef_decl)
- type = unsigned_type (type);
- else
- type = unsigned_type_node;
- }
- else if ((specbits & RIDBIT (RID_SIGNED))
- && type == char_type_node)
- type = signed_char_type_node;
- else if (longlong)
- type = long_long_integer_type_node;
- else if (specbits & RIDBIT (RID_LONG))
- type = long_integer_type_node;
- else if (specbits & RIDBIT (RID_SHORT))
- type = short_integer_type_node;
-
- /* Set CONSTP if this declaration is `const', whether by
- explicit specification or via a typedef.
- Likewise for VOLATILEP. */
-
- constp = !! (specbits & RIDBIT (RID_CONST)) + TYPE_READONLY (type);
- volatilep = !! (specbits & RIDBIT (RID_VOLATILE)) + TYPE_VOLATILE (type);
- staticp = 0;
- inlinep = !! (specbits & RIDBIT (RID_INLINE));
- if (constp > 1)
- warning ("duplicate `const'");
- if (volatilep > 1)
- warning ("duplicate `volatile'");
- virtualp = specbits & RIDBIT (RID_VIRTUAL);
- if (specbits & RIDBIT (RID_STATIC))
- staticp = 1 + (decl_context == FIELD);
-
- if (virtualp && staticp == 2)
- {
- error ("member `%s' cannot be declared both virtual and static", name);
- staticp = 0;
- }
- friendp = specbits & RIDBIT (RID_FRIEND);
- specbits &= ~ (RIDBIT (RID_VIRTUAL) | RIDBIT (RID_FRIEND));
-
- /* Warn if two storage classes are given. Default to `auto'. */
-
- if (specbits)
- {
- if (specbits & RIDBIT (RID_STATIC)) nclasses++;
- if (specbits & RIDBIT (RID_EXTERN)) nclasses++;
- if (decl_context == PARM && nclasses > 0)
- error ("storage class specifiers invalid in parameter declarations");
- if (specbits & RIDBIT (RID_TYPEDEF))
- {
- if (decl_context == PARM)
- error ("typedef declaration invalid in parameter declaration");
- nclasses++;
- }
- if (specbits & RIDBIT (RID_AUTO)) nclasses++;
- if (specbits & RIDBIT (RID_REGISTER)) nclasses++;
- }
-
- /* Give error if `virtual' is used outside of class declaration. */
- if (virtualp && current_class_name == NULL_TREE)
- {
- error ("virtual outside class declaration");
- virtualp = 0;
- }
-
- /* Warn about storage classes that are invalid for certain
- kinds of declarations (parameters, typenames, etc.). */
-
- if (nclasses > 1)
- error ("multiple storage classes in declaration of `%s'", name);
- else if (decl_context != NORMAL && nclasses > 0)
- {
- if (decl_context == PARM
- && ((specbits & RIDBIT (RID_REGISTER)) | RIDBIT (RID_AUTO)))
- ;
- else if ((decl_context == FIELD
- || decl_context == TYPENAME)
- && (specbits & RIDBIT (RID_TYPEDEF)))
- {
- /* A typedef which was made in a class's scope. */
- tree loc_typedecl;
- register int i = sizeof (struct lang_decl_flags) / sizeof (int);
- register int *pi;
- struct binding_level *local_binding_level;
-
- /* keep `grokdeclarator' from thinking we are in PARM context. */
- pushlevel (0);
- /* poplevel_class may be called by grokdeclarator which is called in
- start_decl which is called below. In this case, our pushed level
- may vanish and poplevel mustn't be called. So remember what we
- have pushed and pop only if that is matched by
- current_binding_level later. mnl@dtro.e-technik.th-darmstadt.de */
- local_binding_level = current_binding_level;
-
- loc_typedecl = start_decl (declarator, declspecs, initialized, NULL_TREE);
-
- pi = (int *) permalloc (sizeof (struct lang_decl_flags));
- while (i > 0)
- pi[--i] = 0;
- DECL_LANG_SPECIFIC (loc_typedecl) = (struct lang_decl *) pi;
- /* This poplevel conflicts with the popclass over in
- grokdeclarator. See ``This popclass conflicts'' */
- if (current_binding_level == local_binding_level)
- poplevel (0, 0, 0);
-
-#if 0
- if (TREE_CODE (TREE_TYPE (loc_typedecl)) == ENUMERAL_TYPE)
- {
- tree ref = lookup_tag (ENUMERAL_TYPE, DECL_NAME (loc_typedecl), current_binding_level, 0);
- if (! ref)
- pushtag (DECL_NAME (loc_typedecl), TREE_TYPE (loc_typedecl));
- }
-#endif
-
- /* We used to check for a typedef hiding a previous decl in
- class scope, but delete_duplicate_fields_1 will now do
- that for us in the proper place. */
-
- /* We reset loc_typedecl because the IDENTIFIER_CLASS_NAME is
- set by pushdecl_class_level. */
- loc_typedecl = pushdecl_class_level (loc_typedecl);
-
- return loc_typedecl;
- }
- else if (decl_context == FIELD
- /* C++ allows static class elements */
- && (specbits & RIDBIT (RID_STATIC)))
- /* C++ also allows inlines and signed and unsigned elements,
- but in those cases we don't come in here. */
- ;
- else
- {
- if (decl_context == FIELD)
- {
- tree tmp = TREE_OPERAND (declarator, 0);
- register int op = IDENTIFIER_OPNAME_P (tmp);
- error ("storage class specified for %s `%s'",
- op ? "member operator" : "structure field",
- op ? operator_name_string (tmp) : name);
- }
- else
- error ((decl_context == PARM
- ? "storage class specified for parameter `%s'"
- : "storage class specified for typename"), name);
- specbits &= ~ (RIDBIT (RID_REGISTER) | RIDBIT (RID_AUTO)
- | RIDBIT (RID_EXTERN));
- }
- }
- else if ((specbits & RIDBIT (RID_EXTERN)) && initialized && !funcdef_flag)
- {
- if (current_binding_level == global_binding_level)
- {
- /* It's common practice (and completely legal) to have a const
- be initialized and declared extern. */
- if (! constp)
- warning ("`%s' initialized and declared `extern'", name);
- }
- else
- error ("`%s' has both `extern' and initializer", name);
- }
- else if ((specbits & RIDBIT (RID_EXTERN)) && funcdef_flag
- && current_binding_level != global_binding_level)
- error ("nested function `%s' declared `extern'", name);
- else if (current_binding_level == global_binding_level)
- {
- if (specbits & RIDBIT (RID_AUTO))
- error ("top-level declaration of `%s' specifies `auto'", name);
-#if 0
- if (specbits & RIDBIT (RID_REGISTER))
- error ("top-level declaration of `%s' specifies `register'", name);
-#endif
-#if 0
- /* I'm not sure under what circumstances we should turn
- on the extern bit, and under what circumstances we should
- warn if other bits are turned on. */
- if (decl_context == NORMAL
- && ! (specbits & RIDBIT (RID_EXTERN))
- && ! root_lang_context_p ())
- {
- specbits |= RIDBIT (RID_EXTERN);
- }
-#endif
- }
-
- /* Now figure out the structure of the declarator proper.
- Descend through it, creating more complex types, until we reach
- the declared identifier (or NULL_TREE, in an absolute declarator). */
-
- while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE)
- {
- /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
- an INDIRECT_REF (for *...),
- a CALL_EXPR (for ...(...)),
- an identifier (for the name being declared)
- or a null pointer (for the place in an absolute declarator
- where the name was omitted).
- For the last two cases, we have just exited the loop.
-
- For C++ it could also be
- a SCOPE_REF (for class :: ...). In this case, we have converted
- sensible names to types, and those are the values we use to
- qualify the member name.
- an ADDR_EXPR (for &...),
- a BIT_NOT_EXPR (for destructors)
- a TYPE_EXPR (for operator typenames)
-
- At this point, TYPE is the type of elements of an array,
- or for a function to return, or for a pointer to point to.
- After this sequence of ifs, TYPE is the type of the
- array or function or pointer, and DECLARATOR has had its
- outermost layer removed. */
-
- if (TREE_CODE (type) == ERROR_MARK)
- {
- if (TREE_CODE (declarator) == SCOPE_REF)
- declarator = TREE_OPERAND (declarator, 1);
- else
- declarator = TREE_OPERAND (declarator, 0);
- continue;
- }
- if (quals != NULL_TREE
- && (declarator == NULL_TREE
- || TREE_CODE (declarator) != SCOPE_REF))
- {
- if (ctype == NULL_TREE && TREE_CODE (type) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (type);
- if (ctype != NULL_TREE)
- {
-#if 0 /* not yet, should get fixed properly later */
- tree dummy = make_type_decl (NULL_TREE, type);
-#else
- tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
-#endif
- ctype = grok_method_quals (ctype, dummy, quals);
- type = TREE_TYPE (dummy);
- quals = NULL_TREE;
- }
- }
- switch (TREE_CODE (declarator))
- {
- case ARRAY_REF:
- maybe_globalize_type (type);
- {
- register tree itype = NULL_TREE;
- register tree size = TREE_OPERAND (declarator, 1);
-
- declarator = TREE_OPERAND (declarator, 0);
-
- /* Check for some types that there cannot be arrays of. */
-
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
- {
- error ("declaration of `%s' as array of voids", name);
- type = error_mark_node;
- }
-
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("declaration of `%s' as array of functions", name);
- type = error_mark_node;
- }
-
- /* ARM $8.4.3: Since you can't have a pointer to a reference,
- you can't have arrays of references. If we allowed them,
- then we'd be saying x[i] is legal for an array x, but
- then you'd have to ask: what does `*(x + i)' mean? */
- if (TREE_CODE (type) == REFERENCE_TYPE)
- error ("declaration of `%s' as array of references", name);
-
- if (size == error_mark_node)
- type = error_mark_node;
-
- if (type == error_mark_node)
- continue;
-
- if (size)
- {
- /* Must suspend_momentary here because the index
- type may need to live until the end of the function.
- For example, it is used in the declaration of a
- variable which requires destructing at the end of
- the function; then build_vec_delete will need this
- value. */
- int yes = suspend_momentary ();
- /* might be a cast */
- if (TREE_CODE (size) == NOP_EXPR
- && TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
- size = TREE_OPERAND (size, 0);
-
- /* If this is a template parameter, it'll be constant, but
- we don't know what the value is yet. */
- if (TREE_CODE (size) == TEMPLATE_CONST_PARM)
- goto dont_grok_size;
-
- if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
- {
- error ("size of array `%s' has non-integer type", name);
- size = integer_one_node;
- }
- if (TREE_READONLY_DECL_P (size))
- size = decl_constant_value (size);
- if (pedantic && integer_zerop (size))
- pedwarn ("ANSI C++ forbids zero-size array `%s'", name);
- if (TREE_CONSTANT (size))
- {
- if (INT_CST_LT (size, integer_zero_node))
- {
- error ("size of array `%s' is negative", name);
- size = integer_one_node;
- }
- itype = build_index_type (size_binop (MINUS_EXPR, size,
- integer_one_node));
- }
- else
- {
- if (pedantic)
- pedwarn ("ANSI C++ forbids variable-size array `%s'", name);
- dont_grok_size:
- itype =
- build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
- /* Make sure the array size remains visibly nonconstant
- even if it is (eg) a const variable with known value. */
- size_varies = 1;
- itype = variable_size (itype);
- itype = build_index_type (itype);
- }
- resume_momentary (yes);
- }
-
- /* Build the array type itself.
- Merge any constancy or volatility into the target type. */
-
- if (constp || volatilep)
- type = build_type_variant (type, constp, volatilep);
-
- type = build_cplus_array_type (type, itype);
- ctype = NULL_TREE;
- }
- break;
-
- case CALL_EXPR:
- maybe_globalize_type (type);
- {
- tree arg_types;
-
- /* Declaring a function type.
- Make sure we have a valid type for the function to return. */
-#if 0
- /* Is this an error? Should they be merged into TYPE here? */
- if (pedantic && (constp || volatilep))
- pedwarn ("function declared to return const or volatile result");
-#else
- /* Merge any constancy or volatility into the target type
- for the pointer. */
-
- if (constp || volatilep)
- {
- type = build_type_variant (type, constp, volatilep);
- if (IS_AGGR_TYPE (type))
- build_pointer_type (type);
- constp = 0;
- volatilep = 0;
- }
-#endif
-
- /* Warn about some types functions can't return. */
-
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("`%s' declared as function returning a function", name);
- type = integer_type_node;
- }
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- error ("`%s' declared as function returning an array", name);
- type = integer_type_node;
- }
-
- if (ctype == NULL_TREE
- && decl_context == FIELD
- && (friendp == 0 || dname == current_class_name))
- ctype = current_class_type;
-
- if (ctype && flags == TYPENAME_FLAG)
- TYPE_HAS_CONVERSION (ctype) = 1;
- if (ctype && constructor_name (ctype) == dname)
- {
- /* We are within a class's scope. If our declarator name
- is the same as the class name, and we are defining
- a function, then it is a constructor/destructor, and
- therefore returns a void type. */
-
- if (flags == DTOR_FLAG)
- {
- /* ANSI C++ June 5 1992 WP 12.4.1. A destructor may
- not be declared const or volatile. A destructor
- may not be static. */
- if (staticp == 2)
- error ("destructor cannot be static member function");
- if (TYPE_READONLY (type))
- {
- error ("destructors cannot be declared `const'");
- return void_type_node;
- }
- if (TYPE_VOLATILE (type))
- {
- error ("destructors cannot be declared `volatile'");
- return void_type_node;
- }
- if (decl_context == FIELD)
- {
- if (! member_function_or_else (ctype, current_class_type,
- "destructor for alien class `%s' cannot be a member"))
- return void_type_node;
- }
- }
- else /* it's a constructor. */
- {
- /* ANSI C++ June 5 1992 WP 12.1.2. A constructor may
- not be declared const or volatile. A constructor may
- not be virtual. A constructor may not be static. */
- if (staticp == 2)
- error ("constructor cannot be static member function");
- if (virtualp)
- {
- pedwarn ("constructors cannot be declared virtual");
- virtualp = 0;
- }
- if (TYPE_READONLY (type))
- {
- error ("constructors cannot be declared `const'");
- return void_type_node;
- }
- if (TYPE_VOLATILE (type))
- {
- error ("constructors cannot be declared `volatile'");
- return void_type_node;
- }
- if (specbits & ~(RIDBIT (RID_INLINE)|RIDBIT (RID_STATIC)))
- error ("return value type specifier for constructor ignored");
- type = TYPE_POINTER_TO (ctype);
- if (decl_context == FIELD)
- {
- if (! member_function_or_else (ctype, current_class_type,
- "constructor for alien class `%s' cannot be member"))
- return void_type_node;
- TYPE_HAS_CONSTRUCTOR (ctype) = 1;
- if (return_type != return_ctor)
- return NULL_TREE;
- }
- }
- if (decl_context == FIELD)
- staticp = 0;
- }
- else if (friendp && virtualp)
- {
- /* Cannot be both friend and virtual. */
- error ("virtual functions cannot be friends");
- specbits &= ~ RIDBIT (RID_FRIEND);
- }
-
- if (decl_context == NORMAL && friendp)
- error ("friend declaration not in class definition");
-
- /* Pick up type qualifiers which should be applied to `this'. */
- quals = TREE_OPERAND (declarator, 2);
-
- /* Traditionally, declaring return type float means double. */
-
- if (flag_traditional
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- {
- type = build_type_variant (double_type_node,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- }
-
- /* Construct the function type and go to the next
- inner layer of declarator. */
-
- {
- int funcdef_p;
- tree inner_parms = TREE_OPERAND (declarator, 1);
- tree inner_decl = TREE_OPERAND (declarator, 0);
-
- declarator = TREE_OPERAND (declarator, 0);
-
- if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
- inner_decl = TREE_OPERAND (inner_decl, 1);
-
- /* Say it's a definition only for the CALL_EXPR
- closest to the identifier. */
- funcdef_p =
- (inner_decl &&
- (TREE_CODE (inner_decl) == IDENTIFIER_NODE
- || TREE_CODE (inner_decl) == TYPE_EXPR)) ? funcdef_flag : 0;
-
- arg_types = grokparms (inner_parms, funcdef_p);
- }
-
- if (declarator)
- {
- /* Get past destructors, etc.
- We know we have one because FLAGS will be non-zero.
-
- Complain about improper parameter lists here. */
- if (TREE_CODE (declarator) == BIT_NOT_EXPR)
- {
- declarator = TREE_OPERAND (declarator, 0);
-
- if (strict_prototype == 0 && arg_types == NULL_TREE)
- arg_types = void_list_node;
- else if (arg_types == NULL_TREE
- || arg_types != void_list_node)
- {
- error ("destructors cannot be specified with parameters");
- arg_types = void_list_node;
- }
- }
- }
- /* the top level const or volatile is attached semantically only
- to the function not the actual type. */
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
- {
- int constp = TYPE_READONLY (type);
- int volatilep = TYPE_VOLATILE (type);
- type = build_function_type (TYPE_MAIN_VARIANT (type),
- flag_traditional
- ? 0
- : arg_types);
- type = build_type_variant (type, constp, volatilep);
- }
- else
- type = build_function_type (type,
- flag_traditional
- ? 0
- : arg_types);
- }
- break;
-
- case ADDR_EXPR:
- case INDIRECT_REF:
- maybe_globalize_type (type);
-
- /* Filter out pointers-to-references and references-to-references.
- We can get these if a TYPE_DECL is used. */
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- error ("cannot declare %s to references",
- TREE_CODE (declarator) == ADDR_EXPR
- ? "references" : "pointers");
- declarator = TREE_OPERAND (declarator, 0);
- continue;
- }
-
- /* Merge any constancy or volatility into the target type
- for the pointer. */
-
- if (constp || volatilep)
- {
- type = build_type_variant (type, constp, volatilep);
- if (IS_AGGR_TYPE (type))
- build_pointer_type (type);
- constp = 0;
- volatilep = 0;
- }
-
- if (TREE_CODE (declarator) == ADDR_EXPR)
- {
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("cannot declare references to functions; use pointer to function instead");
- type = build_pointer_type (type);
- }
- else
- {
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
- error ("invalid type: `void &'");
- else
- type = build_reference_type (type);
- }
- }
- else
- type = build_pointer_type (type);
-
- /* Process a list of type modifier keywords (such as
- const or volatile) that were given inside the `*' or `&'. */
-
- if (TREE_TYPE (declarator))
- {
- register tree typemodlist;
- int erred = 0;
- for (typemodlist = TREE_TYPE (declarator); typemodlist;
- typemodlist = TREE_CHAIN (typemodlist))
- {
- if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
- constp++;
- else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
- volatilep++;
- else if (!erred)
- {
- erred = 1;
- error ("invalid type modifier within %s declarator",
- TREE_CODE (declarator) == ADDR_EXPR
- ? "reference" : "pointer");
- }
- }
- if (constp > 1)
- warning ("duplicate `const'");
- if (volatilep > 1)
- warning ("duplicate `volatile'");
- }
- declarator = TREE_OPERAND (declarator, 0);
- ctype = NULL_TREE;
- break;
-
- case SCOPE_REF:
- {
- /* We have converted type names to NULL_TREE if the
- name was bogus, or to a _TYPE node, if not.
-
- The variable CTYPE holds the type we will ultimately
- resolve to. The code here just needs to build
- up appropriate member types. */
- tree sname = TREE_OPERAND (declarator, 1);
- /* Destructors can have their visibilities changed as well. */
- if (TREE_CODE (sname) == BIT_NOT_EXPR)
- sname = TREE_OPERAND (sname, 0);
-
- if (TREE_COMPLEXITY (declarator) == 0)
- /* This needs to be here, in case we are called
- multiple times. */ ;
- else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
- /* don't fall out into global scope. Hides real bug? --eichin */ ;
- else if (TREE_COMPLEXITY (declarator) == current_class_depth)
- {
- TREE_COMPLEXITY (declarator) -= 1;
- /* This popclass conflicts with the poplevel over in
- grokdeclarator. See ``This poplevel conflicts'' */
- popclass (1);
- }
- else
- my_friendly_abort (16);
-
- if (TREE_OPERAND (declarator, 0) == NULL_TREE)
- {
- /* We had a reference to a global decl, or
- perhaps we were given a non-aggregate typedef,
- in which case we cleared this out, and should just
- keep going as though it wasn't there. */
- declarator = sname;
- continue;
- }
- ctype = TREE_OPERAND (declarator, 0);
-
- if (sname == NULL_TREE)
- goto done_scoping;
-
- if (TREE_CODE (sname) == IDENTIFIER_NODE)
- {
- /* This is the `standard' use of the scoping operator:
- basetype :: member . */
-
- if (TYPE_MAIN_VARIANT (ctype) == current_class_type || friendp)
- {
- if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type), TYPE_ARG_TYPES (type));
- else
- {
- if (TYPE_MAIN_VARIANT (ctype) != current_class_type)
- {
- error ("cannot declare member `%s::%s' within this class",
- TYPE_NAME_STRING (ctype), name);
- return void_type_node;
- }
- else if (extra_warnings)
- warning ("extra qualification `%s' on member `%s' ignored",
- TYPE_NAME_STRING (ctype), name);
- type = build_offset_type (ctype, type);
- }
- }
- else if (TYPE_SIZE (ctype) != NULL_TREE
- || (specbits & RIDBIT (RID_TYPEDEF)))
- {
- tree t;
- /* have to move this code elsewhere in this function.
- this code is used for i.e., typedef int A::M; M *pm; */
-
- if (explicit_int == -1 && decl_context == FIELD
- && funcdef_flag == 0)
- {
- /* The code in here should only be used to build
- stuff that will be grokked as visibility decls. */
- t = lookup_field (ctype, sname, 0, 0);
- if (t)
- {
- t = build_lang_field_decl (FIELD_DECL, build_nt (SCOPE_REF, ctype, t), type);
- DECL_INITIAL (t) = init;
- return t;
- }
- /* No such field, try member functions. */
- t = lookup_fnfields (TYPE_BINFO (ctype), sname, 0);
- if (t)
- {
- if (flags == DTOR_FLAG)
- t = TREE_VALUE (t);
- else if (CLASSTYPE_METHOD_VEC (ctype)
- && TREE_VALUE (t) == TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), 0))
- {
- /* Don't include destructor with constructors. */
- t = DECL_CHAIN (TREE_VALUE (t));
- if (t == NULL_TREE)
- error ("class `%s' does not have any constructors", IDENTIFIER_POINTER (sname));
- t = build_tree_list (NULL_TREE, t);
- }
- t = build_lang_field_decl (FIELD_DECL, build_nt (SCOPE_REF, ctype, t), type);
- DECL_INITIAL (t) = init;
- return t;
- }
-
- if (flags == TYPENAME_FLAG)
- error_with_aggr_type (ctype, "type conversion is not a member of structure `%s'");
- else
- error ("field `%s' is not a member of structure `%s'",
- IDENTIFIER_POINTER (sname),
- TYPE_NAME_STRING (ctype));
- }
- if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type), TYPE_ARG_TYPES (type));
- else
- {
- if (current_class_type)
- {
- if (TYPE_MAIN_VARIANT (ctype) != current_class_type)
- {
- error ("cannot declare member `%s::%s' within this class",
- TYPE_NAME_STRING (ctype), name);
- return void_type_node;
- }
- else if (extra_warnings)
- warning ("extra qualification `%s' on member `%s' ignored",
- TYPE_NAME_STRING (ctype), name);
- }
- type = build_offset_type (ctype, type);
- }
- }
- else if (uses_template_parms (ctype))
- {
- enum tree_code c;
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- c = FUNCTION_DECL;
- }
- }
- else
- sorry ("structure `%s' not yet defined",
- TYPE_NAME_STRING (ctype));
- declarator = sname;
- }
- else if (TREE_CODE (sname) == TYPE_EXPR)
- {
- /* A TYPE_EXPR will change types out from under us.
- So do the TYPE_EXPR now, and make this SCOPE_REF
- inner to the TYPE_EXPR's CALL_EXPR.
-
- This does not work if we don't get a CALL_EXPR back.
- I did not think about error recovery, hence the
- my_friendly_abort. */
-
- /* Get the CALL_EXPR. */
- sname = grokoptypename (sname, 0);
- my_friendly_assert (TREE_CODE (sname) == CALL_EXPR, 157);
- type = TREE_TYPE (TREE_OPERAND (sname, 0));
- /* Scope the CALL_EXPR's name. */
- TREE_OPERAND (declarator, 1) = TREE_OPERAND (sname, 0);
- /* Put the SCOPE_EXPR in the CALL_EXPR's innermost position. */
- TREE_OPERAND (sname, 0) = declarator;
- /* Now work from the CALL_EXPR. */
- declarator = sname;
- continue;
- }
- else if (TREE_CODE (sname) == SCOPE_REF)
- my_friendly_abort (17);
- else
- {
- done_scoping:
- declarator = TREE_OPERAND (declarator, 1);
- if (declarator && TREE_CODE (declarator) == CALL_EXPR)
- /* In this case, we will deal with it later. */
- ;
- else
- {
- if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), TREE_TYPE (type), TYPE_ARG_TYPES (type));
- else
- type = build_offset_type (ctype, type);
- }
- }
- }
- break;
-
- case BIT_NOT_EXPR:
- declarator = TREE_OPERAND (declarator, 0);
- break;
-
- case TYPE_EXPR:
- declarator = grokoptypename (declarator, 0);
- if (explicit_int != -1)
- if (comp_target_types (type,
- TREE_TYPE (TREE_OPERAND (declarator, 0)),
- 1) == 0)
- error ("type conversion function declared to return incongruent type");
- else
- pedwarn ("return type specified for type conversion function");
- type = TREE_TYPE (TREE_OPERAND (declarator, 0));
- maybe_globalize_type (type);
- break;
-
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- declarator = NULL_TREE;
- break;
-
- case ERROR_MARK:
- declarator = NULL_TREE;
- break;
-
- default:
- my_friendly_abort (158);
- }
- }
-
- /* Now TYPE has the actual type. */
-
- /* If this is declaring a typedef name, return a TYPE_DECL. */
-
- if (specbits & RIDBIT (RID_TYPEDEF))
- {
- tree decl;
-
- /* Note that the grammar rejects storage classes
- in typenames, fields or parameters. */
- if (constp || volatilep)
- type = build_type_variant (type, constp, volatilep);
-
- /* If the user declares "struct {...} foo" then `foo' will have
- an anonymous name. Fill that name in now. Nothing can
- refer to it, so nothing needs know about the name change.
- The TYPE_NAME field was filled in by build_struct_xref. */
- if (TYPE_NAME (type)
- && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
- {
- /* replace the anonymous name with the real name everywhere. */
- lookup_tag_reverse (type, declarator);
- TYPE_IDENTIFIER (type) = declarator;
- }
-
-#if 0 /* not yet, should get fixed properly later */
- decl = make_type_decl (declarator, type);
-#else
- decl = build_decl (TYPE_DECL, declarator, type);
-#endif
- if (quals)
- {
- if (ctype == NULL_TREE)
- {
- if (TREE_CODE (type) != METHOD_TYPE)
- error_with_decl (decl, "invalid type qualifier for non-method type");
- else
- ctype = TYPE_METHOD_BASETYPE (type);
- }
- if (ctype != NULL_TREE)
- grok_method_quals (ctype, decl, quals);
- }
-
- if ((specbits & RIDBIT (RID_SIGNED))
- || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
- C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
-
- return decl;
- }
-
- /* Detect the case of an array type of unspecified size
- which came, as such, direct from a typedef name.
- We must copy the type, so that each identifier gets
- a distinct type, so that each identifier's size can be
- controlled separately by its own initializer. */
-
- if (type == typedef_type && TREE_CODE (type) == ARRAY_TYPE
- && TYPE_DOMAIN (type) == NULL_TREE)
- {
- type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type));
- }
-
- /* If this is a type name (such as, in a cast or sizeof),
- compute the type and return it now. */
-
- if (decl_context == TYPENAME)
- {
- /* Note that the grammar rejects storage classes
- in typenames, fields or parameters. */
- if (constp || volatilep)
- type = build_type_variant (type, constp, volatilep);
-
- /* Special case: "friend class foo" looks like a TYPENAME context. */
- if (friendp)
- {
- /* A friendly class? */
- if (current_class_type)
- make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
- else
- error("trying to make class `%s' a friend of global scope",
- TYPE_NAME_STRING (type));
- type = void_type_node;
- }
- else if (quals)
- {
-#if 0 /* not yet, should get fixed properly later */
- tree dummy = make_type_decl (declarator, type);
-#else
- tree dummy = build_decl (TYPE_DECL, declarator, type);
-#endif
- if (ctype == NULL_TREE)
- {
- my_friendly_assert (TREE_CODE (type) == METHOD_TYPE, 159);
- ctype = TYPE_METHOD_BASETYPE (type);
- }
- grok_method_quals (ctype, dummy, quals);
- type = TREE_TYPE (dummy);
- }
-
- return type;
- }
-
- /* `void' at top level (not within pointer)
- is allowed only in typedefs or type names.
- We don't complain about parms either, but that is because
- a better error message can be made later. */
-
- if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM)
- {
- if (declarator != NULL_TREE
- && TREE_CODE (declarator) == IDENTIFIER_NODE)
- {
- if (IDENTIFIER_OPNAME_P (declarator))
- error ("operator `%s' declared void",
- operator_name_string (declarator));
- else
- error ("variable or field `%s' declared void", name);
- }
- else
- error ("variable or field declared void");
- type = integer_type_node;
- }
-
- /* Now create the decl, which may be a VAR_DECL, a PARM_DECL
- or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
-
- {
- register tree decl;
-
- if (decl_context == PARM)
- {
- tree parmtype = type;
-
- if (ctype)
- error ("cannot use `::' in parameter declaration");
- bad_specifiers ("parameter", virtualp, quals != NULL_TREE,
- friendp, raises != NULL_TREE);
-
- /* A parameter declared as an array of T is really a pointer to T.
- One declared as a function is really a pointer to a function.
- One declared as a member is really a pointer to member.
-
- Don't be misled by references. */
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- if (parmtype == type)
- {
- /* Transfer const-ness of array into that of type
- pointed to. */
- type = build_pointer_type
- (build_type_variant (TREE_TYPE (type), constp, volatilep));
- volatilep = constp = 0;
- }
- else
- type = build_pointer_type (TREE_TYPE (type));
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_pointer_type (type);
- else if (TREE_CODE (type) == OFFSET_TYPE)
- type = build_pointer_type (type);
-
- if (TREE_CODE (parmtype) == REFERENCE_TYPE)
- {
- /* Transfer const-ness of reference into that of type pointed to. */
- type = build_type_variant (build_reference_type (type), constp, volatilep);
- constp = volatilep = 0;
- }
-
- decl = build_decl (PARM_DECL, declarator, type);
-
- /* Compute the type actually passed in the parmlist,
- for the case where there is no prototype.
- (For example, shorts and chars are passed as ints.)
- When there is a prototype, this is overridden later. */
-
- DECL_ARG_TYPE (decl) = type;
- if (TYPE_MAIN_VARIANT (type) == float_type_node)
- DECL_ARG_TYPE (decl) = build_type_variant (double_type_node,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- else if (C_PROMOTING_INTEGER_TYPE_P (type))
- {
- tree argtype;
-
- /* Retain unsignedness if traditional or if not really
- getting wider. */
- if (TREE_UNSIGNED (type)
- && (flag_traditional
- || TYPE_PRECISION (type)
- == TYPE_PRECISION (integer_type_node)))
- argtype = unsigned_type_node;
- else
- argtype = integer_type_node;
- DECL_ARG_TYPE (decl) = build_type_variant (argtype,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- }
- }
- else if (decl_context == FIELD)
- {
- if (type == error_mark_node)
- {
- /* Happens when declaring arrays of sizes which
- are error_mark_node, for example. */
- decl = NULL_TREE;
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- int publicp = 0;
-
- if (friendp == 0)
- {
- if (ctype == NULL_TREE)
- ctype = current_class_type;
-
- if (ctype == NULL_TREE)
- {
- register int op = IDENTIFIER_OPNAME_P (declarator);
- error ("can't make %s `%s' into a method -- not in a class",
- op ? "operator" : "function",
- op ? operator_name_string (declarator) : IDENTIFIER_POINTER (declarator));
- return void_type_node;
- }
-
- /* ``A union may [ ... ] not [ have ] virtual functions.''
- ARM 9.5 */
- if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
- {
- error ("function `%s' declared virtual inside a union",
- IDENTIFIER_POINTER (declarator));
- return void_type_node;
- }
-
- /* Don't convert type of operators new and delete to
- METHOD_TYPE; they remain FUNCTION_TYPEs. */
- if (staticp < 2
- && declarator != ansi_opname[(int) NEW_EXPR]
- && declarator != ansi_opname[(int) DELETE_EXPR])
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type), TYPE_ARG_TYPES (type));
- }
-
- /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
- publicp = ((specbits & RIDBIT (RID_EXTERN))
- || (ctype != NULL_TREE && funcdef_flag >= 0)
-#if 0
- /* These are replicated in each object, so we shouldn't
- set TREE_PUBLIC. */
- || (friendp
- && !(specbits & RIDBIT (RID_STATIC))
- && !(specbits & RIDBIT (RID_INLINE)))
-#endif
- );
- decl = grokfndecl (ctype, type, declarator,
- virtualp, flags, quals,
- raises, friendp ? -1 : 0, publicp);
- DECL_INLINE (decl) = inlinep;
- }
- else if (TREE_CODE (type) == METHOD_TYPE)
- {
- /* All method decls are public, so tell grokfndecl to set
- TREE_PUBLIC, also. */
- decl = grokfndecl (ctype, type, declarator,
- virtualp, flags, quals,
- raises, friendp ? -1 : 0, 1);
- DECL_INLINE (decl) = inlinep;
- }
- else if (TREE_CODE (type) == RECORD_TYPE
- && CLASSTYPE_DECLARED_EXCEPTION (type))
- {
- /* Handle a class-local exception declaration. */
- decl = build_lang_field_decl (VAR_DECL, declarator, type);
- if (ctype == NULL_TREE)
- ctype = current_class_type;
- finish_exception_decl (TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL
- ? TYPE_IDENTIFIER (ctype) : TYPE_NAME (ctype), decl);
- return void_type_node;
- }
- else if (TYPE_SIZE (type) == NULL_TREE && !staticp
- && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
- {
- if (declarator)
- error ("field `%s' has incomplete type",
- IDENTIFIER_POINTER (declarator));
- else
- error ("field has incomplete type");
-
- /* If we're instantiating a template, tell them which
- instantiation made the field's type be incomplete. */
- if (current_class_type
- && IDENTIFIER_TEMPLATE (current_class_type)
- && declspecs && TREE_VALUE (declspecs)
- && TREE_TYPE (TREE_VALUE (declspecs)) == type)
- error (" in instantiation of template `%s'",
- TYPE_NAME_STRING (current_class_type));
-
- type = error_mark_node;
- decl = NULL_TREE;
- }
- else
- {
- if (friendp)
- {
- if (declarator)
- error ("`%s' is neither function nor method; cannot be declared friend",
- IDENTIFIER_POINTER (declarator));
- else
- {
- error ("invalid friend declaration");
- return void_type_node;
- }
- friendp = 0;
- }
- decl = NULL_TREE;
- }
-
- if (friendp)
- {
- tree t;
-
- /* Friends are treated specially. */
- if (ctype == current_class_type)
- warning ("member functions are implicitly friends of their class");
- else if (decl && (t = DECL_NAME (decl)))
- {
- /* ARM $13.4.3 */
- if (t == ansi_opname[(int) MODIFY_EXPR])
- pedwarn ("operator `=' must be a member function");
- else
- return do_friend (ctype, declarator, decl,
- last_function_parms, flags, quals);
- }
- else return void_type_node;
- }
-
- /* Structure field. It may not be a function, except for C++ */
-
- if (decl == NULL_TREE)
- {
- bad_specifiers ("field", virtualp, quals != NULL_TREE,
- friendp, raises != NULL_TREE);
-
- /* ANSI C++ June 5 1992 WP 9.2.2 and 9.4.2. A member-declarator
- cannot have an initializer, and a static member declaration must
- be defined elsewhere. */
- if (initialized)
- {
- if (staticp)
- error ("static member `%s' must be defined separately from its declaration",
- IDENTIFIER_POINTER (declarator));
- /* Note that initialization of const members is not
- mentioned in the ARM or draft ANSI standard explicitly,
- and it appears to be in common practice. However,
- reading the draft section 9.2.2, it does say that a
- member declarator can't have an initializer--it does
- not except constant members, which also qualify as
- member-declarators. */
- else if (!pedantic && (!constp || flag_ansi))
- warning ("ANSI C++ forbids initialization of %s `%s'",
- constp ? "const member" : "member",
- IDENTIFIER_POINTER (declarator));
- }
-
- if (staticp || (constp && initialized))
- {
- /* C++ allows static class members.
- All other work for this is done by grokfield.
- This VAR_DECL is built by build_lang_field_decl.
- All other VAR_DECLs are built by build_decl. */
- decl = build_lang_field_decl (VAR_DECL, declarator, type);
- if (staticp || TREE_CODE (type) == ARRAY_TYPE)
- TREE_STATIC (decl) = 1;
- /* In class context, static means public visibility. */
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = !initialized;
- }
- else
- decl = build_lang_field_decl (FIELD_DECL, declarator, type);
- }
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
- {
- int was_overloaded = 0;
- tree original_name = declarator;
- int publicp = 0;
-
- if (! declarator) return NULL_TREE;
-
- if (specbits & (RIDBIT (RID_AUTO) | RIDBIT (RID_REGISTER)))
- error ("invalid storage class for function `%s'", name);
- /* Function declaration not at top level.
- Storage classes other than `extern' are not allowed
- and `extern' makes no difference. */
- if (current_binding_level != global_binding_level
- && (specbits & (RIDBIT (RID_STATIC) | RIDBIT (RID_INLINE)))
- && pedantic)
- pedwarn ("invalid storage class for function `%s'", name);
-
- if (ctype == NULL_TREE)
- {
- if (virtualp)
- {
- error ("virtual non-class function `%s'", name);
- virtualp = 0;
- }
-
- /* ARM $13.4.3 */
- /* XXX: It's likely others should also be forbidden. (bpk) */
- if (declarator == ansi_opname[(int) MODIFY_EXPR])
- warning ("operator `=' must be a member function");
-
- if (current_lang_name == lang_name_cplusplus
- && ! (IDENTIFIER_LENGTH (original_name) == 4
- && IDENTIFIER_POINTER (original_name)[0] == 'm'
- && strcmp (IDENTIFIER_POINTER (original_name), "main") == 0)
- && ! (IDENTIFIER_LENGTH (original_name) > 10
- && IDENTIFIER_POINTER (original_name)[0] == '_'
- && IDENTIFIER_POINTER (original_name)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (original_name)+2, "builtin_", 8) == 0))
- {
- /* Plain overloading: will not be grok'd by grokclassfn. */
- declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
- was_overloaded = 1;
- }
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type), TYPE_ARG_TYPES (type));
-
- /* Record presence of `static'. In C++, `inline' is like `static'.
- Methods of classes should be public, unless we're dropping them
- into some other file, so we don't clear TREE_PUBLIC for them. */
- publicp
- = ((ctype
- && ! CLASSTYPE_INTERFACE_UNKNOWN (ctype)
- && ! CLASSTYPE_INTERFACE_ONLY (ctype))
- || !(specbits & (RIDBIT (RID_STATIC)
- | RIDBIT (RID_INLINE))));
-
- decl = grokfndecl (ctype, type, original_name,
- virtualp, flags, quals,
- raises,
- processing_template_decl ? 0 : friendp ? 2 : 1,
- publicp);
-
- if (ctype == NULL_TREE)
- DECL_ASSEMBLER_NAME (decl) = declarator;
-
- if (staticp == 1)
- {
- int illegal_static = 0;
-
- /* Don't allow a static member function in a class, and forbid
- declaring main to be static. */
- if (TREE_CODE (type) == METHOD_TYPE)
- {
- error_with_decl (decl,
- "cannot declare member function `%s' to have static linkage");
- illegal_static = 1;
- }
- else if (! was_overloaded
- && ! ctype
- && IDENTIFIER_LENGTH (original_name) == 4
- && IDENTIFIER_POINTER (original_name)[0] == 'm'
- && ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
- {
- error ("cannot declare function `main' to have static linkage");
- illegal_static = 1;
- }
-
- if (illegal_static)
- {
- staticp = 0;
- specbits &= ~ RIDBIT (RID_STATIC);
- }
- }
-
- /* Record presence of `inline', if it is reasonable. */
- if (inlinep)
- {
- tree last = tree_last (TYPE_ARG_TYPES (type));
-
- if (! was_overloaded
- && ! ctype
- && ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
- warning ("cannot inline function `main'");
- else if (last && last != void_list_node)
- warning ("inline declaration ignored for function with `...'");
- else
- /* Assume that otherwise the function can be inlined. */
- DECL_INLINE (decl) = 1;
-
- if (specbits & RIDBIT (RID_EXTERN))
- {
- current_extern_inline = 1;
- if (pedantic)
- error ("ANSI C++ does not permit `extern inline'");
- else if (flag_ansi)
- warning ("ANSI C++ does not permit `extern inline'");
- }
- }
- if (was_overloaded)
- DECL_OVERLOADED (decl) = 1;
- }
- else
- {
- /* It's a variable. */
-
- bad_specifiers ("variable", virtualp, quals != NULL_TREE,
- friendp, raises != NULL_TREE);
- if (inlinep)
- warning ("variable declared `inline'");
-
- /* An uninitialized decl with `extern' is a reference. */
- decl = grokvardecl (type, declarator, specbits, initialized);
- if (ctype)
- {
- if (staticp == 1)
- {
- error ("cannot declare member `%s' to have static linkage",
- lang_printable_name (decl));
- staticp = 0;
- specbits &= ~ RIDBIT (RID_STATIC);
- }
- if (specbits & RIDBIT (RID_EXTERN))
- {
- error ("cannot explicitly declare member `%s' to have extern linkage",
- lang_printable_name (decl));
- specbits &= ~ RIDBIT (RID_EXTERN);
- }
- }
- }
-
- /* Record `register' declaration for warnings on &
- and in case doing stupid register allocation. */
-
- if (specbits & RIDBIT (RID_REGISTER))
- DECL_REGISTER (decl) = 1;
-
- /* Record constancy and volatility. */
-
- if (constp)
- TREE_READONLY (decl) = TREE_CODE (type) != REFERENCE_TYPE;
- if (volatilep)
- {
- TREE_SIDE_EFFECTS (decl) = 1;
- TREE_THIS_VOLATILE (decl) = 1;
- }
-
- return decl;
- }
-}
-
-/* Tell if a parmlist/exprlist looks like an exprlist or a parmlist.
- An empty exprlist is a parmlist. An exprlist which
- contains only identifiers at the global level
- is a parmlist. Otherwise, it is an exprlist. */
-int
-parmlist_is_exprlist (exprs)
- tree exprs;
-{
- if (exprs == NULL_TREE || TREE_PARMLIST (exprs))
- return 0;
-
- if (current_binding_level == global_binding_level)
- {
- /* At the global level, if these are all identifiers,
- then it is a parmlist. */
- while (exprs)
- {
- if (TREE_CODE (TREE_VALUE (exprs)) != IDENTIFIER_NODE)
- return 1;
- exprs = TREE_CHAIN (exprs);
- }
- return 0;
- }
- return 1;
-}
-
-/* Make sure that the this list of PARMS has a chance of being
- grokked by `grokparms'.
-
- @@ This is really weak, but the grammar does not allow us
- @@ to easily reject things that this has to catch as syntax errors. */
-static int
-parmlist_is_random (parms)
- tree parms;
-{
- if (parms == NULL_TREE)
- return 0;
-
- if (TREE_CODE (parms) != TREE_LIST)
- return 1;
-
- while (parms)
- {
- if (parms == void_list_node)
- return 0;
-
- if (TREE_CODE (TREE_VALUE (parms)) != TREE_LIST)
- return 1;
- /* Don't get faked out by overloaded functions, which
- masquerade as TREE_LISTs! */
- if (TREE_TYPE (TREE_VALUE (parms)) == unknown_type_node)
- return 1;
- parms = TREE_CHAIN (parms);
- }
- return 0;
-}
-
-/* Subroutine of `grokparms'. In a fcn definition, arg types must
- be complete.
-
- C++: also subroutine of `start_function'. */
-static void
-require_complete_types_for_parms (parms)
- tree parms;
-{
- while (parms)
- {
- tree type = TREE_TYPE (parms);
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- if (DECL_NAME (parms))
- error ("parameter `%s' has incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (parms)));
- else
- error ("parameter has incomplete type");
- TREE_TYPE (parms) = error_mark_node;
- }
-#if 0
- /* If the arg types are incomplete in a declaration,
- they must include undefined tags.
- These tags can never be defined in the scope of the declaration,
- so the types can never be completed,
- and no call can be compiled successfully. */
- /* This is not the right behavior for C++, but not having
- it is also probably wrong. */
- else
- {
- /* Now warn if is a pointer to an incomplete type. */
- while (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
- type = TYPE_MAIN_VARIANT (type);
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- if (DECL_NAME (parm) != NULL_TREE)
- warning ("parameter `%s' points to incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (parm)));
- else
- warning ("parameter points to incomplete type");
- }
- }
-#endif
- parms = TREE_CHAIN (parms);
- }
-}
-
-/* Decode the list of parameter types for a function type.
- Given the list of things declared inside the parens,
- return a list of types.
-
- The list we receive can have three kinds of elements:
- an IDENTIFIER_NODE for names given without types,
- a TREE_LIST node for arguments given as typespecs or names with typespecs,
- or void_type_node, to mark the end of an argument list
- when additional arguments are not permitted (... was not used).
-
- FUNCDEF_FLAG is nonzero for a function definition, 0 for
- a mere declaration. A nonempty identifier-list gets an error message
- when FUNCDEF_FLAG is zero.
- If FUNCDEF_FLAG is 1, then parameter types must be complete.
- If FUNCDEF_FLAG is -1, then parameter types may be incomplete.
-
- If all elements of the input list contain types,
- we return a list of the types.
- If all elements contain no type (except perhaps a void_type_node
- at the end), we return a null list.
- If some have types and some do not, it is an error, and we
- return a null list.
-
- Also set last_function_parms to either
- a list of names (IDENTIFIER_NODEs) or a chain of PARM_DECLs.
- A list of names is converted to a chain of PARM_DECLs
- by store_parm_decls so that ultimately it is always a chain of decls.
-
- Note that in C++, parameters can take default values. These default
- values are in the TREE_PURPOSE field of the TREE_LIST. It is
- an error to specify default values which are followed by parameters
- that have no default values, or an ELLIPSES. For simplicities sake,
- only parameters which are specified with their types can take on
- default values. */
-
-static tree
-grokparms (first_parm, funcdef_flag)
- tree first_parm;
- int funcdef_flag;
-{
- tree result = NULL_TREE;
- tree decls = NULL_TREE;
-
- if (first_parm != NULL_TREE
- && TREE_CODE (TREE_VALUE (first_parm)) == IDENTIFIER_NODE)
- {
- if (! funcdef_flag)
- warning ("parameter names (without types) in function declaration");
- last_function_parms = first_parm;
- return NULL_TREE;
- }
- else
- {
- /* Types were specified. This is a list of declarators
- each represented as a TREE_LIST node. */
- register tree parm, chain;
- int any_init = 0, any_error = 0, saw_void = 0;
-
- if (first_parm != NULL_TREE)
- {
- tree last_result = NULL_TREE;
- tree last_decl = NULL_TREE;
-
- for (parm = first_parm; parm != NULL_TREE; parm = chain)
- {
- tree type, list_node = parm;
- register tree decl = TREE_VALUE (parm);
- tree init = TREE_PURPOSE (parm);
-
- chain = TREE_CHAIN (parm);
- /* @@ weak defense against parse errors. */
- if (decl != void_type_node && TREE_CODE (decl) != TREE_LIST)
- {
- /* Give various messages as the need arises. */
- if (TREE_CODE (decl) == STRING_CST)
- error ("invalid string constant `%s'",
- TREE_STRING_POINTER (decl));
- else if (TREE_CODE (decl) == INTEGER_CST)
- error ("invalid integer constant in parameter list, did you forget to give parameter name?");
- continue;
- }
-
- if (decl != void_type_node)
- {
- /* @@ May need to fetch out a `raises' here. */
- decl = grokdeclarator (TREE_VALUE (decl),
- TREE_PURPOSE (decl),
- PARM, init != NULL_TREE, NULL_TREE);
- if (! decl)
- continue;
- type = TREE_TYPE (decl);
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
- decl = void_type_node;
- else if (TREE_CODE (type) == METHOD_TYPE)
- {
- if (DECL_NAME (decl))
- /* Cannot use `error_with_decl' here because
- we don't have DECL_CONTEXT set up yet. */
- error ("parameter `%s' invalidly declared method type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- else
- error ("parameter invalidly declared method type");
- type = build_pointer_type (type);
- TREE_TYPE (decl) = type;
- }
- else if (TREE_CODE (type) == OFFSET_TYPE)
- {
- if (DECL_NAME (decl))
- error ("parameter `%s' invalidly declared offset type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- else
- error ("parameter invalidly declared offset type");
- type = build_pointer_type (type);
- TREE_TYPE (decl) = type;
- }
- else if (TREE_CODE (type) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (type)
- && CLASSTYPE_ABSTRACT_VIRTUALS (type))
- {
- abstract_virtuals_error (decl, type);
- any_error = 1; /* seems like a good idea */
- }
- }
-
- if (decl == void_type_node)
- {
- if (result == NULL_TREE)
- {
- result = void_list_node;
- last_result = result;
- }
- else
- {
- TREE_CHAIN (last_result) = void_list_node;
- last_result = void_list_node;
- }
- saw_void = 1;
- if (chain
- && (chain != void_list_node || TREE_CHAIN (chain)))
- error ("`void' in parameter list must be entire list");
- break;
- }
-
- /* Since there is a prototype, args are passed in their own types. */
- DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
-#ifdef PROMOTE_PROTOTYPES
- if (C_PROMOTING_INTEGER_TYPE_P (type))
- DECL_ARG_TYPE (decl) = integer_type_node;
-#endif
- if (!any_error)
- {
- if (init)
- {
- any_init++;
- if (TREE_CODE (init) == SAVE_EXPR)
- PARM_DECL_EXPR (init) = 1;
- else if (TREE_CODE (init) == VAR_DECL)
- {
- if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init)))
- {
- /* ``Local variables may not be used in default
- argument expressions.'' dpANSI C++ 8.2.6 */
- /* If extern int i; within a function is not
- considered a local variable, then this code is
- wrong. */
- error_with_decl (init, "local variable `%s' may not be used as a default argument");
- any_error = 1;
- }
- else if (TREE_READONLY_DECL_P (init))
- init = decl_constant_value (init);
- }
- else
- init = require_instantiated_type (type, init, integer_zero_node);
- }
- else if (any_init)
- {
- error ("all trailing parameters must have default arguments");
- any_error = 1;
- }
- }
- else
- init = NULL_TREE;
-
- if (decls == NULL_TREE)
- {
- decls = decl;
- last_decl = decls;
- }
- else
- {
- TREE_CHAIN (last_decl) = decl;
- last_decl = decl;
- }
- if (TREE_PERMANENT (list_node))
- {
- TREE_PURPOSE (list_node) = init;
- TREE_VALUE (list_node) = type;
- TREE_CHAIN (list_node) = NULL_TREE;
- }
- else
- list_node = saveable_tree_cons (init, type, NULL_TREE);
- if (result == NULL_TREE)
- {
- result = list_node;
- last_result = result;
- }
- else
- {
- TREE_CHAIN (last_result) = list_node;
- last_result = list_node;
- }
- }
- if (last_result)
- TREE_CHAIN (last_result) = NULL_TREE;
- /* If there are no parameters, and the function does not end
- with `...', then last_decl will be NULL_TREE. */
- if (last_decl != NULL_TREE)
- TREE_CHAIN (last_decl) = NULL_TREE;
- }
- }
-
- last_function_parms = decls;
-
- /* In a fcn definition, arg types must be complete. */
- if (funcdef_flag > 0)
- require_complete_types_for_parms (last_function_parms);
-
- return result;
-}
-
-/* These memoizing functions keep track of special properties which
- a class may have. `grok_ctor_properties' notices whether a class
- has a constructor of the for X(X&), and also complains
- if the class has a constructor of the form X(X).
- `grok_op_properties' takes notice of the various forms of
- operator= which are defined, as well as what sorts of type conversion
- may apply. Both functions take a FUNCTION_DECL as an argument. */
-void
-grok_ctor_properties (ctype, decl)
- tree ctype, decl;
-{
- tree parmtypes = FUNCTION_ARG_CHAIN (decl);
- tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
-
- if (parmtypes && TREE_CHAIN (parmtypes)
- && TREE_CODE (TREE_VALUE (TREE_CHAIN (parmtypes))) == REFERENCE_TYPE
- && TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (TREE_VALUE (TREE_CHAIN (parmtypes)))))
- {
- parmtypes = TREE_CHAIN (parmtypes);
- parmtype = TREE_VALUE (parmtypes);
- }
-
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype)
- {
- if (TREE_CHAIN (parmtypes) == NULL_TREE
- || TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
- {
- TYPE_HAS_INIT_REF (ctype) = 1;
- TYPE_GETS_INIT_REF (ctype) = 1;
- if (TYPE_READONLY (TREE_TYPE (parmtype)))
- TYPE_GETS_CONST_INIT_REF (ctype) = 1;
- }
- else
- TYPE_GETS_INIT_AGGR (ctype) = 1;
- }
- else if (TYPE_MAIN_VARIANT (parmtype) == ctype)
- {
- if (TREE_CHAIN (parmtypes) != NULL_TREE
- && TREE_CHAIN (parmtypes) == void_list_node)
- error ("invalid constructor; you probably meant `%s (%s&)'",
- TYPE_NAME_STRING (ctype),
- TYPE_NAME_STRING (ctype));
- SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
- TYPE_GETS_INIT_AGGR (ctype) = 1;
- }
- else if (TREE_CODE (parmtype) == VOID_TYPE
- || TREE_PURPOSE (parmtypes) != NULL_TREE)
- TYPE_HAS_DEFAULT_CONSTRUCTOR (ctype) = 1;
-}
-
-/* Do a little sanity-checking on how they declared their operator. */
-static void
-grok_op_properties (decl, virtualp)
- tree decl;
- int virtualp;
-{
- tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
-
- if (DECL_STATIC_FUNCTION_P (decl))
- {
- if (DECL_NAME (decl) == ansi_opname[(int) NEW_EXPR])
- {
- if (virtualp)
- error ("`operator new' cannot be declared virtual");
-
- /* Take care of function decl if we had syntax errors. */
- if (argtypes == NULL_TREE)
- TREE_TYPE (decl) =
- build_function_type (ptr_type_node,
- hash_tree_chain (integer_type_node,
- void_list_node));
- else
- decl = coerce_new_type (TREE_TYPE (decl));
- }
- else if (DECL_NAME (decl) == ansi_opname[(int) DELETE_EXPR])
- {
- if (virtualp)
- error ("`operator delete' cannot be declared virtual");
-
- if (argtypes == NULL_TREE)
- TREE_TYPE (decl) =
- build_function_type (void_type_node,
- hash_tree_chain (ptr_type_node,
- void_list_node));
- else
- decl = coerce_delete_type (TREE_TYPE (decl));
- }
- else
- error_with_decl (decl, "`%s' cannot be a static member function");
- }
- else if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
- {
- tree parmtypes;
- tree parmtype;
-
- if (argtypes == NULL_TREE)
- {
- error_with_decl (decl, "too few arguments to `%s'");
- return;
- }
- parmtypes = TREE_CHAIN (argtypes);
- parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
-
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TREE_TYPE (parmtype) == current_class_type)
- {
- TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
- TYPE_GETS_ASSIGN_REF (current_class_type) = 1;
- if (TYPE_READONLY (TREE_TYPE (parmtype)))
- TYPE_GETS_CONST_INIT_REF (current_class_type) = 1;
- }
- }
-}
-
-/* Get the struct, enum or union (CODE says which) with tag NAME.
- Define the tag as a forward-reference if it is not defined.
-
- C++: If a class derivation is given, process it here, and report
- an error if multiple derivation declarations are not identical.
-
- If this is a definition, come in through xref_tag and only look in
- the current frame for the name (since C++ allows new names in any
- scope.) */
-
-/* avoid rewriting all callers of xref_tag */
-static int xref_next_defn = 0;
-
-tree
-xref_defn_tag (code_type_node, name, binfo)
- tree code_type_node;
- tree name, binfo;
-{
- tree rv, ncp;
- xref_next_defn = 1;
-
- if (class_binding_level)
- {
- tree n1;
- char *buf;
- /* we need to build a new IDENTIFIER_NODE for name which nukes
- * the pieces... */
- n1 = IDENTIFIER_LOCAL_VALUE (current_class_name);
- if (n1)
- n1 = DECL_NAME (n1);
- else
- n1 = current_class_name;
-
- buf = (char *) alloca (4 + IDENTIFIER_LENGTH (n1)
- + IDENTIFIER_LENGTH (name));
-
- sprintf (buf, "%s::%s", IDENTIFIER_POINTER (n1),
- IDENTIFIER_POINTER (name));
- ncp = get_identifier (buf);
-#ifdef SPEW_DEBUG
- if (spew_debug)
- printf("*** %s ***\n", IDENTIFIER_POINTER (ncp));
-#endif
-#if 0
- IDENTIFIER_LOCAL_VALUE (name) =
- build_lang_decl (TYPE_DECL, ncp, NULL_TREE);
-#endif
- rv = xref_tag (code_type_node, name, binfo);
- pushdecl_top_level (build_lang_decl (TYPE_DECL, ncp, rv));
- }
- else
- {
- rv = xref_tag (code_type_node, name, binfo);
- }
- xref_next_defn = 0;
- return rv;
-}
-
-tree
-xref_tag (code_type_node, name, binfo)
- tree code_type_node;
- tree name, binfo;
-{
- enum tag_types tag_code;
- enum tree_code code;
- int temp = 0;
- int i, len;
- register tree ref;
- struct binding_level *b
- = (class_binding_level ? class_binding_level : current_binding_level);
-
- tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
- switch (tag_code)
- {
- case record_type:
- case class_type:
- case exception_type:
- code = RECORD_TYPE;
- len = list_length (binfo);
- break;
- case union_type:
- code = UNION_TYPE;
- if (binfo)
- {
- error ("derived union `%s' invalid", IDENTIFIER_POINTER (name));
- binfo = NULL_TREE;
- }
- len = 0;
- break;
- case enum_type:
- code = ENUMERAL_TYPE;
- break;
- default:
- my_friendly_abort (18);
- }
-
- /* If a cross reference is requested, look up the type
- already defined for this tag and return it. */
- if (xref_next_defn)
- {
- /* If we know we are defining this tag, only look it up in this scope
- * and don't try to find it as a type. */
- xref_next_defn = 0;
- ref = lookup_tag (code, name, b, 1);
- }
- else
- {
- ref = lookup_tag (code, name, b, 0);
-
- if (! ref)
- {
- /* Try finding it as a type declaration. If that wins, use it. */
- ref = lookup_name (name, 1);
- if (ref && TREE_CODE (ref) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (ref)) == code)
- ref = TREE_TYPE (ref);
- else
- ref = NULL_TREE;
- }
- }
-
- push_obstacks_nochange ();
-
- if (! ref)
- {
- /* If no such tag is yet defined, create a forward-reference node
- and record it as the "definition".
- When a real declaration of this type is found,
- the forward-reference will be altered into a real type. */
-
- /* In C++, since these migrate into the global scope, we must
- build them on the permanent obstack. */
-
- temp = allocation_temporary_p ();
- if (temp)
- end_temporary_allocation ();
-
- if (code == ENUMERAL_TYPE)
- {
- ref = make_node (ENUMERAL_TYPE);
-
- /* Give the type a default layout like unsigned int
- to avoid crashing if it does not get defined. */
- TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
- TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
- TREE_UNSIGNED (ref) = 1;
- TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
- TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
- TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
-
- /* Enable us to recognize when a type is created in class context.
- To do nested classes correctly, this should probably be cleared
- out when we leave this classes scope. Currently this in only
- done in `start_enum'. */
-
- pushtag (name, ref);
- if (flag_cadillac)
- cadillac_start_enum (ref);
- }
- else if (tag_code == exception_type)
- {
- ref = make_lang_type (code);
- /* Enable us to recognize when an exception type is created in
- class context. To do nested classes correctly, this should
- probably be cleared out when we leave this class's scope. */
- CLASSTYPE_DECLARED_EXCEPTION (ref) = 1;
- pushtag (name, ref);
- if (flag_cadillac)
- cadillac_start_struct (ref);
- }
- else
- {
- extern tree pending_vtables;
- struct binding_level *old_b = class_binding_level;
- int needs_writing;
-
- ref = make_lang_type (code);
-
- /* Record how to set the visibility of this class's
- virtual functions. If write_virtuals == 2 or 3, then
- inline virtuals are ``extern inline''. */
- switch (write_virtuals)
- {
- case 0:
- case 1:
- needs_writing = 1;
- break;
- case 2:
- needs_writing = !! value_member (name, pending_vtables);
- break;
- case 3:
- needs_writing
- = ! (CLASSTYPE_INTERFACE_ONLY (ref) || CLASSTYPE_INTERFACE_UNKNOWN (ref));
- break;
- default:
- needs_writing = 0;
- }
-
- CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = needs_writing;
-
-#ifdef NONNESTED_CLASSES
- /* Class types don't nest the way enums do. */
- class_binding_level = (struct binding_level *)0;
-#endif
- pushtag (name, ref);
- class_binding_level = old_b;
-
- if (flag_cadillac)
- cadillac_start_struct (ref);
- }
- }
- else
- {
- if (IS_AGGR_TYPE_CODE (code))
- {
- if (IS_AGGR_TYPE (ref)
- && ((tag_code == exception_type)
- != (CLASSTYPE_DECLARED_EXCEPTION (ref) == 1)))
- {
- error ("type `%s' is both exception and aggregate type",
- IDENTIFIER_POINTER (name));
- CLASSTYPE_DECLARED_EXCEPTION (ref) = (tag_code == exception_type);
- }
- }
-
- /* If it no longer looks like a nested type, make sure it's
- in global scope. */
- if (b == global_binding_level && !class_binding_level
- && IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref);
-
- if (binfo)
- {
- tree tt1 = binfo;
- tree tt2 = TYPE_BINFO_BASETYPES (ref);
-
- if (TYPE_BINFO_BASETYPES (ref))
- for (i = 0; tt1; i++, tt1 = TREE_CHAIN (tt1))
- if (TREE_VALUE (tt1) != TYPE_IDENTIFIER (BINFO_TYPE (TREE_VEC_ELT (tt2, i))))
- {
- error ("redeclaration of derivation chain of type `%s'",
- IDENTIFIER_POINTER (name));
- break;
- }
-
- if (tt1 == NULL_TREE)
- /* The user told us something we already knew. */
- goto just_return;
-
- /* In C++, since these migrate into the global scope, we must
- build them on the permanent obstack. */
- end_temporary_allocation ();
- }
- }
-
- if (binfo)
- {
- /* In the declaration `A : X, Y, ... Z' we mark all the types
- (A, X, Y, ..., Z) so we can check for duplicates. */
- tree binfos;
-
- SET_CLASSTYPE_MARKED (ref);
- BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
-
- for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
- {
- /* The base of a derived struct is public. */
- int via_public = (tag_code != class_type
- || TREE_PURPOSE (binfo) == (tree)visibility_public
- || TREE_PURPOSE (binfo) == (tree)visibility_public_virtual);
- int via_protected = TREE_PURPOSE (binfo) == (tree)visibility_protected;
- int via_virtual = (TREE_PURPOSE (binfo) == (tree)visibility_private_virtual
- || TREE_PURPOSE (binfo) == (tree)visibility_public_virtual
- || TREE_PURPOSE (binfo) == (tree)visibility_default_virtual);
- tree basetype = TREE_TYPE (TREE_VALUE (binfo));
- tree base_binfo;
-
- GNU_xref_hier (IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TREE_VALUE (binfo)),
- via_public, via_virtual, 0);
-
- if (basetype && TREE_CODE (basetype) == TYPE_DECL)
- basetype = TREE_TYPE (basetype);
- if (!basetype || TREE_CODE (basetype) != RECORD_TYPE)
- {
- error ("base type `%s' fails to be a struct or class type",
- IDENTIFIER_POINTER (TREE_VALUE (binfo)));
- continue;
- }
-#if 1
- /* This code replaces similar code in layout_basetypes. */
- else if (TYPE_SIZE (basetype) == NULL_TREE)
- {
- error_with_aggr_type (basetype, "base class `%s' has incomplete type");
- continue;
- }
-#endif
- else
- {
- if (CLASSTYPE_MARKED (basetype))
- {
- if (basetype == ref)
- error_with_aggr_type (basetype, "recursive type `%s' undefined");
- else
- error_with_aggr_type (basetype, "duplicate base type `%s' invalid");
- continue;
- }
-
- /* Note that the BINFO records which describe individual
- inheritances are *not* shared in the lattice! They
- cannot be shared because a given baseclass may be
- inherited with different `accessibility' by different
- derived classes. (Each BINFO record describing an
- individual inheritance contains flags which say what
- the `accessibility' of that particular inheritance is.) */
-
- base_binfo = make_binfo (integer_zero_node, basetype,
- TYPE_BINFO_VTABLE (basetype),
- TYPE_BINFO_VIRTUALS (basetype), 0);
-
- TREE_VEC_ELT (binfos, i) = base_binfo;
- TREE_VIA_PUBLIC (base_binfo) = via_public;
- TREE_VIA_PROTECTED (base_binfo) = via_protected;
- TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
-
- SET_CLASSTYPE_MARKED (basetype);
-#if 0
-/* XYZZY TEST VIRTUAL BASECLASSES */
-if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
- && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
- && via_virtual == 0)
- {
- warning ("making type `%s' a virtual baseclass",
- TYPE_NAME_STRING (basetype));
- via_virtual = 1;
- }
-#endif
- /* We are free to modify these bits because they are meaningless
- at top level, and BASETYPE is a top-level type. */
- if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
- TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
- }
-
- TYPE_GETS_ASSIGNMENT (ref) |= TYPE_GETS_ASSIGNMENT (basetype);
- TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
- TREE_GETS_NEW (ref) |= TREE_GETS_NEW (basetype);
- TREE_GETS_DELETE (ref) |= TREE_GETS_DELETE (basetype);
- CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
- i += 1;
- }
- }
- if (i)
- TREE_VEC_LENGTH (binfos) = i;
- else
- BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
-
- if (i > 1)
- TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
- else if (i == 1)
- TYPE_USES_MULTIPLE_INHERITANCE (ref)
- = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
- if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
- TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
-
- /* Unmark all the types. */
- while (--i >= 0)
- CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
- CLEAR_CLASSTYPE_MARKED (ref);
- }
-
- just_return:
-
- /* Until the type is defined, tentatively accept whatever
- structure tag the user hands us. */
- if (TYPE_SIZE (ref) == NULL_TREE
- && ref != current_class_type
- /* Have to check this, in case we have contradictory tag info. */
- && IS_AGGR_TYPE_CODE (TREE_CODE (ref)))
- {
- if (tag_code == class_type)
- CLASSTYPE_DECLARED_CLASS (ref) = 1;
- else if (tag_code == record_type)
- CLASSTYPE_DECLARED_CLASS (ref) = 0;
- }
-
- pop_obstacks ();
-
- return ref;
-}
-
-static tree current_local_enum = NULL_TREE;
-
-/* Begin compiling the definition of an enumeration type.
- NAME is its name (or null if anonymous).
- Returns the type object, as yet incomplete.
- Also records info about it so that build_enumerator
- may be used to declare the individual values as they are read. */
-
-tree
-start_enum (name)
- tree name;
-{
- register tree enumtype = NULL_TREE;
- struct binding_level *b
- = (class_binding_level ? class_binding_level : current_binding_level);
-
- /* If this is the real definition for a previous forward reference,
- fill in the contents in the same object that used to be the
- forward reference. */
-
- if (name != NULL_TREE)
- enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
-
- if (enumtype == NULL_TREE || TREE_CODE (enumtype) != ENUMERAL_TYPE)
- {
- enumtype = make_node (ENUMERAL_TYPE);
- pushtag (name, enumtype);
- }
-
- if (current_class_type)
- TREE_ADDRESSABLE (b->tags) = 1;
- current_local_enum = NULL_TREE;
-
- if (TYPE_VALUES (enumtype) != NULL_TREE)
- {
- /* This enum is a named one that has been declared already. */
- error ("redeclaration of `enum %s'", IDENTIFIER_POINTER (name));
-
- /* Completely replace its old definition.
- The old enumerators remain defined, however. */
- TYPE_VALUES (enumtype) = NULL_TREE;
- }
-
- /* Initially, set up this enum as like `int'
- so that we can create the enumerators' declarations and values.
- Later on, the precision of the type may be changed and
- it may be laid out again. */
-
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
- TYPE_SIZE (enumtype) = NULL_TREE;
- fixup_unsigned_type (enumtype);
-
- /* We copy this value because enumerated type constants
- are really of the type of the enumerator, not integer_type_node. */
- enum_next_value = copy_node (integer_zero_node);
-
- GNU_xref_decl (current_function_decl, enumtype);
- return enumtype;
-}
-
-/* After processing and defining all the values of an enumeration type,
- install their decls in the enumeration type and finish it off.
- ENUMTYPE is the type object and VALUES a list of name-value pairs.
- Returns ENUMTYPE. */
-
-tree
-finish_enum (enumtype, values)
- register tree enumtype, values;
-{
- register tree pair;
- register HOST_WIDE_INT maxvalue = 0;
- register HOST_WIDE_INT minvalue = 0;
- register HOST_WIDE_INT i;
-
- TYPE_VALUES (enumtype) = values;
-
- /* Calculate the maximum value of any enumerator in this type. */
-
- if (values)
- {
- /* Speed up the main loop by performing some precalculations */
-
- HOST_WIDE_INT value = TREE_INT_CST_LOW (TREE_VALUE (values));
- TREE_TYPE (TREE_VALUE (values)) = enumtype;
- minvalue = maxvalue = value;
-
- for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
- {
- value = TREE_INT_CST_LOW (TREE_VALUE (pair));
- if (value > maxvalue)
- maxvalue = value;
- else if (value < minvalue)
- minvalue = value;
- TREE_TYPE (TREE_VALUE (pair)) = enumtype;
- }
- }
-
- if (flag_short_enums)
- {
- /* Determine the precision this type needs, lay it out, and define it. */
-
- for (i = maxvalue; i; i >>= 1)
- TYPE_PRECISION (enumtype)++;
-
- if (!TYPE_PRECISION (enumtype))
- TYPE_PRECISION (enumtype) = 1;
-
- /* Cancel the laying out previously done for the enum type,
- so that fixup_unsigned_type will do it over. */
- TYPE_SIZE (enumtype) = NULL_TREE;
-
- fixup_unsigned_type (enumtype);
- }
-
- TREE_INT_CST_LOW (TYPE_MAX_VALUE (enumtype)) = maxvalue;
-
- /* An enum can have some negative values; then it is signed. */
- if (minvalue < 0)
- {
- TREE_INT_CST_LOW (TYPE_MIN_VALUE (enumtype)) = minvalue;
- TREE_INT_CST_HIGH (TYPE_MIN_VALUE (enumtype)) = -1;
- TREE_UNSIGNED (enumtype) = 0;
- }
- if (flag_cadillac)
- cadillac_finish_enum (enumtype);
-
- /* Finish debugging output for this type. */
-#if 0
- /* @@ Do we ever generate generate ENUMERAL_TYPE nodes for which debugging
- information should *not* be generated? I think not. */
- if (! DECL_IGNORED_P (TYPE_NAME (enumtype)))
-#endif
- rest_of_type_compilation (enumtype, global_bindings_p ());
-
- return enumtype;
-}
-
-/* Build and install a CONST_DECL for one value of the
- current enumeration type (one that was begun with start_enum).
- Return a tree-list containing the name and its value.
- Assignment of sequential values by default is handled here. */
-
-tree
-build_enumerator (name, value)
- tree name, value;
-{
- tree decl, result;
- /* Change this to zero if we find VALUE is not shareable. */
- int shareable = 1;
-
- /* Remove no-op casts from the value. */
- if (value)
- STRIP_TYPE_NOPS (value);
-
- /* Validate and default VALUE. */
- if (value != NULL_TREE)
- {
- if (TREE_READONLY_DECL_P (value))
- {
- value = decl_constant_value (value);
- shareable = 0;
- }
-
- if (TREE_CODE (value) != INTEGER_CST)
- {
- error ("enumerator value for `%s' not integer constant",
- IDENTIFIER_POINTER (name));
- value = NULL_TREE;
- }
- }
- /* The order of things is reversed here so that we
- can check for possible sharing of enum values,
- to keep that from happening. */
- /* Default based on previous value. */
- if (value == NULL_TREE)
- value = enum_next_value;
-
- /* Remove no-op casts from the value. */
- if (value)
- STRIP_TYPE_NOPS (value);
-
- /* Make up for hacks in cp-lex.c. */
- if (value == integer_zero_node)
- value = build_int_2 (0, 0);
- else if (value == integer_one_node)
- value = build_int_2 (1, 0);
- else if (TREE_CODE (value) == INTEGER_CST
- && (shareable == 0
- || TREE_CODE (TREE_TYPE (value)) == ENUMERAL_TYPE))
- {
- value = copy_node (value);
- TREE_TYPE (value) = integer_type_node;
- }
-
- result = saveable_tree_cons (name, value, NULL_TREE);
-
- /* C++ associates enums with global, function, or class declarations. */
- if (current_class_type == NULL_TREE || current_function_decl != NULL_TREE)
- {
- /* Create a declaration for the enum value name. */
-
- decl = build_decl (CONST_DECL, name, integer_type_node);
- DECL_INITIAL (decl) = value;
-
- pushdecl (decl);
- GNU_xref_decl (current_function_decl, decl);
- }
-
- if (current_class_type)
- {
- /* class-local enum declaration */
- decl = build_lang_field_decl (CONST_DECL, name, integer_type_node);
- DECL_INITIAL (decl) = value;
- TREE_READONLY (decl) = 1;
- pushdecl_class_level (decl);
- TREE_CHAIN (decl) = current_local_enum;
- current_local_enum = decl;
- }
-
- /* Set basis for default for next value. */
- enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
- integer_one_node, PLUS_EXPR);
- if (enum_next_value == integer_one_node)
- enum_next_value = copy_node (enum_next_value);
-
- return result;
-}
-
-tree
-grok_enum_decls (type, decl)
- tree type, decl;
-{
- tree d = current_local_enum;
-
- if (d == NULL_TREE)
- return decl;
-
- while (1)
- {
- TREE_TYPE (d) = type;
- if (TREE_CHAIN (d) == NULL_TREE)
- {
- TREE_CHAIN (d) = decl;
- break;
- }
- d = TREE_CHAIN (d);
- }
-
- decl = current_local_enum;
- current_local_enum = NULL_TREE;
-
- return decl;
-}
-
-/* Create the FUNCTION_DECL for a function definition.
- DECLSPECS and DECLARATOR are the parts of the declaration;
- they describe the function's name and the type it returns,
- but twisted together in a fashion that parallels the syntax of C.
-
- This function creates a binding context for the function body
- as well as setting up the FUNCTION_DECL in current_function_decl.
-
- Returns 1 on success. If the DECLARATOR is not suitable for a function
- (it defines a datum instead), we return 0, which tells
- yyparse to report a parse error.
-
- For C++, we must first check whether that datum makes any sense.
- For example, "class A local_a(1,2);" means that variable local_a
- is an aggregate of type A, which should have a constructor
- applied to it with the argument list [1, 2].
-
- @@ There is currently no way to retrieve the storage
- @@ allocated to FUNCTION (or all of its parms) if we return
- @@ something we had previously. */
-
-int
-start_function (declspecs, declarator, raises, pre_parsed_p)
- tree declarator, declspecs, raises;
- int pre_parsed_p;
-{
- extern tree EHS_decl;
- tree decl1, olddecl;
- tree ctype = NULL_TREE;
- tree fntype;
- tree restype;
- extern int have_extern_spec;
- extern int used_extern_spec;
- int doing_friend = 0;
-
- if (flag_handle_exceptions && EHS_decl == NULL_TREE)
- init_exception_processing_1 ();
-
- /* Sanity check. */
- my_friendly_assert (TREE_VALUE (void_list_node) == void_type_node, 160);
- my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
-
- /* Assume, until we see it does. */
- current_function_returns_value = 0;
- current_function_returns_null = 0;
- warn_about_return_type = 0;
- current_extern_inline = 0;
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
- current_function_parms_stored = 0;
- original_result_rtx = NULL_RTX;
- current_function_obstack_index = 0;
- current_function_obstack_usage = 0;
-
- clear_temp_name ();
-
- /* This should only be done once on the top most decl. */
- if (have_extern_spec && !used_extern_spec)
- {
- declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
- used_extern_spec = 1;
- }
-
- if (pre_parsed_p)
- {
- decl1 = declarator;
- last_function_parms = DECL_ARGUMENTS (decl1);
- last_function_parm_tags = NULL_TREE;
- fntype = TREE_TYPE (decl1);
- if (TREE_CODE (fntype) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (fntype);
-
- /* ANSI C++ June 5 1992 WP 11.4.5. A friend function defined in a
- class is in the (lexical) scope of the class in which it is
- defined. */
- if (!ctype && DECL_FRIEND_P (decl1))
- {
- ctype = TREE_TYPE (TREE_CHAIN (decl1));
-
- /* CTYPE could be null here if we're dealing with a template;
- for example, `inline friend float foo()' inside a template
- will have no CTYPE set. */
- if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
- ctype = NULL_TREE;
- else
- doing_friend = 1;
- }
-
- if ( !(DECL_VINDEX (decl1)
- && write_virtuals >= 2
- && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype)))
- current_extern_inline = TREE_PUBLIC (decl1) && DECL_INLINE (decl1);
-
- raises = TYPE_RAISES_EXCEPTIONS (fntype);
-
- /* In a fcn definition, arg types must be complete. */
- require_complete_types_for_parms (last_function_parms);
- }
- else
- {
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, raises);
- /* If the declarator is not suitable for a function definition,
- cause a syntax error. */
- if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
-
- fntype = TREE_TYPE (decl1);
-
- restype = TREE_TYPE (fntype);
- if (IS_AGGR_TYPE (restype)
- && ! CLASSTYPE_GOT_SEMICOLON (restype))
- {
- error_with_aggr_type (restype, "semicolon missing after declaration of `%s'");
- shadow_tag (build_tree_list (NULL_TREE, restype));
- CLASSTYPE_GOT_SEMICOLON (restype) = 1;
- if (TREE_CODE (fntype) == FUNCTION_TYPE)
- fntype = build_function_type (integer_type_node,
- TYPE_ARG_TYPES (fntype));
- else
- fntype = build_cplus_method_type (build_type_variant (TYPE_METHOD_BASETYPE (fntype), TREE_READONLY (decl1), TREE_SIDE_EFFECTS (decl1)),
- integer_type_node,
- TYPE_ARG_TYPES (fntype));
- TREE_TYPE (decl1) = fntype;
- }
-
- if (TREE_CODE (fntype) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (fntype);
- else if (IDENTIFIER_LENGTH (DECL_NAME (decl1)) == 4
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (decl1)), "main")
- && DECL_CONTEXT (decl1) == NULL_TREE)
- {
- /* If this doesn't return integer_type, complain. */
- if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
- {
- warning ("return type for `main' changed to integer type");
- TREE_TYPE (decl1) = fntype = default_function_type;
- }
- warn_about_return_type = 0;
- }
- }
-
- /* Warn if function was previously implicitly declared
- (but not if we warned then). */
- if (! warn_implicit
- && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
- warning_with_decl (IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)),
- "`%s' implicitly declared before its definition");
-
- current_function_decl = decl1;
-
- if (flag_cadillac)
- cadillac_start_function (decl1);
- else
- announce_function (decl1);
-
- if (TYPE_SIZE (TREE_TYPE (fntype)) == NULL_TREE)
- {
- if (IS_AGGR_TYPE (TREE_TYPE (fntype)))
- error_with_aggr_type (TREE_TYPE (fntype),
- "return-type `%s' is an incomplete type");
- else
- error ("return-type is an incomplete type");
-
- /* Make it return void instead, but don't change the
- type of the DECL_RESULT, in case we have a named return value. */
- if (ctype)
- TREE_TYPE (decl1)
- = build_cplus_method_type (build_type_variant (ctype,
- TREE_READONLY (decl1),
- TREE_SIDE_EFFECTS (decl1)),
- void_type_node,
- FUNCTION_ARG_CHAIN (decl1));
- else
- TREE_TYPE (decl1)
- = build_function_type (void_type_node,
- TYPE_ARG_TYPES (TREE_TYPE (decl1)));
- DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, TREE_TYPE (fntype));
- }
-
- if (warn_about_return_type)
- warning ("return-type defaults to `int'");
-
- /* Make the init_value nonzero so pushdecl knows this is not tentative.
- error_mark_node is replaced below (in poplevel) with the BLOCK. */
- DECL_INITIAL (decl1) = error_mark_node;
-
- /* Didn't get anything from C. */
- olddecl = NULL_TREE;
-
- /* This function exists in static storage.
- (This does not mean `static' in the C sense!) */
- TREE_STATIC (decl1) = 1;
-
- /* If this function belongs to an interface, it is public.
- If it belongs to someone else's interface, it is also external.
- It doesn't matter whether it's inline or not. */
- if (interface_unknown == 0)
- {
- TREE_PUBLIC (decl1) = 1;
- DECL_EXTERNAL (decl1) = (interface_only
- || (DECL_INLINE (decl1)
- && ! flag_implement_inlines));
- }
- else
- /* This is a definition, not a reference.
- So normally clear DECL_EXTERNAL.
- However, `extern inline' acts like a declaration except for
- defining how to inline. So set DECL_EXTERNAL in that case. */
- DECL_EXTERNAL (decl1) = current_extern_inline;
-
- /* Now see if this is the implementation of a function
- declared with "C" linkage. */
- if (ctype == NULL_TREE && current_lang_name == lang_name_cplusplus
- && !DECL_CONTEXT (decl1))
- {
- olddecl = lookup_name_current_level (DECL_NAME (decl1));
- if (olddecl && TREE_CODE (olddecl) != FUNCTION_DECL)
- olddecl = NULL_TREE;
- if (olddecl && DECL_NAME (decl1) != DECL_NAME (olddecl))
- {
- /* Collision between user and internal naming scheme. */
- olddecl = lookup_name_current_level (DECL_ASSEMBLER_NAME (decl1));
- if (olddecl == NULL_TREE)
- olddecl = decl1;
- }
- if (olddecl && olddecl != decl1
- && DECL_NAME (decl1) == DECL_NAME (olddecl))
- {
- if (TREE_CODE (olddecl) == FUNCTION_DECL
- && decls_match (decl1, olddecl))
- {
- olddecl = DECL_MAIN_VARIANT (olddecl);
- /* The following copy is needed to handle forcing a function's
- linkage to obey the linkage of the original decl. */
- DECL_ASSEMBLER_NAME (decl1) = DECL_ASSEMBLER_NAME (olddecl);
- DECL_OVERLOADED (decl1) = DECL_OVERLOADED (olddecl);
- if (DECL_INITIAL (olddecl))
- redeclaration_error_message (decl1, olddecl);
- if (! duplicate_decls (decl1, olddecl))
- my_friendly_abort (19);
- decl1 = olddecl;
- }
- else
- olddecl = NULL_TREE;
- }
- }
-
- /* Record the decl so that the function name is defined.
- If we already have a decl for this name, and it is a FUNCTION_DECL,
- use the old decl. */
-
- if (olddecl)
- current_function_decl = olddecl;
- else if (pre_parsed_p == 0)
- {
- current_function_decl = pushdecl (decl1);
- if (TREE_CODE (current_function_decl) == TREE_LIST)
- {
- /* @@ revert to modified original declaration. */
- decl1 = DECL_MAIN_VARIANT (decl1);
- current_function_decl = decl1;
- }
- else
- {
- decl1 = current_function_decl;
- DECL_MAIN_VARIANT (decl1) = decl1;
- }
- fntype = TREE_TYPE (decl1);
- }
- else
- current_function_decl = decl1;
-
- if (DECL_OVERLOADED (decl1))
- decl1 = push_overloaded_decl (decl1, 1);
-
- if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1))
- {
- if (TREE_CODE (fntype) == METHOD_TYPE)
- TREE_TYPE (decl1) = fntype
- = build_function_type (TREE_TYPE (fntype),
- TREE_CHAIN (TYPE_ARG_TYPES (fntype)));
- last_function_parms = TREE_CHAIN (last_function_parms);
- DECL_ARGUMENTS (decl1) = last_function_parms;
- ctype = NULL_TREE;
- }
- restype = TREE_TYPE (fntype);
-
- pushlevel (0);
- current_binding_level->parm_flag = 1;
-
- /* Save the parm names or decls from this function's declarator
- where store_parm_decls will find them. */
- current_function_parms = last_function_parms;
- current_function_parm_tags = last_function_parm_tags;
-
- GNU_xref_function (decl1, current_function_parms);
-
- make_function_rtl (decl1);
-
- if (ctype)
- {
- pushclass (ctype, 1);
-
- /* If we're compiling a friend function, neither of the variables
- current_class_decl nor current_class_type will have values. */
- if (! doing_friend)
- {
- /* We know that this was set up by `grokclassfn'.
- We do not wait until `store_parm_decls', since evil
- parse errors may never get us to that point. Here
- we keep the consistency between `current_class_type'
- and `current_class_decl'. */
- current_class_decl = last_function_parms;
- my_friendly_assert (current_class_decl != NULL_TREE
- && TREE_CODE (current_class_decl) == PARM_DECL, 162);
- if (TREE_CODE (TREE_TYPE (current_class_decl)) == POINTER_TYPE)
- {
- tree variant = TREE_TYPE (TREE_TYPE (current_class_decl));
- if (CLASSTYPE_INST_VAR (ctype) == NULL_TREE)
- {
- /* Can't call build_indirect_ref here, because it has special
- logic to return C_C_D given this argument. */
- C_C_D = build1 (INDIRECT_REF, current_class_type, current_class_decl);
- CLASSTYPE_INST_VAR (ctype) = C_C_D;
- }
- else
- {
- C_C_D = CLASSTYPE_INST_VAR (ctype);
- /* `current_class_decl' is different for every
- function we compile. */
- TREE_OPERAND (C_C_D, 0) = current_class_decl;
- }
- TREE_READONLY (C_C_D) = TYPE_READONLY (variant);
- TREE_SIDE_EFFECTS (C_C_D) = TYPE_VOLATILE (variant);
- TREE_THIS_VOLATILE (C_C_D) = TYPE_VOLATILE (variant);
- }
- else
- C_C_D = current_class_decl;
- }
- }
- else
- {
- if (DECL_STATIC_FUNCTION_P (decl1))
- pushclass (DECL_CONTEXT (decl1), 2);
- else
- push_memoized_context (0, 1);
- }
-
- /* Allocate further tree nodes temporarily during compilation
- of this function only. Tiemann moved up here from bottom of fn. */
- temporary_allocation ();
-
- /* Promote the value to int before returning it. */
- if (C_PROMOTING_INTEGER_TYPE_P (restype))
- {
- /* It retains unsignedness if traditional or if it isn't
- really getting wider. */
- if (TREE_UNSIGNED (restype)
- && (flag_traditional
- || TYPE_PRECISION (restype)
- == TYPE_PRECISION (integer_type_node)))
- restype = unsigned_type_node;
- else
- restype = integer_type_node;
- }
- if (DECL_RESULT (decl1) == NULL_TREE)
- DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, restype);
-
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1)))
- {
- dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- ctor_label = NULL_TREE;
- }
- else
- {
- dtor_label = NULL_TREE;
- if (DECL_CONSTRUCTOR_P (decl1))
- ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- }
-
- /* If this fcn was already referenced via a block-scope `extern' decl
- (or an implicit decl), propagate certain information about the usage. */
- if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl1)))
- TREE_ADDRESSABLE (decl1) = 1;
-
- return 1;
-}
-
-/* Store the parameter declarations into the current function declaration.
- This is called after parsing the parameter declarations, before
- digesting the body of the function.
-
- Also install to binding contour return value identifier, if any. */
-
-void
-store_parm_decls ()
-{
- register tree fndecl = current_function_decl;
- register tree parm;
- int parms_have_cleanups = 0;
- tree eh_decl;
-
- /* This is either a chain of PARM_DECLs (when a prototype is used). */
- tree specparms = current_function_parms;
-
- /* This is a list of types declared among parms in a prototype. */
- tree parmtags = current_function_parm_tags;
-
- /* This is a chain of any other decls that came in among the parm
- declarations. If a parm is declared with enum {foo, bar} x;
- then CONST_DECLs for foo and bar are put here. */
- tree nonparms = NULL_TREE;
-
- if (current_binding_level == global_binding_level)
- fatal ("parse errors have confused me too much");
-
- /* Initialize RTL machinery. */
- init_function_start (fndecl, input_filename, lineno);
-
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
- declare_function_name ();
-
- /* Create a binding level for the parms. */
- expand_start_bindings (0);
-
- /* Prepare to catch raises, if appropriate. */
- if (flag_handle_exceptions)
- {
- /* Get this cleanup to be run last, since it
- is a call to `longjmp'. */
- setup_exception_throw_decl ();
- eh_decl = current_binding_level->names;
- current_binding_level->names = TREE_CHAIN (current_binding_level->names);
- }
- if (flag_handle_exceptions)
- expand_start_try (integer_one_node, 0, 1);
-
- if (specparms != NULL_TREE)
- {
- /* This case is when the function was defined with an ANSI prototype.
- The parms already have decls, so we need not do anything here
- except record them as in effect
- and complain if any redundant old-style parm decls were written. */
-
- register tree next;
-
- /* Must clear this because it might contain TYPE_DECLs declared
- at class level. */
- storedecls (NULL_TREE);
- for (parm = nreverse (specparms); parm; parm = next)
- {
- next = TREE_CHAIN (parm);
- if (TREE_CODE (parm) == PARM_DECL)
- {
- tree cleanup = maybe_build_cleanup (parm);
- if (DECL_NAME (parm) == NULL_TREE)
- {
-#if 0
- error_with_decl (parm, "parameter name omitted");
-#else
- /* for C++, this is not an error. */
- pushdecl (parm);
-#endif
- }
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
- error_with_decl (parm, "parameter `%s' declared void");
- else
- {
- /* Now fill in DECL_REFERENCE_SLOT for any of the parm decls.
- A parameter is assumed not to have any side effects.
- If this should change for any reason, then this
- will have to wrap the bashed reference type in a save_expr.
-
- Also, if the parameter type is declared to be an X
- and there is an X(X&) constructor, we cannot lay it
- into the stack (any more), so we make this parameter
- look like it is really of reference type. Functions
- which pass parameters to this function will know to
- create a temporary in their frame, and pass a reference
- to that. */
-
- if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE
- && TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))))
- SET_DECL_REFERENCE_SLOT (parm, convert_from_reference (parm));
-
- pushdecl (parm);
- }
- if (cleanup)
- {
- expand_decl (parm);
- expand_decl_cleanup (parm, cleanup);
- parms_have_cleanups = 1;
- }
- }
- else
- {
- /* If we find an enum constant or a type tag,
- put it aside for the moment. */
- TREE_CHAIN (parm) = NULL_TREE;
- nonparms = chainon (nonparms, parm);
- }
- }
-
- /* Get the decls in their original chain order
- and record in the function. This is all and only the
- PARM_DECLs that were pushed into scope by the loop above. */
- DECL_ARGUMENTS (fndecl) = getdecls ();
-
- storetags (chainon (parmtags, gettags ()));
- }
- else
- DECL_ARGUMENTS (fndecl) = NULL_TREE;
-
- /* Now store the final chain of decls for the arguments
- as the decl-chain of the current lexical scope.
- Put the enumerators in as well, at the front so that
- DECL_ARGUMENTS is not modified. */
-
- storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
-
- /* Initialize the RTL code for the function. */
- DECL_SAVED_INSNS (fndecl) = NULL_RTX;
- expand_function_start (fndecl, parms_have_cleanups);
-
- if (flag_handle_exceptions)
- {
- /* Make the throw decl visible at this level, just
- not in the way of the parameters. */
- pushdecl (eh_decl);
- expand_decl_init (eh_decl);
- }
-
- /* Create a binding contour which can be used to catch
- cleanup-generated temporaries. Also, if the return value needs or
- has initialization, deal with that now. */
- if (parms_have_cleanups)
- {
- pushlevel (0);
- expand_start_bindings (0);
- }
-
- current_function_parms_stored = 1;
-
- if (flag_gc)
- {
- maybe_gc_cleanup = build_tree_list (NULL_TREE, error_mark_node);
- expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup);
- }
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
- && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- {
- expand_main_function ();
-
- if (flag_gc)
- expand_expr (build_function_call (lookup_name (get_identifier ("__gc_main"), 0), NULL_TREE),
- 0, VOIDmode, 0);
-
- if (flag_dossier)
- output_builtin_tdesc_entries ();
- }
-}
-
-/* Bind a name and initialization to the return value of
- the current function. */
-void
-store_return_init (return_id, init)
- tree return_id, init;
-{
- tree decl = DECL_RESULT (current_function_decl);
-
- if (pedantic)
- /* Give this error as many times as there are occurrences,
- so that users can use Emacs compilation buffers to find
- and fix all such places. */
- error ("ANSI C++ does not permit named return values");
-
- if (return_id != NULL_TREE)
- {
- if (DECL_NAME (decl) == NULL_TREE)
- {
- DECL_NAME (decl) = return_id;
- DECL_ASSEMBLER_NAME (decl) = return_id;
- }
- else
- error ("return identifier `%s' already in place",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- }
-
- /* Can't let this happen for constructors. */
- if (DECL_CONSTRUCTOR_P (current_function_decl))
- {
- error ("can't redefine default return value for constructors");
- return;
- }
-
- /* If we have a named return value, put that in our scope as well. */
- if (DECL_NAME (decl) != NULL_TREE)
- {
- /* If this named return value comes in a register,
- put it in a pseudo-register. */
- if (DECL_REGISTER (decl))
- {
- original_result_rtx = DECL_RTL (decl);
- DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
- }
-
- /* Let `finish_decl' know that this initializer is ok. */
- DECL_INITIAL (decl) = init;
- pushdecl (decl);
- finish_decl (decl, init, 0, 0);
- }
-}
-
-/* Generate code for default X(X&) constructor. */
-static void
-build_default_constructor (fndecl)
- tree fndecl;
-{
- int i = CLASSTYPE_N_BASECLASSES (current_class_type);
- tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
- tree fields = TYPE_FIELDS (current_class_type);
- tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- parm = TREE_CHAIN (parm);
- parm = DECL_REFERENCE_SLOT (parm);
-
- while (--i >= 0)
- {
- tree basetype = TREE_VEC_ELT (binfos, i);
- if (TYPE_GETS_INIT_REF (basetype))
- {
- tree name = TYPE_NAME (basetype);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- current_base_init_list = tree_cons (name, parm, current_base_init_list);
- }
- }
- for (; fields; fields = TREE_CHAIN (fields))
- {
- tree name, init;
- if (TREE_STATIC (fields))
- continue;
- 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;
- }
-
- init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
-
- if (TREE_ANON_UNION_ELEM (fields))
- name = build (COMPONENT_REF, TREE_TYPE (fields), C_C_D, fields);
- else
- {
- name = DECL_NAME (fields);
- init = build_tree_list (NULL_TREE, init);
- }
-
- current_member_init_list
- = tree_cons (name, init, current_member_init_list);
- }
-}
-
-
-/* Finish up a function declaration and compile that function
- all the way to assembler language output. The free the storage
- for the function definition.
-
- This is called after parsing the body of the function definition.
- LINENO is the current line number.
-
- C++: CALL_POPLEVEL is non-zero if an extra call to poplevel
- (and expand_end_bindings) must be made to take care of the binding
- contour for the base initializers. This is only relevant for
- constructors. */
-
-void
-finish_function (lineno, call_poplevel)
- int lineno;
- int call_poplevel;
-{
- register tree fndecl = current_function_decl;
- tree fntype, ctype = NULL_TREE;
- rtx head, last_parm_insn, mark;
- extern int sets_exception_throw_decl;
- /* Label to use if this function is supposed to return a value. */
- tree no_return_label = NULL_TREE;
-
- /* When we get some parse errors, we can end up without a
- current_function_decl, so cope. */
- if (fndecl == NULL_TREE)
- return;
-
- fntype = TREE_TYPE (fndecl);
-
-/* TREE_READONLY (fndecl) = 1;
- This caused &foo to be of type ptr-to-const-function
- which then got a warning when stored in a ptr-to-function variable. */
-
- /* This happens on strange parse errors. */
- if (! current_function_parms_stored)
- {
- call_poplevel = 0;
- store_parm_decls ();
- }
-
- if (write_symbols != NO_DEBUG && TREE_CODE (fntype) != METHOD_TYPE)
- {
- tree ttype = target_type (fntype);
- tree parmdecl;
-
- if (IS_AGGR_TYPE (ttype))
- /* Let debugger know it should output info for this type. */
- note_debug_info_needed (ttype);
-
- for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
- {
- ttype = target_type (TREE_TYPE (parmdecl));
- if (IS_AGGR_TYPE (ttype))
- /* Let debugger know it should output info for this type. */
- note_debug_info_needed (ttype);
- }
- }
-
- /* Clean house because we will need to reorder insns here. */
- do_pending_stack_adjust ();
-
- if (dtor_label)
- {
- tree binfo = TYPE_BINFO (current_class_type);
- tree cond = integer_one_node;
- tree exprstmt, vfields;
- tree in_charge_node = lookup_name (in_charge_identifier, 0);
- tree virtual_size;
- int ok_to_optimize_dtor = 0;
-
- if (current_function_assigns_this)
- cond = build (NE_EXPR, integer_type_node,
- current_class_decl, integer_zero_node);
- else
- {
- int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
-
- /* If this destructor is empty, then we don't need to check
- whether `this' is NULL in some cases. */
- mark = get_last_insn ();
- last_parm_insn = get_first_nonparm_insn ();
-
- if ((flag_this_is_variable & 1) == 0)
- ok_to_optimize_dtor = 1;
- else if (mark == last_parm_insn)
- ok_to_optimize_dtor
- = (n_baseclasses == 0
- || (n_baseclasses == 1
- && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0))));
- }
-
- /* These initializations might go inline. Protect
- the binding level of the parms. */
- pushlevel (0);
-
- if (current_function_assigns_this)
- {
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
- }
-
- /* Generate the code to call destructor on base class.
- If this destructor belongs to a class with virtual
- functions, then set the virtual function table
- pointer to represent the type of our base class. */
-
- /* This side-effect makes call to `build_delete' generate the
- code we have to have at the end of this destructor. */
- TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
-
- /* These are two cases where we cannot delegate deletion. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
- || TREE_GETS_DELETE (current_class_type))
- exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0, 0);
- else
- exprstmt = build_delete (current_class_type, C_C_D, in_charge_node,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0, 0);
-
- /* If we did not assign to this, then `this' is non-zero at
- the end of a destructor. As a special optimization, don't
- emit test if this is an empty destructor. If it does nothing,
- it does nothing. If it calls a base destructor, the base
- destructor will perform the test. */
-
- if (exprstmt != error_mark_node
- && (TREE_CODE (exprstmt) != NOP_EXPR
- || TREE_OPERAND (exprstmt, 0) != integer_zero_node
- || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
- {
- expand_label (dtor_label);
- if (cond != integer_one_node)
- expand_start_cond (cond, 0);
- if (exprstmt != void_zero_node)
- /* Don't call `expand_expr_stmt' if we're not going to do
- anything, since -Wall will give a diagnostic. */
- expand_expr_stmt (exprstmt);
-
- /* Run destructor on all virtual baseclasses. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- {
- tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
- expand_start_cond (build (BIT_AND_EXPR, integer_type_node,
- in_charge_node, integer_two_node), 0);
- while (vbases)
- {
- if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
- {
- tree ptr = convert_pointer_to_vbase (vbases, current_class_decl);
- expand_expr_stmt (build_delete (TYPE_POINTER_TO (BINFO_TYPE (vbases)),
- ptr, integer_zero_node,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0, 0));
- }
- vbases = TREE_CHAIN (vbases);
- }
- expand_end_cond ();
- }
-
- do_pending_stack_adjust ();
- if (cond != integer_one_node)
- expand_end_cond ();
- }
-
- TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
-
- virtual_size = c_sizeof (current_class_type);
-
- /* At the end, call delete if that's what's requested. */
- if (TREE_GETS_DELETE (current_class_type))
- /* This NOP_EXPR means we are in a static call context. */
- exprstmt =
- build_method_call
- (build1 (NOP_EXPR,
- TYPE_POINTER_TO (current_class_type), error_mark_node),
- ansi_opname[(int) DELETE_EXPR],
- tree_cons (NULL_TREE, current_class_decl,
- build_tree_list (NULL_TREE, virtual_size)),
- NULL_TREE, LOOKUP_NORMAL);
- else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0,
- virtual_size);
- else
- exprstmt = NULL_TREE;
-
- if (exprstmt)
- {
- cond = build (BIT_AND_EXPR, integer_type_node,
- in_charge_node, integer_one_node);
- expand_start_cond (cond, 0);
- expand_expr_stmt (exprstmt);
- expand_end_cond ();
- }
-
- /* End of destructor. */
- poplevel (2, 0, 0);
-
- /* Back to the top of destructor. */
- /* Dont execute destructor code if `this' is NULL. */
- mark = get_last_insn ();
- last_parm_insn = get_first_nonparm_insn ();
- if (last_parm_insn == NULL_RTX)
- last_parm_insn = mark;
- else
- last_parm_insn = previous_insn (last_parm_insn);
-
- /* Make all virtual function table pointers point to CURRENT_CLASS_TYPE's
- virtual function tables. */
- if (CLASSTYPE_VFIELDS (current_class_type))
- {
- for (vfields = CLASSTYPE_VFIELDS (current_class_type);
- TREE_CHAIN (vfields);
- vfields = TREE_CHAIN (vfields))
- {
- tree vf_decl = current_class_decl;
- /* ??? This may need to be a loop if there are multiple
- levels of replication. */
- if (VF_BINFO_VALUE (vfields))
- vf_decl = convert_pointer_to (VF_BINFO_VALUE (vfields), vf_decl);
- if (vf_decl != error_mark_node)
- {
- /* It is one of these two, or a combination... */
- /* basically speaking, I want to get down to the right
- VF_BASETYPE_VALUE (vfields) */
-#if 0
- if (VF_NORMAL_VALUE (vfields) != VF_DERIVED_VALUE (vfields))
- warning ("hum, wonder if I am doing the right thing");
-#endif
- expand_expr_stmt (build_virtual_init (binfo,
- get_binfo (VF_BASETYPE_VALUE (vfields),
- get_binfo (VF_DERIVED_VALUE (vfields), binfo, 0), 0),
- vf_decl));
- }
- }
- expand_expr_stmt (build_virtual_init (binfo, binfo,
- current_class_decl));
- }
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- expand_expr_stmt (build_vbase_vtables_init (binfo, binfo,
- C_C_D, current_class_decl, 0));
- if (! ok_to_optimize_dtor)
- {
- cond = build_binary_op (NE_EXPR,
- current_class_decl, integer_zero_node, 1);
- expand_start_cond (cond, 0);
- }
- if (mark != get_last_insn ())
- reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
- if (! ok_to_optimize_dtor)
- expand_end_cond ();
- }
- else if (current_function_assigns_this)
- {
- /* Does not need to call emit_base_init, because
- that is done (if needed) just after assignment to this
- is seen. */
-
- if (DECL_CONSTRUCTOR_P (current_function_decl))
- {
- expand_label (ctor_label);
- ctor_label = NULL_TREE;
-
- if (call_poplevel)
- {
- tree decls = getdecls ();
- if (flag_handle_exceptions == 2)
- deactivate_exception_cleanups ();
- expand_end_bindings (decls, decls != NULL_TREE, 0);
- poplevel (decls != NULL_TREE, 0, 0);
- }
- c_expand_return (current_class_decl);
- }
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (
- DECL_RESULT (current_function_decl))) != void_type_node
- && return_label != NULL_RTX)
- no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
- base_init_insns = NULL_RTX;
- }
- else if (DECL_CONSTRUCTOR_P (fndecl))
- {
- tree allocated_this;
- tree cond, thenclause;
- /* Allow constructor for a type to get a new instance of the object
- using `build_new'. */
- tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
- CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
-
- DECL_RETURNS_FIRST_ARG (fndecl) = 1;
-
- if (flag_this_is_variable > 0)
- {
- cond = build_binary_op (EQ_EXPR,
- current_class_decl, integer_zero_node, 1);
- thenclause = build_modify_expr (current_class_decl, NOP_EXPR,
- build_new (NULL_TREE, current_class_type, void_type_node, 0));
- if (flag_handle_exceptions == 2)
- {
- tree cleanup, cleanup_deallocate;
- tree virtual_size;
-
- /* This is the size of the virtual object pointed to by
- allocated_this. In this case, it is simple. */
- virtual_size = c_sizeof (current_class_type);
-
- allocated_this = build_decl (VAR_DECL, NULL_TREE, ptr_type_node);
- DECL_REGISTER (allocated_this) = 1;
- DECL_INITIAL (allocated_this) = error_mark_node;
- expand_decl (allocated_this);
- expand_decl_init (allocated_this);
- /* How we cleanup `this' if an exception was raised before
- we are ready to bail out. */
- cleanup = TREE_GETS_DELETE (current_class_type)
- ? build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, allocated_this, virtual_size, NULL_TREE)
- /* The size of allocated_this is wrong, and hence the
- second argument to operator delete will be wrong. */
- : build_delete (TREE_TYPE (allocated_this), allocated_this,
- integer_three_node,
- LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, 1, 0);
- cleanup_deallocate
- = build_modify_expr (current_class_decl, NOP_EXPR, integer_zero_node);
- cleanup = tree_cons (NULL_TREE, cleanup,
- build_tree_list (NULL_TREE, cleanup_deallocate));
-
- expand_decl_cleanup (allocated_this,
- build (COND_EXPR, integer_type_node,
- build (NE_EXPR, integer_type_node,
- allocated_this, integer_zero_node),
- build_compound_expr (cleanup),
- integer_zero_node));
- }
- }
- else if (TREE_GETS_NEW (current_class_type))
- /* Just check visibility here. */
- build_method_call (build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), error_mark_node),
- ansi_opname[(int) NEW_EXPR],
- build_tree_list (NULL_TREE, integer_zero_node),
- NULL_TREE, LOOKUP_NORMAL);
-
- CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
-
- /* must keep the first insn safe. */
- head = get_insns ();
-
- /* this note will come up to the top with us. */
- mark = get_last_insn ();
-
- if (flag_this_is_variable > 0)
- {
- expand_start_cond (cond, 0);
- expand_expr_stmt (thenclause);
- if (flag_handle_exceptions == 2)
- expand_assignment (allocated_this, current_class_decl, 0, 0);
- expand_end_cond ();
- }
-
- if (DECL_NAME (fndecl) == NULL_TREE
- && TREE_CHAIN (DECL_ARGUMENTS (fndecl)) != NULL_TREE)
- build_default_constructor (fndecl);
-
- /* Emit insns from `emit_base_init' which sets up virtual
- function table pointer(s). */
- emit_insns (base_init_insns);
- base_init_insns = NULL_RTX;
-
- /* This is where the body of the constructor begins.
- If there were no insns in this function body, then the
- last_parm_insn is also the last insn.
-
- If optimization is enabled, last_parm_insn may move, so
- we don't hold on to it (across emit_base_init). */
- last_parm_insn = get_first_nonparm_insn ();
- if (last_parm_insn == NULL_RTX) last_parm_insn = mark;
- else last_parm_insn = previous_insn (last_parm_insn);
-
- if (mark != get_last_insn ())
- reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
-
- /* This is where the body of the constructor ends. */
- expand_label (ctor_label);
- ctor_label = NULL_TREE;
- if (flag_handle_exceptions == 2)
- {
- expand_assignment (allocated_this, integer_zero_node, 0, 0);
- if (call_poplevel)
- deactivate_exception_cleanups ();
- }
-
- pop_implicit_try_blocks (NULL_TREE);
-
- if (call_poplevel)
- {
- expand_end_bindings (getdecls (), 1, 0);
- poplevel (1, 1, 0);
- }
-
- c_expand_return (current_class_decl);
-
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
- }
- else if (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- {
- /* Make it so that `main' always returns 0 by default. */
-#ifdef VMS
- c_expand_return (integer_one_node);
-#else
- c_expand_return (integer_zero_node);
-#endif
- }
- else if (return_label != NULL_RTX
- && current_function_return_value == NULL_TREE
- && ! DECL_NAME (DECL_RESULT (current_function_decl)))
- no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- if (flag_gc)
- expand_gc_prologue_and_epilogue ();
-
- /* That's the end of the vtable decl's life. Need to mark it such
- if doing stupid register allocation.
-
- Note that current_vtable_decl is really an INDIRECT_REF
- on top of a VAR_DECL here. */
- if (obey_regdecls && current_vtable_decl)
- use_variable (DECL_RTL (TREE_OPERAND (current_vtable_decl, 0)));
-
- /* If this function is supposed to return a value, ensure that
- we do not fall into the cleanups by mistake. The end of our
- function will look like this:
-
- user code (may have return stmt somewhere)
- goto no_return_label
- cleanup_label:
- cleanups
- goto return_label
- no_return_label:
- NOTE_INSN_FUNCTION_END
- return_label:
- things for return
-
- If the user omits a return stmt in the USER CODE section, we
- will have a control path which reaches NOTE_INSN_FUNCTION_END.
- Otherwise, we won't. */
- if (no_return_label)
- {
- DECL_CONTEXT (no_return_label) = fndecl;
- DECL_INITIAL (no_return_label) = error_mark_node;
- DECL_SOURCE_FILE (no_return_label) = input_filename;
- DECL_SOURCE_LINE (no_return_label) = lineno;
- expand_goto (no_return_label);
- }
-
- if (cleanup_label)
- {
- /* remove the binding contour which is used
- to catch cleanup-generated temporaries. */
- expand_end_bindings (0, 0, 0);
- poplevel (0, 0, 0);
- }
-
- if (cleanup_label)
- /* Emit label at beginning of cleanup code for parameters. */
- emit_label (cleanup_label);
-
-#if 1
- /* Cheap hack to get better code from GNU C++. Remove when cse is fixed. */
- if (exception_throw_decl && sets_exception_throw_decl == 0)
- expand_assignment (exception_throw_decl, integer_zero_node, 0, 0);
-#endif
-
- if (flag_handle_exceptions)
- {
- expand_end_try ();
- expand_start_except (0, 0);
- expand_end_except ();
- }
- expand_end_bindings (0, 0, 0);
-
- /* Get return value into register if that's where it's supposed to be. */
- if (original_result_rtx)
- fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
-
- /* Finish building code that will trigger warnings if users forget
- to make their functions return values. */
- if (no_return_label || cleanup_label)
- emit_jump (return_label);
- if (no_return_label)
- {
- /* We don't need to call `expand_*_return' here because we
- don't need any cleanups here--this path of code is only
- for error checking purposes. */
- expand_label (no_return_label);
- }
-
- /* reset scope for C++: if we were in the scope of a class,
- then when we finish this function, we are not longer so.
- This cannot be done until we know for sure that no more
- class members will ever be referenced in this function
- (i.e., calls to destructors). */
- if (current_class_name)
- {
- ctype = current_class_type;
- popclass (1);
- }
- else
- pop_memoized_context (1);
-
- /* Forget about all overloaded functions defined in
- this scope which go away. */
- while (overloads_to_forget)
- {
- IDENTIFIER_GLOBAL_VALUE (TREE_PURPOSE (overloads_to_forget))
- = TREE_VALUE (overloads_to_forget);
- overloads_to_forget = TREE_CHAIN (overloads_to_forget);
- }
-
- /* Generate rtl for function exit. */
- expand_function_end (input_filename, lineno);
-
- /* This must come after expand_function_end because cleanups might
- have declarations (from inline functions) that need to go into
- this function's blocks. */
- if (current_binding_level->parm_flag != 1)
- my_friendly_abort (122);
- poplevel (1, 0, 1);
-
- /* Must mark the RESULT_DECL as being in this function. */
- DECL_CONTEXT (DECL_RESULT (fndecl)) = DECL_INITIAL (fndecl);
-
- /* Obey `register' declarations if `setjmp' is called in this fn. */
- if (flag_traditional && current_function_calls_setjmp)
- setjmp_protect (DECL_INITIAL (fndecl));
-
- /* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point
- to the FUNCTION_DECL node itself. */
- BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
-
- /* So we can tell if jump_optimize sets it to 1. */
- can_reach_end = 0;
-
- /* ??? Compensate for Sun brain damage in dealing with data segments
- of PIC code. */
- if (flag_pic
- && (DECL_CONSTRUCTOR_P (fndecl)
- || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
- && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))
- DECL_INLINE (fndecl) = 0;
-
- if (DECL_EXTERNAL (fndecl)
- /* This function is just along for the ride. If we can make
- it inline, that's great. Otherwise, just punt it. */
- && (DECL_INLINE (fndecl) == 0
- || flag_no_inline
- || function_cannot_inline_p (fndecl)))
- {
- extern int rtl_dump_and_exit;
- int old_rtl_dump_and_exit = rtl_dump_and_exit;
- int inline_spec = DECL_INLINE (fndecl);
-
- /* This throws away the code for FNDECL. */
- rtl_dump_and_exit = 1;
- /* This throws away the memory of the code for FNDECL. */
- if (flag_no_inline)
- DECL_INLINE (fndecl) = 0;
- rest_of_compilation (fndecl);
- rtl_dump_and_exit = old_rtl_dump_and_exit;
- DECL_INLINE (fndecl) = inline_spec;
- }
- else
- {
- /* Run the optimizers and output the assembler code for this function. */
- rest_of_compilation (fndecl);
- }
-
- if (ctype && TREE_ASM_WRITTEN (fndecl))
- note_debug_info_needed (ctype);
-
- current_function_returns_null |= can_reach_end;
-
- /* Since we don't normally go through c_expand_return for constructors,
- this normally gets the wrong value.
- Also, named return values have their return codes emitted after
- NOTE_INSN_FUNCTION_END, confusing jump.c. */
- if (DECL_CONSTRUCTOR_P (fndecl)
- || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE)
- current_function_returns_null = 0;
-
- if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
- warning ("`volatile' function does return");
- else if (warn_return_type && current_function_returns_null
- && TYPE_MAIN_VARIANT (TREE_TYPE (fntype)) != void_type_node)
- {
- /* If this function returns non-void and control can drop through,
- complain. */
- pedwarn ("control reaches end of non-void function");
- }
- /* With just -W, complain only if function returns both with
- and without a value. */
- else if (extra_warnings
- && current_function_returns_value && current_function_returns_null)
- warning ("this function may return with or without a value");
-
- /* Free all the tree nodes making up this function. */
- /* Switch back to allocating nodes permanently
- until we start another function. */
- permanent_allocation ();
-
- if (flag_cadillac)
- cadillac_finish_function (fndecl);
-
- if (DECL_SAVED_INSNS (fndecl) == NULL_RTX)
- {
- /* Stop pointing to the local nodes about to be freed. */
- /* But DECL_INITIAL must remain nonzero so we know this
- was an actual function definition. */
- DECL_INITIAL (fndecl) = error_mark_node;
- if (! DECL_CONSTRUCTOR_P (fndecl)
- || !TYPE_USES_VIRTUAL_BASECLASSES (TYPE_METHOD_BASETYPE (fntype)))
- DECL_ARGUMENTS (fndecl) = NULL_TREE;
- }
-
- /* Let the error reporting routines know that we're outside a function. */
- current_function_decl = NULL_TREE;
- named_label_uses = NULL_TREE;
- clear_anon_parm_name ();
-}
-
-/* Create the FUNCTION_DECL for a function definition.
- LINE1 is the line number that the definition absolutely begins on.
- LINE2 is the line number that the name of the function appears on.
- DECLSPECS and DECLARATOR are the parts of the declaration;
- they describe the function's name and the type it returns,
- but twisted together in a fashion that parallels the syntax of C.
-
- This function creates a binding context for the function body
- as well as setting up the FUNCTION_DECL in current_function_decl.
-
- Returns a FUNCTION_DECL on success.
-
- If the DECLARATOR is not suitable for a function (it defines a datum
- instead), we return 0, which tells yyparse to report a parse error.
-
- May return void_type_node indicating that this method is actually
- a friend. See grokfield for more details.
-
- Came here with a `.pushlevel' .
-
- DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
- CHANGES TO CODE IN `grokfield'. */
-tree
-start_method (declspecs, declarator, raises)
- tree declarator, declspecs, raises;
-{
- tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, raises);
-
- /* Something too ugly to handle. */
- if (fndecl == NULL_TREE)
- return NULL_TREE;
-
- /* Pass friends other than inline friend functions back. */
- if (TYPE_MAIN_VARIANT (fndecl) == void_type_node)
- return fndecl;
-
- if (TREE_CODE (fndecl) != FUNCTION_DECL)
- /* Not a function, tell parser to report parse error. */
- return NULL_TREE;
-
- if (DECL_IN_AGGR_P (fndecl))
- {
- if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type)
- {
- if (DECL_CONTEXT (fndecl))
- error_with_decl (fndecl, "`%s' is already defined in class %s",
- TYPE_NAME_STRING (DECL_CONTEXT (fndecl)));
- }
- return void_type_node;
- }
-
- /* If we're expanding a template, a function must be explicitly declared
- inline if we're to compile it now. If it isn't, we have to wait to see
- whether it's needed, and whether an override exists. */
- if (flag_default_inline && !processing_template_defn)
- DECL_INLINE (fndecl) = 1;
-
- /* We read in the parameters on the maybepermanent_obstack,
- but we won't be getting back to them until after we
- may have clobbered them. So the call to preserve_data
- will keep them safe. */
- preserve_data ();
-
- if (! DECL_FRIEND_P (fndecl))
- {
- if (DECL_CHAIN (fndecl) != NULL_TREE)
- {
- /* Need a fresh node here so that we don't get circularity
- when we link these together. If FNDECL was a friend, then
- `pushdecl' does the right thing, which is nothing wrt its
- current value of DECL_CHAIN. */
- fndecl = copy_node (fndecl);
- }
- if (TREE_CHAIN (fndecl))
- {
- fndecl = copy_node (fndecl);
- TREE_CHAIN (fndecl) = NULL_TREE;
- }
-
- if (DECL_CONSTRUCTOR_P (fndecl))
- grok_ctor_properties (current_class_type, fndecl);
- else if (IDENTIFIER_OPNAME_P (DECL_NAME (fndecl)))
- grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl));
- }
-
- finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
-
- /* Make a place for the parms */
- pushlevel (0);
- current_binding_level->parm_flag = 1;
-
- DECL_IN_AGGR_P (fndecl) = 1;
- return fndecl;
-}
-
-/* Go through the motions of finishing a function definition.
- We don't compile this method until after the whole class has
- been processed.
-
- FINISH_METHOD must return something that looks as though it
- came from GROKFIELD (since we are defining a method, after all).
-
- This is called after parsing the body of the function definition.
- STMTS is the chain of statements that makes up the function body.
-
- DECL is the ..._DECL that `start_method' provided. */
-
-tree
-finish_method (decl)
- tree decl;
-{
- register tree fndecl = decl;
- tree old_initial;
- tree context = DECL_CONTEXT (fndecl);
-
- register tree link;
-
- if (TYPE_MAIN_VARIANT (decl) == void_type_node)
- return decl;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "finish_method");
- debug_bindings_indentation += 4;
-#endif
-
- old_initial = DECL_INITIAL (fndecl);
-
- /* Undo the level for the parms (from start_method).
- This is like poplevel, but it causes nothing to be
- saved. Saving information here confuses symbol-table
- output routines. Besides, this information will
- be correctly output when this method is actually
- compiled. */
-
- /* Clear out the meanings of the local variables of this level;
- also record in each decl which block it belongs to. */
-
- for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
- {
- if (DECL_NAME (link) != NULL_TREE)
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
- my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
- DECL_CONTEXT (link) = NULL_TREE;
- }
-
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-
- GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
- (HOST_WIDE_INT) current_binding_level->level_chain,
- current_binding_level->parm_flag,
- current_binding_level->keep,
- current_binding_level->tag_transparent);
-
- pop_binding_level ();
-
- DECL_INITIAL (fndecl) = old_initial;
-#if 0
- /* tiemann would like this, but is causes String.cc to not compile. */
- if (DECL_FRIEND_P (fndecl) || DECL_CONTEXT (fndecl) != current_class_type)
-#else
- if (DECL_FRIEND_P (fndecl))
-#endif
- {
- CLASSTYPE_INLINE_FRIENDS (current_class_type)
- = tree_cons (NULL_TREE, fndecl, CLASSTYPE_INLINE_FRIENDS (current_class_type));
- decl = void_type_node;
- }
-#if 0
- /* Work in progress, 9/17/92. */
- else if (context != current_class_type
- && TREE_CHAIN (context) != NULL_TREE
- && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))
- {
- /* Don't allow them to declare a function like this:
- class A {
- public:
- class B {
- public:
- int f();
- };
- int B::f() {}
- };
-
- Note we can get in here if it's a friend (in which case we'll
- avoid lots of nasty cruft), or it's a destructor. Compensate.
- */
- tree tmp = DECL_ARGUMENTS (TREE_CHAIN (context));
- if (tmp
- && TREE_CODE (tmp) == IDENTIFIER_NODE
- && TREE_CHAIN (IDENTIFIER_GLOBAL_VALUE (tmp))
- && TREE_CODE (TREE_CHAIN (IDENTIFIER_GLOBAL_VALUE (tmp))) == TYPE_DECL)
- {
- error_with_decl (decl,
- "qualified name used in declaration of `%s'");
- /* Make this node virtually unusable in the end. */
- TREE_CHAIN (decl) = NULL_TREE;
- }
- }
-#endif
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-
- return decl;
-}
-
-/* Called when a new struct TYPE is defined.
- If this structure or union completes the type of any previous
- variable declaration, lay it out and output its rtl. */
-
-void
-hack_incomplete_structures (type)
- tree type;
-{
- tree decl;
-
- if (current_binding_level->n_incomplete == 0)
- return;
-
- if (!type) /* Don't do this for class templates. */
- return;
-
- for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl))
- if (TREE_TYPE (decl) == type
- || (TREE_TYPE (decl)
- && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (decl)) == type))
- {
- if (TREE_CODE (decl) == TYPE_DECL)
- layout_type (TREE_TYPE (decl));
- else
- {
- int toplevel = global_binding_level == current_binding_level;
- if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (decl)) == type)
- layout_type (TREE_TYPE (decl));
- layout_decl (decl, 0);
- rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
- if (! toplevel)
- {
- expand_decl (decl);
- expand_decl_cleanup (decl, maybe_build_cleanup (decl));
- expand_decl_init (decl);
- }
- }
- my_friendly_assert (current_binding_level->n_incomplete > 0, 164);
- --current_binding_level->n_incomplete;
- }
-}
-
-/* Nonzero if presently building a cleanup. Needed because
- SAVE_EXPRs are not the right things to use inside of cleanups.
- They are only ever evaluated once, where the cleanup
- might be evaluated several times. In this case, a later evaluation
- of the cleanup might fill in the SAVE_EXPR_RTL, and it will
- not be valid for an earlier cleanup. */
-
-int building_cleanup;
-
-/* If DECL is of a type which needs a cleanup, build that cleanup here.
- We don't build cleanups if just going for syntax checking, since
- fixup_cleanups does not know how to not handle them.
-
- Don't build these on the momentary obstack; they must live
- the life of the binding contour. */
-tree
-maybe_build_cleanup (decl)
- tree decl;
-{
- tree type = TREE_TYPE (decl);
- if (TYPE_NEEDS_DESTRUCTOR (type))
- {
- int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
- tree rval;
- int old_building_cleanup = building_cleanup;
- building_cleanup = 1;
-
- if (TREE_CODE (decl) != PARM_DECL)
- temp = suspend_momentary ();
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- rval = decl;
- else
- {
- mark_addressable (decl);
- rval = build_unary_op (ADDR_EXPR, decl, 0);
- }
-
- /* Optimize for space over speed here. */
- if (! TYPE_USES_VIRTUAL_BASECLASSES (type)
- || flag_expensive_optimizations)
- flags |= LOOKUP_NONVIRTUAL;
-
- /* Use TYPE_MAIN_VARIANT so we don't get a warning about
- calling delete on a `const' variable. */
- if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (rval))))
- rval = build1 (NOP_EXPR, TYPE_POINTER_TO (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (rval)))), rval);
-
- rval = build_delete (TREE_TYPE (rval), rval, integer_two_node, flags, 0, 0);
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (type)
- && ! TYPE_HAS_DESTRUCTOR (type))
- rval = build_compound_expr (tree_cons (NULL_TREE, rval,
- build_tree_list (NULL_TREE, build_vbase_delete (type, decl))));
-
- current_binding_level->have_cleanups = 1;
- current_binding_level->more_exceptions_ok = 0;
-
- if (TREE_CODE (decl) != PARM_DECL)
- resume_momentary (temp);
-
- building_cleanup = old_building_cleanup;
-
- return rval;
- }
- return 0;
-}
-
-/* Expand a C++ expression at the statement level.
- This is needed to ferret out nodes which have UNKNOWN_TYPE.
- The C++ type checker should get all of these out when
- expressions are combined with other, type-providing, expressions,
- leaving only orphan expressions, such as:
-
- &class::bar; / / takes its address, but does nothing with it.
-
- */
-void
-cplus_expand_expr_stmt (exp)
- tree exp;
-{
- if (TREE_TYPE (exp) == unknown_type_node)
- {
- if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST)
- error ("address of overloaded function with no contextual type information");
- else if (TREE_CODE (exp) == COMPONENT_REF)
- warning ("useless reference to a member function name, did you forget the ()?");
- }
- else
- {
- int remove_implicit_immediately = 0;
-
- if (TREE_CODE (exp) == FUNCTION_DECL)
- {
- warning_with_decl (exp, "reference, not call, to function `%s'");
- warning ("at this point in file");
- }
- if (TREE_RAISES (exp))
- {
- my_friendly_assert (flag_handle_exceptions, 165);
- if (flag_handle_exceptions == 2)
- {
- if (! current_binding_level->more_exceptions_ok)
- {
- extern struct nesting *nesting_stack, *block_stack;
-
- remove_implicit_immediately
- = (nesting_stack != block_stack);
- cplus_expand_start_try (1);
- }
- current_binding_level->have_exceptions = 1;
- }
- }
-
- expand_expr_stmt (break_out_cleanups (exp));
-
- if (remove_implicit_immediately)
- pop_implicit_try_blocks (NULL_TREE);
- }
-
- /* Clean up any pending cleanups. This happens when a function call
- returns a cleanup-needing value that nobody uses. */
- expand_cleanups_to (NULL_TREE);
-}
-
-/* When a stmt has been parsed, this function is called.
-
- Currently, this function only does something within a
- constructor's scope: if a stmt has just assigned to this,
- and we are in a derived class, we call `emit_base_init'. */
-
-void
-finish_stmt ()
-{
- extern struct nesting *cond_stack, *loop_stack, *case_stack;
-
-
- if (current_function_assigns_this
- || ! current_function_just_assigned_this)
- return;
- if (DECL_CONSTRUCTOR_P (current_function_decl))
- {
- /* Constructors must wait until we are out of control
- zones before calling base constructors. */
- if (cond_stack || loop_stack || case_stack)
- return;
- emit_insns (base_init_insns);
- check_base_init (current_class_type);
- }
- current_function_assigns_this = 1;
-
- if (flag_cadillac)
- cadillac_finish_stmt ();
-}
-
-void
-pop_implicit_try_blocks (decl)
- tree decl;
-{
- if (decl)
- {
- my_friendly_assert (current_binding_level->parm_flag == 3, 166);
- current_binding_level->names = TREE_CHAIN (decl);
- }
-
- while (current_binding_level->parm_flag == 3)
- {
- tree name = get_identifier ("(compiler error)");
- tree orig_ex_type = current_exception_type;
- tree orig_ex_decl = current_exception_decl;
- tree orig_ex_obj = current_exception_object;
- tree decl = cplus_expand_end_try (2);
-
- /* @@ It would be nice to make all these point
- to exactly the same handler. */
- /* Start hidden EXCEPT. */
- cplus_expand_start_except (name, decl);
- /* reraise ALL. */
- cplus_expand_reraise (NULL_TREE);
- current_exception_type = orig_ex_type;
- current_exception_decl = orig_ex_decl;
- current_exception_object = orig_ex_obj;
- /* This will reraise for us. */
- cplus_expand_end_except (error_mark_node);
- }
-
- if (decl)
- {
- TREE_CHAIN (decl) = current_binding_level->names;
- current_binding_level->names = decl;
- }
-}
-
-/* Push a cleanup onto the current binding contour that will cause
- ADDR to be cleaned up, in the case that an exception propagates
- through its binding contour. */
-
-void
-push_exception_cleanup (addr)
- tree addr;
-{
- tree decl = build_decl (VAR_DECL, get_identifier (EXCEPTION_CLEANUP_NAME), ptr_type_node);
- tree cleanup;
-
- decl = pushdecl (decl);
- DECL_REGISTER (decl) = 1;
- store_init_value (decl, addr);
- expand_decl (decl);
- expand_decl_init (decl);
-
- cleanup = build (COND_EXPR, integer_type_node,
- build (NE_EXPR, integer_type_node,
- decl, integer_zero_node),
- build_delete (TREE_TYPE (addr), decl,
- lookup_name (in_charge_identifier, 0),
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0),
- integer_zero_node);
- expand_decl_cleanup (decl, cleanup);
-}
-
-/* For each binding contour, emit code that deactivates the
- exception cleanups. All other cleanups are left as they were. */
-
-static void
-deactivate_exception_cleanups ()
-{
- struct binding_level *b = current_binding_level;
- tree xyzzy = get_identifier (EXCEPTION_CLEANUP_NAME);
- while (b != class_binding_level)
- {
- if (b->parm_flag == 3)
- {
- tree decls = b->names;
- while (decls)
- {
- if (DECL_NAME (decls) == xyzzy)
- expand_assignment (decls, integer_zero_node, 0, 0);
- decls = TREE_CHAIN (decls);
- }
- }
- b = b->level_chain;
- }
-}
-
-/* Change a static member function definition into a FUNCTION_TYPE, instead
- of the METHOD_TYPE that we create when it's originally parsed. */
-void
-revert_static_member_fn (fn, decl, argtypes)
- tree *fn, *decl, *argtypes;
-{
- tree tmp, function = *fn;
-
- *argtypes = TREE_CHAIN (*argtypes);
- tmp = build_function_type (TREE_TYPE (function), *argtypes);
- tmp = build_type_variant (tmp, TYPE_READONLY (function),
- TYPE_VOLATILE (function));
- tmp = build_exception_variant (TYPE_METHOD_BASETYPE (function), tmp,
- TYPE_RAISES_EXCEPTIONS (function));
- TREE_TYPE (*decl) = tmp;
- *fn = tmp;
- DECL_STATIC_FUNCTION_P (*decl) = 1;
-}
diff --git a/gnu/gcc2/cc1plus/cp-decl.h b/gnu/gcc2/cc1plus/cp-decl.h
deleted file mode 100644
index aabfa2fb9264..000000000000
--- a/gnu/gcc2/cc1plus/cp-decl.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Variables and structures for declaration processing.
- Copyright (C) 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* In grokdeclarator, distinguish syntactic contexts of declarators. */
-enum decl_context
-{ NORMAL, /* Ordinary declaration */
- FUNCDEF, /* Function definition */
- PARM, /* Declaration of parm before function body */
- FIELD, /* Declaration inside struct or union */
- BITFIELD, /* Likewise but with specified width */
- TYPENAME, /* Typename (inside cast or sizeof) */
- MEMFUNCDEF /* Member function definition */
-};
-
-/* C++: Keep these around to reduce calls to `get_identifier'.
- Identifiers for `this' in member functions and the auto-delete
- parameter for destructors. */
-extern tree this_identifier, in_charge_identifier;
-
-/* Parsing a function declarator leaves a list of parameter names
- or a chain or parameter decls here. */
-extern tree last_function_parms;
-
-/* A list of static class variables. This is needed, because a
- static class variable can be declared inside the class without
- an initializer, and then initialized, staticly, outside the class. */
-extern tree pending_statics;
-
-/* A list of objects which have constructors or destructors
- which reside in the global scope. The decl is stored in
- the TREE_VALUE slot and the initializer is stored
- in the TREE_PURPOSE slot. */
-extern tree static_aggregates;
-
-/* A list of functions which were declared inline, but later had their
- address taken. Used only for non-virtual member functions, since we can
- find other functions easily enough. */
-extern tree pending_addressable_inlines;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
-/* Purely for debugging purposes. */
-extern int debug_bindings_indentation;
-#endif
diff --git a/gnu/gcc2/cc1plus/cp-decl2.c b/gnu/gcc2/cc1plus/cp-decl2.c
deleted file mode 100644
index bb1a9cd7b828..000000000000
--- a/gnu/gcc2/cc1plus/cp-decl2.c
+++ /dev/null
@@ -1,2451 +0,0 @@
-/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-
-/* Process declarations and symbol lookup for C front end.
- Also constructs types; the standard scalar types at initialization,
- and structure, union, array and enum types when they are declared. */
-
-/* ??? not all decl nodes are given the most useful possible
- line numbers. For example, the CONST_DECLs for enum values. */
-
-#include "config.h"
-#include <stdio.h>
-#include "tree.h"
-#include "rtl.h"
-#include "flags.h"
-#include "cp-tree.h"
-#include "cp-decl.h"
-#include "cp-lex.h"
-
-extern tree grokdeclarator ();
-static void grok_function_init ();
-
-/* A list of virtual function tables we must make sure to write out. */
-tree pending_vtables;
-
-/* A list of static class variables. This is needed, because a
- static class variable can be declared inside the class without
- an initializer, and then initialized, staticly, outside the class. */
-tree pending_statics;
-
-extern tree pending_addressable_inlines;
-
-/* Used to help generate temporary names which are unique within
- a function. Reset to 0 by start_function. */
-
-static int temp_name_counter;
-
-/* Same, but not reset. Local temp variables and global temp variables
- can have the same name. */
-static int global_temp_name_counter;
-
-/* The (assembler) name of the first globally-visible object output. */
-extern char * first_global_object_name;
-
-/* Flag used when debugging cp-spew.c */
-
-extern int spew_debug;
-
-/* C (and C++) language-specific option variables. */
-
-/* Nonzero means allow type mismatches in conditional expressions;
- just make their values `void'. */
-
-int flag_cond_mismatch;
-
-/* Nonzero means give `double' the same size as `float'. */
-
-int flag_short_double;
-
-/* Nonzero means don't recognize the keyword `asm'. */
-
-int flag_no_asm;
-
-/* Nonzero means don't recognize the non-ANSI builtin functions. */
-
-int flag_no_builtin;
-
-/* Nonzero means do some things the same way PCC does. */
-
-int flag_traditional;
-
-/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */
-
-int flag_signed_bitfields = 1;
-
-/* Nonzero means handle `#ident' directives. 0 means ignore them. */
-
-int flag_no_ident = 0;
-
-/* Nonzero means handle things in ANSI, instead of GNU fashion. This
- flag should be tested for language behavior that's different between
- ANSI and GNU, but not so horrible as to merit a PEDANTIC label. */
-
-int flag_ansi = 0;
-
-/* Nonzero means do emit exported implementations of functions even if
- they can be inlined. */
-
-int flag_implement_inlines = 1;
-
-/* Nonzero means warn about implicit declarations. */
-
-int warn_implicit = 1;
-
-/* Like `warn_return_type', but this is set by users, whereas
- `warn_return_type' is set by the compiler. */
-
-int explicit_warn_return_type;
-
-/* Nonzero means give string constants the type `const char *'
- to get extra warnings from them. These warnings will be too numerous
- to be useful, except in thoroughly ANSIfied programs. */
-
-int warn_write_strings;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-int warn_cast_qual;
-
-/* Nonzero means warn that dbx info for template class methods isn't fully
- supported yet. */
-
-int warn_template_debugging;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C. */
-
-int warn_traditional;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
- of function pointers. */
-
-int warn_pointer_arith;
-
-/* Nonzero means warn for non-prototype function decls
- or non-prototyped defs without previous prototype. */
-
-int warn_strict_prototypes;
-
-/* Nonzero means warn for any function def without prototype decl. */
-
-int warn_missing_prototypes;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-int warn_redundant_decls;
-
-/* Warn about *printf or *scanf format/argument anomalies. */
-
-int warn_format;
-
-/* Warn about a subscript that has type char. */
-
-int warn_char_subscripts = 0;
-
-/* Warn if a type conversion is done that might have confusing results. */
-
-int warn_conversion;
-
-/* Warn if adding () is suggested. */
-
-int warn_parentheses = 1;
-
-/* Non-zero means warn in function declared in derived class has the
- same name as a virtual in the base class, but fails to match the
- type signature of any virtual function in the base class. */
-int warn_overloaded_virtual;
-
-/* Non-zero means warn when converting between different enumeral types. */
-int warn_enum_clash;
-
-/* Non-zero means warn when declaring a class that has a non virtual
- destructor, when it really ought to have a virtual one. */
-int warn_nonvdtor = 1;
-
-/* Nonzero means `$' can be in an identifier.
- See cccp.c for reasons why this breaks some obscure ANSI C programs. */
-
-#ifndef DOLLARS_IN_IDENTIFIERS
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
-int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-
-/* Nonzero for -no-strict-prototype switch: do not consider empty
- argument prototype to mean function takes no arguments. */
-
-int strict_prototype = 1;
-int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus = 1;
-
-/* Nonzero means that labels can be used as first-class objects */
-
-int flag_labels_ok;
-
-/* Non-zero means to collect statistics which might be expensive
- and to print them when we are done. */
-int flag_detailed_statistics;
-
-/* C++ specific flags. */
-/* Nonzero for -fall-virtual: make every member function (except
- constructors) lay down in the virtual function table. Calls
- can then either go through the virtual function table or not,
- depending. */
-
-int flag_all_virtual;
-
-/* Zero means that `this' is a *const. This gives nice behavior in the
- 2.0 world. 1 gives 1.2-compatible behavior. 2 gives Spring behavior.
- -2 means we're constructing an object and it has fixed type. */
-
-int flag_this_is_variable;
-
-/* Nonzero means memoize our member lookups. */
-
-int flag_memoize_lookups; int flag_save_memoized_contexts;
-
-/* 3 means write out only virtuals function tables `defined'
- in this implementation file.
- 2 means write out only specific virtual function tables
- and give them (C) public visibility.
- 1 means write out virtual function tables and give them
- (C) public visibility.
- 0 means write out virtual function tables and give them
- (C) static visibility (default).
- -1 means declare virtual function tables extern. */
-
-int write_virtuals;
-
-/* Nonzero means we should attempt to elide constructors when possible. */
-
-int flag_elide_constructors;
-
-/* Same, but for inline functions: nonzero means write out debug info
- for inlines. Zero means do not. */
-
-int flag_inline_debug;
-
-/* Nonzero means recognize and handle exception handling constructs.
- 2 means handle exceptions the way Spring wants them handled. */
-
-int flag_handle_exceptions;
-
-/* Nonzero means recognize and handle exception handling constructs.
- Use ansi syntax and semantics. WORK IN PROGRESS!
- 2 means handle exceptions the way Spring wants them handled. */
-
-int flag_ansi_exceptions;
-
-/* Nonzero means that member functions defined in class scope are
- inline by default. */
-
-int flag_default_inline = 1;
-
-/* Controls whether enums and ints freely convert.
- 1 means with complete freedom.
- 0 means enums can convert to ints, but not vice-versa. */
-int flag_int_enum_equivalence;
-
-/* Controls whether compiler is operating under LUCID's Cadillac
- system. 1 means yes, 0 means no. */
-int flag_cadillac;
-
-/* Controls whether compiler generates code to build objects
- that can be collected when they become garbage. */
-int flag_gc;
-
-/* Controls whether compiler generates 'dossiers' that give
- run-time type information. */
-int flag_dossier;
-
-/* Nonzero if we wish to output cross-referencing information
- for the GNU class browser. */
-extern int flag_gnu_xref;
-
-/* Nonzero if compiler can make `reasonable' assumptions about
- references and objects. For example, the compiler must be
- conservative about the following and not assume that `a' is nonnull:
-
- obj &a = g ();
- a.f (2);
-
- In general, it is `reasonable' to assume that for many programs,
- and better code can be generated in that case. */
-
-int flag_assume_nonnull_objects;
-
-/* Table of language-dependent -f options.
- STRING is the option name. VARIABLE is the address of the variable.
- ON_VALUE is the value to store in VARIABLE
- if `-fSTRING' is seen as an option.
- (If `-fno-STRING' is seen as an option, the opposite value is stored.) */
-
-static struct { char *string; int *variable; int on_value;} lang_f_options[] =
-{
- {"signed-char", &flag_signed_char, 1},
- {"unsigned-char", &flag_signed_char, 0},
- {"signed-bitfields", &flag_signed_bitfields, 1},
- {"unsigned-bitfields", &flag_signed_bitfields, 0},
- {"short-enums", &flag_short_enums, 1},
- {"short-double", &flag_short_double, 1},
- {"cond-mismatch", &flag_cond_mismatch, 1},
- {"asm", &flag_no_asm, 0},
- {"builtin", &flag_no_builtin, 0},
- {"ident", &flag_no_ident, 0},
- {"labels-ok", &flag_labels_ok, 1},
- {"stats", &flag_detailed_statistics, 1},
- {"this-is-variable", &flag_this_is_variable, 1},
- {"strict-prototype", &strict_prototypes_lang_cplusplus, 1},
- {"all-virtual", &flag_all_virtual, 1},
- {"memoize-lookups", &flag_memoize_lookups, 1},
- {"elide-constructors", &flag_elide_constructors, 1},
- {"inline-debug", &flag_inline_debug, 0},
- {"handle-exceptions", &flag_handle_exceptions, 1},
- {"ansi-exceptions", &flag_ansi_exceptions, 1},
- {"spring-exceptions", &flag_handle_exceptions, 2},
- {"default-inline", &flag_default_inline, 1},
- {"dollars-in-identifiers", &dollars_in_ident, 1},
- {"enum-int-equiv", &flag_int_enum_equivalence, 1},
- {"gc", &flag_gc, 1},
- {"dossier", &flag_dossier, 1},
- {"xref", &flag_gnu_xref, 1},
- {"nonnull-objects", &flag_assume_nonnull_objects, 1},
- {"implement-inlines", &flag_implement_inlines, 1},
-};
-
-/* Decode the string P as a language-specific option.
- Return 1 if it is recognized (and handle it);
- return 0 if not recognized. */
-
-int
-lang_decode_option (p)
- char *p;
-{
- if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
- flag_traditional = 1, dollars_in_ident = 1, flag_writable_strings = 1,
- flag_this_is_variable = 1;
- /* The +e options are for cfront compatibility. They come in as
- `-+eN', to kludge around gcc.c's argument handling. */
- else if (p[0] == '-' && p[1] == '+' && p[2] == 'e')
- {
- int old_write_virtuals = write_virtuals;
- if (p[3] == '1')
- write_virtuals = 1;
- else if (p[3] == '0')
- write_virtuals = -1;
- else if (p[3] == '2')
- write_virtuals = 2;
- else error ("invalid +e option");
- if (old_write_virtuals != 0
- && write_virtuals != old_write_virtuals)
- error ("conflicting +e options given");
- }
- else if (p[0] == '-' && p[1] == 'f')
- {
- /* Some kind of -f option.
- P's value is the option sans `-f'.
- Search for it in the table of options. */
- int found = 0, j;
-
- p += 2;
- /* Try special -f options. */
-
- if (!strcmp (p, "save-memoized"))
- {
- flag_memoize_lookups = 1;
- flag_save_memoized_contexts = 1;
- found = 1;
- }
- if (!strcmp (p, "no-save-memoized"))
- {
- flag_memoize_lookups = 0;
- flag_save_memoized_contexts = 0;
- found = 1;
- }
- else if (! strncmp (p, "cadillac", 8))
- {
- flag_cadillac = atoi (p+9);
- found = 1;
- }
- else if (! strncmp (p, "no-cadillac", 11))
- {
- flag_cadillac = 0;
- found = 1;
- }
- else if (! strcmp (p, "gc"))
- {
- flag_gc = 1;
- /* This must come along for the ride. */
- flag_dossier = 1;
- found = 1;
- }
- else if (! strcmp (p, "no-gc"))
- {
- flag_gc = 0;
- /* This must come along for the ride. */
- flag_dossier = 0;
- found = 1;
- }
- else for (j = 0;
- !found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]);
- j++)
- {
- if (!strcmp (p, lang_f_options[j].string))
- {
- *lang_f_options[j].variable = lang_f_options[j].on_value;
- /* A goto here would be cleaner,
- but breaks the vax pcc. */
- found = 1;
- }
- if (p[0] == 'n' && p[1] == 'o' && p[2] == '-'
- && ! strcmp (p+3, lang_f_options[j].string))
- {
- *lang_f_options[j].variable = ! lang_f_options[j].on_value;
- found = 1;
- }
- }
- return found;
- }
- else if (p[0] == '-' && p[1] == 'W')
- {
- int setting = 1;
-
- /* The -W options control the warning behavior of the compiler. */
- p += 2;
-
- if (p[0] == 'n' && p[1] == 'o' && p[2] == '-')
- setting = 0, p += 3;
-
- if (!strcmp (p, "implicit"))
- warn_implicit = setting;
- else if (!strcmp (p, "return-type"))
- explicit_warn_return_type = setting;
- else if (!strcmp (p, "write-strings"))
- warn_write_strings = setting;
- else if (!strcmp (p, "cast-qual"))
- warn_cast_qual = setting;
- else if (!strcmp (p, "traditional"))
- warn_traditional = setting;
- else if (!strcmp (p, "char-subscripts"))
- warn_char_subscripts = setting;
- else if (!strcmp (p, "pointer-arith"))
- warn_pointer_arith = setting;
- else if (!strcmp (p, "strict-prototypes"))
- warn_strict_prototypes = setting;
- else if (!strcmp (p, "missing-prototypes"))
- warn_missing_prototypes = setting;
- else if (!strcmp (p, "redundant-decls"))
- warn_redundant_decls = setting;
- else if (!strcmp (p, "format"))
- warn_format = setting;
- else if (!strcmp (p, "conversion"))
- warn_conversion = setting;
- else if (!strcmp (p, "parentheses"))
- warn_parentheses = setting;
- else if (!strcmp (p, "comment"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "comments"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "trigraphs"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "import"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "all"))
- {
- extra_warnings = setting;
- explicit_warn_return_type = setting;
- warn_unused = setting;
- warn_implicit = setting;
- warn_switch = setting;
- /* We save the value of warn_uninitialized, since if they put
- -Wuninitialized on the command line, we need to generate a
- warning about not using it without also specifying -O. */
- if (warn_uninitialized != 1)
- warn_uninitialized = (setting ? 2 : 0);
- warn_template_debugging = setting;
-#if 0
- warn_enum_clash = setting;
-#endif
- }
-
- else if (!strcmp (p, "overloaded-virtual"))
- warn_overloaded_virtual = setting;
- else if (!strcmp (p, "enum-clash"))
- warn_enum_clash = setting;
- else return 0;
- }
- else if (!strcmp (p, "-ansi"))
- flag_no_asm = 1, dollars_in_ident = 0, flag_ansi = 1;
-#ifdef SPEW_DEBUG
- /* Undocumented, only ever used when you're invoking cc1plus by hand, since
- it's probably safe to assume no sane person would ever want to use this
- under normal circumstances. */
- else if (!strcmp (p, "-spew-debug"))
- spew_debug = 1;
-#endif
- else
- return 0;
-
- return 1;
-}
-
-/* Incorporate `const' and `volatile' qualifiers for member functions.
- FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
- QUALS is a list of qualifiers. */
-tree
-grok_method_quals (ctype, function, quals)
- tree ctype, function, quals;
-{
- tree fntype = TREE_TYPE (function);
- tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
-
- do
- {
- extern tree ridpointers[];
-
- if (TREE_VALUE (quals) == ridpointers[(int)RID_CONST])
- {
- if (TYPE_READONLY (ctype))
- error ("duplicate `%s' %s",
- IDENTIFIER_POINTER (TREE_VALUE (quals)),
- (TREE_CODE (function) == FUNCTION_DECL
- ? "for member function" : "in type declaration"));
- ctype = build_type_variant (ctype, 1, TYPE_VOLATILE (ctype));
- build_pointer_type (ctype);
- }
- else if (TREE_VALUE (quals) == ridpointers[(int)RID_VOLATILE])
- {
- if (TYPE_VOLATILE (ctype))
- error ("duplicate `%s' %s",
- IDENTIFIER_POINTER (TREE_VALUE (quals)),
- (TREE_CODE (function) == FUNCTION_DECL
- ? "for member function" : "in type declaration"));
- ctype = build_type_variant (ctype, TYPE_READONLY (ctype), 1);
- build_pointer_type (ctype);
- }
- else
- my_friendly_abort (20);
- quals = TREE_CHAIN (quals);
- }
- while (quals);
- fntype = build_cplus_method_type (ctype, TREE_TYPE (fntype),
- (TREE_CODE (fntype) == METHOD_TYPE
- ? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
- : TYPE_ARG_TYPES (fntype)));
- if (raises)
- fntype = build_exception_variant (ctype, fntype, raises);
-
- TREE_TYPE (function) = fntype;
- return ctype;
-}
-
-/* This routine replaces cryptic DECL_NAMEs with readable DECL_NAMEs.
- It leaves DECL_ASSEMBLER_NAMEs with the correct value. */
-/* This does not yet work with user defined conversion operators
- It should. */
-static void
-substitute_nice_name (decl)
- tree decl;
-{
- if (DECL_NAME (decl) && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE)
- {
- char *n = decl_as_string (DECL_NAME (decl));
- if (n[strlen (n) - 1] == ' ')
- n[strlen (n) - 1] = 0;
- DECL_NAME (decl) = get_identifier (n);
- }
-}
-
-/* Classes overload their constituent function names automatically.
- When a function name is declared in a record structure,
- its name is changed to it overloaded name. Since names for
- constructors and destructors can conflict, we place a leading
- '$' for destructors.
-
- CNAME is the name of the class we are grokking for.
-
- FUNCTION is a FUNCTION_DECL. It was created by `grokdeclarator'.
-
- FLAGS contains bits saying what's special about today's
- arguments. 1 == DESTRUCTOR. 2 == OPERATOR.
-
- If FUNCTION is a destructor, then we must add the `auto-delete' field
- as a second parameter. There is some hair associated with the fact
- that we must "declare" this variable in the manner consistent with the
- way the rest of the arguments were declared.
-
- QUALS are the qualifiers for the this pointer. */
-
-void
-grokclassfn (ctype, cname, function, flags, quals)
- tree ctype, cname, function;
- enum overload_flags flags;
- tree quals;
-{
- tree fn_name = DECL_NAME (function);
- tree arg_types;
- tree parm;
-
- if (fn_name == NULL_TREE)
- {
- error ("name missing for member function");
- fn_name = get_identifier ("<anonymous>");
- DECL_NAME (function) = fn_name;
- }
-
- if (quals)
- ctype = grok_method_quals (ctype, function, quals);
-
- arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
- if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
- {
- /* Must add the class instance variable up front. */
- /* Right now we just make this a pointer. But later
- we may wish to make it special. */
- tree type = TREE_VALUE (arg_types);
-
- if (flags == DTOR_FLAG)
- type = TYPE_MAIN_VARIANT (type);
- else if (DECL_CONSTRUCTOR_P (function))
- {
- if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))
- {
- DECL_CONSTRUCTOR_FOR_VBASE_P (function) = 1;
- /* In this case we need "in-charge" flag saying whether
- this constructor is responsible for initialization
- of virtual baseclasses or not. */
- parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
- DECL_ARG_TYPE (parm) = integer_type_node;
- DECL_REGISTER (parm) = 1;
- TREE_CHAIN (parm) = last_function_parms;
- last_function_parms = parm;
- }
- }
-
- parm = build_decl (PARM_DECL, this_identifier, type);
- /* Mark the artificial `this' parameter as "artificial". */
- DECL_SOURCE_LINE (parm) = 0;
- DECL_ARG_TYPE (parm) = type;
- /* We can make this a register, so long as we don't
- accidentally complain if someone tries to take its address. */
- DECL_REGISTER (parm) = 1;
-#if 0
- /* it is wrong to flag the object as readonly, when
- flag_this_is_variable is 0. */
- if (flags != DTOR_FLAG
- && (flag_this_is_variable <= 0 || TYPE_READONLY (type)))
-#else
- if (flags != DTOR_FLAG && TYPE_READONLY (type))
-#endif
- TREE_READONLY (parm) = 1;
- TREE_CHAIN (parm) = last_function_parms;
- last_function_parms = parm;
- }
-
- if (flags == DTOR_FLAG)
- {
- char *buf, *dbuf;
- tree const_integer_type = build_type_variant (integer_type_node, 1, 0);
- int len = sizeof (DESTRUCTOR_DECL_PREFIX)-1;
-
- arg_types = hash_tree_chain (const_integer_type, void_list_node);
- /* Build the overload name. It will look like e.g. 7Example. */
- if (IDENTIFIER_TYPE_VALUE (cname))
- dbuf = build_overload_name (IDENTIFIER_TYPE_VALUE (cname), 1, 1);
- else if (IDENTIFIER_LOCAL_VALUE (cname))
- dbuf = build_overload_name (TREE_TYPE (IDENTIFIER_LOCAL_VALUE (cname)), 1, 1);
- else
-#if 0
- my_friendly_abort (346);
-#else
- /* Using ctype fixes the `X::Y::~Y()' crash. The cname has no type when
- it's defined out of the class definition, since poplevel_class wipes
- it out. */
- dbuf = build_overload_name (ctype, 1, 1);
-#endif
- buf = (char *)alloca (strlen (dbuf) + sizeof (DESTRUCTOR_DECL_PREFIX));
- bcopy (DESTRUCTOR_DECL_PREFIX, buf, len);
- buf[len] = '\0';
- strcat (buf, dbuf);
- DECL_ASSEMBLER_NAME (function) = get_identifier (buf);
- parm = build_decl (PARM_DECL, in_charge_identifier, const_integer_type);
- TREE_USED (parm) = 1;
- TREE_READONLY (parm) = 1;
- DECL_ARG_TYPE (parm) = const_integer_type;
- /* This is the same chain as DECL_ARGUMENTS (...). */
- TREE_CHAIN (last_function_parms) = parm;
-
- TREE_TYPE (function) = build_cplus_method_type (ctype, void_type_node, arg_types);
- TYPE_HAS_DESTRUCTOR (ctype) = 1;
- }
- else
- {
- tree these_arg_types;
-
- if (DECL_CONSTRUCTOR_FOR_VBASE_P (function))
- {
- arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types));
- TREE_TYPE (function)
- = build_cplus_method_type (ctype, TREE_TYPE (TREE_TYPE (function)), arg_types);
- arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
- }
-
- these_arg_types = arg_types;
-
- if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
- /* Only true for static member functions. */
- these_arg_types = hash_tree_chain (TYPE_POINTER_TO (ctype), arg_types);
-
- DECL_ASSEMBLER_NAME (function)
- = build_decl_overload (fn_name, these_arg_types,
- 1 + DECL_CONSTRUCTOR_P (function));
-
-#if 0
- /* This code is going into the compiler, but currently, it makes
- libg++/src/Interger.cc not compile. The problem is that the nice name
- winds up going into the symbol table, and conversion operations look
- for the manged name. */
- substitute_nice_name (function);
-#endif
-
-#if 0
- if (flags == TYPENAME_FLAG)
- /* Not exactly an IDENTIFIER_TYPE_VALUE. */
- TREE_TYPE (DECL_ASSEMBLER_NAME (function)) = TREE_TYPE (fn_name);
-#endif
- }
-
- DECL_ARGUMENTS (function) = last_function_parms;
- /* First approximations. */
- DECL_CONTEXT (function) = ctype;
- DECL_CLASS_CONTEXT (function) = ctype;
-}
-
-/* Generate errors possibly applicable for a given set of specifiers. */
-void
-bad_specifiers (object, virtualp, quals, friendp, raises)
- char *object;
- int virtualp, quals, friendp, raises;
-{
- if (virtualp)
- error ("%s declared `virtual'", object);
- if (quals)
- error ("`const' and `volatile' function specifiers invalid in %s declaration");
- if (friendp)
- error ("invalid friend declaration");
- if (raises)
- error ("invalid raises declaration");
-}
-
-/* Sanity check: report error if this function FUNCTION is not
- really a member of the class (CTYPE) it is supposed to belong to.
- CNAME and FLAGS are the same here as they are for grokclassfn above. */
-
-void
-check_classfn (ctype, cname, function)
- tree ctype, cname, function;
-{
- tree fn_name = DECL_NAME (function);
- tree fndecl;
- int need_quotes = 0;
- char *err_name;
- tree method_vec = CLASSTYPE_METHOD_VEC (ctype);
- tree *methods = 0;
- tree *end = 0;
-
- if (method_vec != 0)
- {
- methods = &TREE_VEC_ELT (method_vec, 0);
- end = TREE_VEC_END (method_vec);
-
- /* First suss out ctors and dtors. */
- if (*methods && fn_name == cname)
- goto got_it;
-
- while (++methods != end)
- {
- if (fn_name == DECL_NAME (*methods))
- {
- got_it:
- fndecl = *methods;
- while (fndecl)
- {
- if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))
- return;
- fndecl = DECL_CHAIN (fndecl);
- }
- break; /* loser */
- }
- }
- }
-
- if (fn_name == ansi_opname[(int) TYPE_EXPR])
- {
- if (TYPE_HAS_CONVERSION (ctype))
- err_name = "such type conversion operator";
- }
- else if (IDENTIFIER_OPNAME_P (fn_name))
- {
- err_name = (char *)alloca (1024);
- sprintf (err_name, "`operator %s'", operator_name_string (fn_name));
- }
- else
- {
- err_name = IDENTIFIER_POINTER (fn_name);
- need_quotes = 1;
- }
-
- if (methods != end)
- if (need_quotes)
- error ("argument list for `%s' does not match any in class `%s'",
- err_name, IDENTIFIER_POINTER (cname));
- else
- error ("argument list for %s does not match any in class `%s'",
- err_name, IDENTIFIER_POINTER (cname));
- else
- {
- methods = 0;
- if (need_quotes)
- error ("no `%s' member function declared in class `%s'",
- err_name, IDENTIFIER_POINTER (cname));
- else
- error ("no %s declared in class `%s'",
- err_name, IDENTIFIER_POINTER (cname));
- }
-
- /* If we did not find the method in the class, add it to
- avoid spurious errors. */
- add_method (ctype, methods, function);
-}
-
-/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
- of a structure component, returning a FIELD_DECL node.
- QUALS is a list of type qualifiers for this decl (such as for declaring
- const member functions).
-
- This is done during the parsing of the struct declaration.
- The FIELD_DECL nodes are chained together and the lot of them
- are ultimately passed to `build_struct' to make the RECORD_TYPE node.
-
- C++:
-
- If class A defines that certain functions in class B are friends, then
- the way I have set things up, it is B who is interested in permission
- granted by A. However, it is in A's context that these declarations
- are parsed. By returning a void_type_node, class A does not attempt
- to incorporate the declarations of the friends within its structure.
-
- DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
- CHANGES TO CODE IN `start_method'. */
-
-tree
-grokfield (declarator, declspecs, raises, init, asmspec_tree)
- tree declarator, declspecs, raises, init, asmspec_tree;
-{
- register tree value;
- char *asmspec = 0;
-
- /* Convert () initializers to = initializers. */
- if (init == NULL_TREE && declarator != NULL_TREE
- && TREE_CODE (declarator) == CALL_EXPR
- && TREE_OPERAND (declarator, 0)
- && (TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE
- || TREE_CODE (TREE_OPERAND (declarator, 0)) == SCOPE_REF)
- && parmlist_is_exprlist (TREE_OPERAND (declarator, 1)))
- {
- init = TREE_OPERAND (declarator, 1);
- declarator = TREE_OPERAND (declarator, 0);
- }
-
- if (init
- && TREE_CODE (init) == TREE_LIST
- && TREE_VALUE (init) == error_mark_node
- && TREE_CHAIN (init) == NULL_TREE)
- init = NULL_TREE;
-
- value = grokdeclarator (declarator, declspecs, FIELD, init != 0, raises);
- if (! value)
- return NULL_TREE; /* friends went bad. */
-
- /* Pass friendly classes back. */
- if (TREE_CODE (value) == VOID_TYPE)
- return void_type_node;
-
- if (DECL_NAME (value) != NULL_TREE
- && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr"))
- error_with_decl (value, "member `%s' conflicts with virtual function table field name");
-
- /* Stash away type declarations. */
- if (TREE_CODE (value) == TYPE_DECL)
- {
- DECL_NONLOCAL (value) = 1;
- CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
- set_identifier_type_value (DECL_NAME (value), TREE_TYPE (value));
- pushdecl_class_level (value);
- return value;
- }
-
- if (DECL_IN_AGGR_P (value))
- {
- error_with_decl (value, "`%s' is already defined in the class %s",
- TYPE_NAME_STRING (DECL_CONTEXT (value)));
- return void_type_node;
- }
-
- if (flag_cadillac)
- cadillac_start_decl (value);
-
- if (asmspec_tree)
- asmspec = TREE_STRING_POINTER (asmspec_tree);
-
- if (init != 0)
- {
- if (TREE_CODE (value) == FUNCTION_DECL)
- {
- grok_function_init (value, init);
- init = NULL_TREE;
- }
- else if (pedantic)
- {
- error ("fields cannot have initializers");
- init = NULL_TREE;
- }
- else
- {
- /* We allow initializers to become parameters to base initializers. */
- if (TREE_CODE (init) == TREE_LIST)
- {
- if (TREE_CHAIN (init) == NULL_TREE)
- init = TREE_VALUE (init);
- else
- init = digest_init (TREE_TYPE (value), init, (tree *)0);
- }
-
- if (TREE_CODE (init) == CONST_DECL)
- init = DECL_INITIAL (init);
- else if (TREE_READONLY_DECL_P (init))
- init = decl_constant_value (init);
- else if (TREE_CODE (init) == CONSTRUCTOR)
- init = digest_init (TREE_TYPE (value), init, (tree *)0);
- my_friendly_assert (TREE_PERMANENT (init), 192);
- if (init == error_mark_node)
- /* We must make this look different than `error_mark_node'
- because `decl_const_value' would mis-interpret it
- as only meaning that this VAR_DECL is defined. */
- init = build1 (NOP_EXPR, TREE_TYPE (value), init);
- else if (! TREE_CONSTANT (init))
- {
- /* We can allow references to things that are effectively
- static, since references are initialized with the address. */
- if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE
- || (TREE_STATIC (init) == 0
- && (TREE_CODE_CLASS (TREE_CODE (init)) != 'd'
- || DECL_EXTERNAL (init) == 0)))
- {
- error ("field initializer is not constant");
- init = error_mark_node;
- }
- }
- }
- }
-
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
-
- if (TREE_CODE (value) == VAR_DECL)
- {
- /* We cannot call pushdecl here, because that would
- fill in the value of our TREE_CHAIN. Instead, we
- modify finish_decl to do the right thing, namely, to
- put this decl out straight away. */
- if (TREE_STATIC (value))
- {
- /* current_class_type can be NULL_TREE in case of error. */
- if (asmspec == 0 && current_class_type)
- {
- tree name;
- char *buf, *buf2;
-
- buf2 = build_overload_name (current_class_type, 1, 1);
- buf = (char *)alloca (IDENTIFIER_LENGTH (DECL_NAME (value))
- + sizeof (STATIC_NAME_FORMAT)
- + strlen (buf2));
- sprintf (buf, STATIC_NAME_FORMAT, buf2,
- IDENTIFIER_POINTER (DECL_NAME (value)));
- name = get_identifier (buf);
- TREE_PUBLIC (value) = 1;
- DECL_INITIAL (value) = error_mark_node;
- DECL_ASSEMBLER_NAME (value) = name;
- }
- pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
-
- /* Static consts need not be initialized in the class definition. */
- if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value)))
- {
- static int explanation = 0;
-
- error ("initializer invalid for static member with constructor");
- if (explanation++ == 0)
- error ("(you really want to initialize it separately)");
- init = 0;
- }
- /* Force the compiler to know when an uninitialized static
- const member is being used. */
- if (TYPE_READONLY (value) && init == 0)
- TREE_USED (value) = 1;
- }
- DECL_INITIAL (value) = init;
- DECL_IN_AGGR_P (value) = 1;
-
- finish_decl (value, init, asmspec_tree, 1);
- pushdecl_class_level (value);
- return value;
- }
- if (TREE_CODE (value) == FIELD_DECL)
- {
- if (asmspec)
- DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec);
- if (DECL_INITIAL (value) == error_mark_node)
- init = error_mark_node;
- finish_decl (value, init, asmspec_tree, 1);
- DECL_INITIAL (value) = init;
- DECL_IN_AGGR_P (value) = 1;
- return value;
- }
- if (TREE_CODE (value) == FUNCTION_DECL)
- {
- /* grokdeclarator defers setting this. */
- TREE_PUBLIC (value) = 1;
- if (DECL_CHAIN (value) != NULL_TREE)
- {
- /* Need a fresh node here so that we don't get circularity
- when we link these together. */
- value = copy_node (value);
- /* When does this happen? */
- my_friendly_assert (init == NULL_TREE, 193);
- }
- finish_decl (value, init, asmspec_tree, 1);
-
- /* Pass friends back this way. */
- if (DECL_FRIEND_P (value))
- return void_type_node;
-
- DECL_IN_AGGR_P (value) = 1;
- return value;
- }
- my_friendly_abort (21);
- /* NOTREACHED */
- return NULL_TREE;
-}
-
-/* Like `grokfield', but for bitfields.
- WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */
-
-tree
-grokbitfield (declarator, declspecs, width)
- tree declarator, declspecs, width;
-{
- register tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL_TREE);
-
- if (! value) return NULL_TREE; /* friends went bad. */
-
- /* Pass friendly classes back. */
- if (TREE_CODE (value) == VOID_TYPE)
- return void_type_node;
-
- if (TREE_CODE (value) == TYPE_DECL)
- {
- error_with_decl (value, "cannot declare `%s' to be a bitfield type");
- return NULL_TREE;
- }
-
- if (DECL_IN_AGGR_P (value))
- {
- error_with_decl (value, "`%s' is already defined in the class %s",
- TYPE_NAME_STRING (DECL_CONTEXT (value)));
- return void_type_node;
- }
-
- GNU_xref_member (current_class_name, value);
-
- if (TREE_STATIC (value))
- {
- error_with_decl (value, "static member `%s' cannot be a bitfield");
- return NULL_TREE;
- }
- finish_decl (value, NULL_TREE, NULL_TREE, 0);
-
- if (width != error_mark_node)
- {
- /* detect invalid field size. */
- if (TREE_CODE (width) == CONST_DECL)
- width = DECL_INITIAL (width);
- else if (TREE_READONLY_DECL_P (width))
- width = decl_constant_value (width);
- if (TREE_CODE (width) != INTEGER_CST)
- {
- error_with_decl (value, "structure field `%s' width not an integer constant");
- DECL_INITIAL (value) = NULL_TREE;
- }
- else
- {
- DECL_INITIAL (value) = width;
- DECL_BIT_FIELD (value) = 1;
- }
- }
-
- DECL_IN_AGGR_P (value) = 1;
- return value;
-}
-
-/* Like GROKFIELD, except that the declarator has been
- buried in DECLSPECS. Find the declarator, and
- return something that looks like it came from
- GROKFIELD. */
-tree
-groktypefield (declspecs, parmlist)
- tree declspecs;
- tree parmlist;
-{
- tree spec = declspecs;
- tree prev = NULL_TREE;
-
- tree type_id = NULL_TREE;
- tree quals = NULL_TREE;
- tree lengths = NULL_TREE;
- tree decl = NULL_TREE;
-
- while (spec)
- {
- register tree id = TREE_VALUE (spec);
-
- if (TREE_CODE (spec) != TREE_LIST)
- /* Certain parse errors slip through. For example,
- `int class ();' is not caught by the parser. Try
- weakly to recover here. */
- return NULL_TREE;
-
- if (TREE_CODE (id) == TYPE_DECL
- || (TREE_CODE (id) == IDENTIFIER_NODE && TREE_TYPE (id)))
- {
- /* We have a constructor/destructor or
- conversion operator. Use it. */
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (spec);
- else
- declspecs = TREE_CHAIN (spec);
-
- type_id = id;
- goto found;
- }
- prev = spec;
- spec = TREE_CHAIN (spec);
- }
-
- /* Nope, we have a conversion operator to a scalar type or something
- else, that includes things like constructor declarations for
- templates. */
- spec = declspecs;
- while (spec)
- {
- tree id = TREE_VALUE (spec);
-
- if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- if (id == ridpointers[(int)RID_INT]
- || id == ridpointers[(int)RID_DOUBLE]
- || id == ridpointers[(int)RID_FLOAT]
- || id == ridpointers[(int)RID_WCHAR])
- {
- if (type_id)
- error ("extra `%s' ignored",
- IDENTIFIER_POINTER (id));
- else
- type_id = id;
- }
- else if (id == ridpointers[(int)RID_LONG]
- || id == ridpointers[(int)RID_SHORT]
- || id == ridpointers[(int)RID_CHAR])
- {
- lengths = tree_cons (NULL_TREE, id, lengths);
- }
- else if (id == ridpointers[(int)RID_VOID])
- {
- if (type_id)
- error ("spurious `void' type ignored");
- else
- error ("conversion to `void' type invalid");
- }
- else if (id == ridpointers[(int)RID_AUTO]
- || id == ridpointers[(int)RID_REGISTER]
- || id == ridpointers[(int)RID_TYPEDEF]
- || id == ridpointers[(int)RID_CONST]
- || id == ridpointers[(int)RID_VOLATILE])
- {
- error ("type specifier `%s' used invalidly",
- IDENTIFIER_POINTER (id));
- }
- else if (id == ridpointers[(int)RID_FRIEND]
- || id == ridpointers[(int)RID_VIRTUAL]
- || id == ridpointers[(int)RID_INLINE]
- || id == ridpointers[(int)RID_UNSIGNED]
- || id == ridpointers[(int)RID_SIGNED]
- || id == ridpointers[(int)RID_STATIC]
- || id == ridpointers[(int)RID_EXTERN])
- {
- quals = tree_cons (NULL_TREE, id, quals);
- }
- else
- {
- /* Happens when we have a global typedef
- and a class-local member function with
- the same name. */
- type_id = id;
- goto found;
- }
- }
- else if (TREE_CODE (id) == RECORD_TYPE)
- {
- type_id = TYPE_NAME (id);
- if (TREE_CODE (type_id) == TYPE_DECL)
- type_id = DECL_NAME (type_id);
- if (type_id == NULL_TREE)
- error ("identifier for aggregate type conversion omitted");
- }
- else if (TREE_CODE_CLASS (TREE_CODE (id)) == 't')
- error ("`operator' missing on conversion operator or tag missing from type");
- else
- my_friendly_abort (194);
- spec = TREE_CHAIN (spec);
- }
-
- if (type_id)
- declspecs = chainon (lengths, quals);
- else if (lengths)
- {
- if (TREE_CHAIN (lengths))
- error ("multiple length specifiers");
- type_id = ridpointers[(int)RID_INT];
- declspecs = chainon (lengths, quals);
- }
- else if (quals)
- {
- error ("no type given, defaulting to `operator int ...'");
- type_id = ridpointers[(int)RID_INT];
- declspecs = quals;
- }
- else
- return NULL_TREE;
-
- found:
- decl = grokdeclarator (build_parse_node (CALL_EXPR, type_id, parmlist, NULL_TREE),
- declspecs, FIELD, 0, NULL_TREE);
- if (decl == NULL_TREE)
- return NULL_TREE;
-
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CHAIN (decl) != NULL_TREE)
- {
- /* Need a fresh node here so that we don't get circularity
- when we link these together. */
- decl = copy_node (decl);
- }
-
- if (decl == void_type_node
- || (TREE_CODE (decl) == FUNCTION_DECL
- && TREE_CODE (TREE_TYPE (decl)) != METHOD_TYPE))
- /* bunch of friends. */
- return decl;
-
- if (DECL_IN_AGGR_P (decl))
- {
- error_with_decl (decl, "`%s' already defined in the class ");
- return void_type_node;
- }
-
- finish_decl (decl, NULL_TREE, NULL_TREE, 0);
-
- /* If this declaration is common to another declaration
- complain about such redundancy, and return NULL_TREE
- so that we don't build a circular list. */
- if (DECL_CHAIN (decl))
- {
- error_with_decl (decl, "function `%s' declared twice in class %s",
- TYPE_NAME_STRING (DECL_CONTEXT (decl)));
- return NULL_TREE;
- }
- DECL_IN_AGGR_P (decl) = 1;
- return decl;
-}
-
-/* The precedence rules of this grammar (or any other deterministic LALR
- grammar, for that matter), place the CALL_EXPR somewhere where we
- may not want it. The solution is to grab the first CALL_EXPR we see,
- pretend that that is the one that belongs to the parameter list of
- the type conversion function, and leave everything else alone.
- We pull it out in place.
-
- CALL_REQUIRED is non-zero if we should complain if a CALL_EXPR
- does not appear in DECL. */
-tree
-grokoptypename (decl, call_required)
- tree decl;
- int call_required;
-{
- tree tmp, last;
-
- my_friendly_assert (TREE_CODE (decl) == TYPE_EXPR, 195);
-
- tmp = TREE_OPERAND (decl, 0);
- last = NULL_TREE;
-
- while (tmp)
- {
- switch (TREE_CODE (tmp))
- {
- case CALL_EXPR:
- {
- tree parms = TREE_OPERAND (tmp, 1);
-
- if (last)
- TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0);
- else
- TREE_OPERAND (decl, 0) = TREE_OPERAND (tmp, 0);
- if (parms
- && TREE_CODE (TREE_VALUE (parms)) == TREE_LIST)
- TREE_VALUE (parms)
- = grokdeclarator (TREE_VALUE (TREE_VALUE (parms)),
- TREE_PURPOSE (TREE_VALUE (parms)),
- TYPENAME, 0, NULL_TREE);
- if (parms)
- {
- if (TREE_VALUE (parms) != void_type_node)
- error ("operator <typename> requires empty parameter list");
- else
- /* Canonicalize parameter lists. */
- TREE_OPERAND (tmp, 1) = void_list_node;
- }
-
- last = grokdeclarator (TREE_OPERAND (decl, 0),
- TREE_TYPE (decl),
- TYPENAME, 0, NULL_TREE);
- TREE_OPERAND (tmp, 0) = build_typename_overload (last);
- TREE_TYPE (TREE_OPERAND (tmp, 0)) = last;
- return tmp;
- }
-
- case INDIRECT_REF:
- case ADDR_EXPR:
- case ARRAY_REF:
- break;
-
- case SCOPE_REF:
- /* This is legal when declaring a conversion to
- something of type pointer-to-member. */
- if (TREE_CODE (TREE_OPERAND (tmp, 1)) == INDIRECT_REF)
- {
- tmp = TREE_OPERAND (tmp, 1);
- }
- else
- {
-#if 0
- /* We may need to do this if grokdeclarator cannot handle this. */
- error ("type `member of class %s' invalid return type",
- TYPE_NAME_STRING (TREE_OPERAND (tmp, 0)));
- TREE_OPERAND (tmp, 1) = build_parse_node (INDIRECT_REF, TREE_OPERAND (tmp, 1));
-#endif
- tmp = TREE_OPERAND (tmp, 1);
- }
- break;
-
- default:
- my_friendly_abort (196);
- }
- last = tmp;
- tmp = TREE_OPERAND (tmp, 0);
- }
-
- if (call_required)
- error ("operator <typename> construct requires parameter list");
-
- last = grokdeclarator (TREE_OPERAND (decl, 0),
- TREE_TYPE (decl),
- TYPENAME, 0, NULL_TREE);
- tmp = build_parse_node (CALL_EXPR, build_typename_overload (last),
- void_list_node, NULL_TREE);
- TREE_TYPE (TREE_OPERAND (tmp, 0)) = last;
- return tmp;
-}
-
-/* When a function is declared with an initializer,
- do the right thing. Currently, there are two possibilities:
-
- class B
- {
- public:
- // initialization possibility #1.
- virtual void f () = 0;
- int g ();
- };
-
- class D1 : B
- {
- public:
- int d1;
- // error, no f ();
- };
-
- class D2 : B
- {
- public:
- int d2;
- void f ();
- };
-
- class D3 : B
- {
- public:
- int d3;
- // initialization possibility #2
- void f () = B::f;
- };
-
-*/
-
-static void
-grok_function_init (decl, init)
- tree decl;
- tree init;
-{
- /* An initializer for a function tells how this function should
- be inherited. */
- tree type = TREE_TYPE (decl);
- extern tree abort_fndecl;
-
- if (TREE_CODE (type) == FUNCTION_TYPE)
- error_with_decl (decl, "initializer specified for non-member function `%s'");
- else if (DECL_VINDEX (decl) == NULL_TREE)
- error_with_decl (decl, "initializer specified for non-virtual method `%s'");
- else if (integer_zerop (init))
- {
- /* Mark this function as being "defined". */
- DECL_INITIAL (decl) = error_mark_node;
- /* pure virtual destructors must be defined. */
- if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))
- {
- /* Give this node rtl from `abort'. */
- DECL_RTL (decl) = DECL_RTL (abort_fndecl);
- }
- DECL_ABSTRACT_VIRTUAL_P (decl) = 1;
- }
- else if (TREE_CODE (init) == OFFSET_REF
- && TREE_OPERAND (init, 0) == NULL_TREE
- && TREE_CODE (TREE_TYPE (init)) == METHOD_TYPE)
- {
- tree basetype = DECL_CLASS_CONTEXT (init);
- tree basefn = TREE_OPERAND (init, 1);
- if (TREE_CODE (basefn) != FUNCTION_DECL)
- error_with_decl (decl, "non-method initializer invalid for method `%s'");
- else if (! BINFO_OFFSET_ZEROP (TYPE_BINFO (DECL_CLASS_CONTEXT (basefn))))
- sorry ("base member function from other than first base class");
- else
- {
- tree binfo = get_binfo (basetype, TYPE_METHOD_BASETYPE (type), 1);
- if (binfo == error_mark_node)
- ;
- else if (binfo == 0)
- error_not_base_type (TYPE_METHOD_BASETYPE (TREE_TYPE (init)),
- TYPE_METHOD_BASETYPE (type));
- else
- {
- /* Mark this function as being defined,
- and give it new rtl. */
- DECL_INITIAL (decl) = error_mark_node;
- DECL_RTL (decl) = DECL_RTL (basefn);
- }
- }
- }
- else
- error_with_decl (decl, "invalid initializer for virtual method `%s'");
-}
-
-/* When we get a declaration of the form
-
- type cname::fname ...
-
- the node for `cname::fname' gets built here in a special way.
- Namely, we push into `cname's scope. When this declaration is
- processed, we pop back out. */
-tree
-build_push_scope (cname, name)
- tree cname;
- tree name;
-{
- extern int current_class_depth;
- tree ctype, rval;
-
- if (cname == error_mark_node)
- return error_mark_node;
-
- ctype = IDENTIFIER_TYPE_VALUE (cname);
-
- if (ctype == NULL_TREE || ! IS_AGGR_TYPE (ctype))
- {
- error ("`%s' not defined as aggregate type", IDENTIFIER_POINTER (cname));
- return name;
- }
-
- rval = build_parse_node (SCOPE_REF, cname, name);
-
- /* Don't need to push the scope here, but we do need to return
- a SCOPE_REF for something like
-
- class foo { typedef int bar (foo::*foo_fn)(void); }; */
- if (ctype == current_class_type)
- return rval;
-
- pushclass (ctype, 3);
- TREE_COMPLEXITY (rval) = current_class_depth;
- return rval;
-}
-
-void cplus_decl_attributes (decl, attributes)
- tree decl, attributes;
-{
- if (decl)
- decl_attributes (decl, attributes);
-}
-
-/* CONSTRUCTOR_NAME:
- Return the name for the constructor (or destructor) for the specified
- class. Argument can be RECORD_TYPE, TYPE_DECL, or IDENTIFIER_NODE. */
-tree
-constructor_name (thing)
- tree thing;
-{
- tree t;
- if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE)
- return DECL_NAME (UPT_TEMPLATE (thing));
- if (TREE_CODE (thing) == RECORD_TYPE || TREE_CODE (thing) == UNION_TYPE)
- thing = TYPE_NAME (thing);
- if (TREE_CODE (thing) == TYPE_DECL
- || (TREE_CODE (thing) == TEMPLATE_DECL
- && DECL_TEMPLATE_IS_CLASS (thing)))
- thing = DECL_NAME (thing);
- my_friendly_assert (TREE_CODE (thing) == IDENTIFIER_NODE, 197);
- t = IDENTIFIER_TEMPLATE (thing);
- if (!t)
- return thing;
- t = TREE_PURPOSE (t);
- return DECL_NAME (t);
-}
-
-/* Cache the value of this class's main virtual function table pointer
- in a register variable. This will save one indirection if a
- more than one virtual function call is made this function. */
-void
-setup_vtbl_ptr ()
-{
- extern rtx base_init_insns;
-
- if (base_init_insns == 0
- && DECL_CONSTRUCTOR_P (current_function_decl))
- emit_base_init (current_class_type, 0);
-
-#if 0
- /* This has something a little wrong with it.
-
- On a sun4, code like:
-
- be L6
- ld [%i0],%o1
-
- is generated, when the below is used when -O4 is given. The delay
- slot it filled with an instruction that is safe, when this isn't
- used, like in:
-
- be L6
- sethi %hi(LC1),%o0
- ld [%i0],%o1
-
- on code like:
-
- struct A {
- virtual void print() { printf("xxx"); }
- void f();
- };
-
- void A::f() {
- if (this) {
- print();
- } else {
- printf("0");
- }
- }
-
- And that is why this is disabled for now. (mrs)
- */
-
- if ((flag_this_is_variable & 1) == 0
- && optimize
- && current_class_type
- && CLASSTYPE_VSIZE (current_class_type)
- && ! DECL_STATIC_FUNCTION_P (current_function_decl))
- {
- tree vfield = build_vfield_ref (C_C_D, current_class_type);
- current_vtable_decl = CLASSTYPE_VTBL_PTR (current_class_type);
- DECL_RTL (current_vtable_decl) = 0;
- DECL_INITIAL (current_vtable_decl) = error_mark_node;
- /* Have to cast the initializer, since it may have come from a
- more base class then we ascribe CURRENT_VTABLE_DECL to be. */
- finish_decl (current_vtable_decl, convert_force (TREE_TYPE (current_vtable_decl), vfield), 0, 0);
- current_vtable_decl = build_indirect_ref (current_vtable_decl, 0);
- }
- else
-#endif
- current_vtable_decl = NULL_TREE;
-}
-
-/* Record the existence of an addressable inline function. */
-void
-mark_inline_for_output (decl)
- tree decl;
-{
- if (DECL_PENDING_INLINE_INFO (decl) != 0
- && ! DECL_PENDING_INLINE_INFO (decl)->deja_vu)
- {
- struct pending_inline *t = pending_inlines;
- my_friendly_assert (DECL_SAVED_INSNS (decl) == 0, 198);
- while (t)
- {
- if (t == DECL_PENDING_INLINE_INFO (decl))
- break;
- t = t->next;
- }
- if (t == 0)
- {
- t = DECL_PENDING_INLINE_INFO (decl);
- t->next = pending_inlines;
- pending_inlines = t;
- }
- DECL_PENDING_INLINE_INFO (decl) = 0;
- }
- pending_addressable_inlines = perm_tree_cons (NULL_TREE, decl,
- pending_addressable_inlines);
-}
-
-void
-clear_temp_name ()
-{
- temp_name_counter = 0;
-}
-
-/* Hand off a unique name which can be used for variable we don't really
- want to know about anyway, for example, the anonymous variables which
- are needed to make references work. Declare this thing so we can use it.
- The variable created will be of type TYPE.
-
- STATICP is nonzero if this variable should be static. */
-
-tree
-get_temp_name (type, staticp)
- tree type;
- int staticp;
-{
- char buf[sizeof (AUTO_TEMP_FORMAT) + 20];
- tree decl;
- int toplev = global_bindings_p ();
-
- push_obstacks_nochange ();
- if (toplev || staticp)
- {
- end_temporary_allocation ();
- sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);
- decl = pushdecl_top_level (build_decl (VAR_DECL, get_identifier (buf), type));
- }
- else
- {
- sprintf (buf, AUTO_TEMP_FORMAT, temp_name_counter++);
- decl = pushdecl (build_decl (VAR_DECL, get_identifier (buf), type));
- }
- TREE_USED (decl) = 1;
- TREE_STATIC (decl) = staticp;
-
- /* If this is a local variable, then lay out its rtl now.
- Otherwise, callers of this function are responsible for dealing
- with this variable's rtl. */
- if (! toplev)
- {
- expand_decl (decl);
- expand_decl_init (decl);
- }
- pop_obstacks ();
-
- return decl;
-}
-
-/* Get a variable which we can use for multiple assignments.
- It is not entered into current_binding_level, because
- that breaks things when it comes time to do final cleanups
- (which take place "outside" the binding contour of the function). */
-tree
-get_temp_regvar (type, init)
- tree type, init;
-{
- static char buf[sizeof (AUTO_TEMP_FORMAT) + 20] = { '_' };
- tree decl;
-
- sprintf (buf+1, AUTO_TEMP_FORMAT, temp_name_counter++);
- decl = build_decl (VAR_DECL, get_identifier (buf), type);
- TREE_USED (decl) = 1;
- DECL_REGISTER (decl) = 1;
-
- if (init)
- store_init_value (decl, init);
-
- /* We can expand these without fear, since they cannot need
- constructors or destructors. */
- expand_decl (decl);
- expand_decl_init (decl);
-
- if (type_needs_gc_entry (type))
- DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index);
-
- return decl;
-}
-
-/* Make the macro TEMP_NAME_P available to units which do not
- include c-tree.h. */
-int
-temp_name_p (decl)
- tree decl;
-{
- return TEMP_NAME_P (decl);
-}
-
-/* Finish off the processing of a UNION_TYPE structure.
- If there are static members, then all members are
- static, and must be laid out together. If the
- union is an anonymous union, we arrange for that
- as well. PUBLIC_P is nonzero if this union is
- not declared static. */
-void
-finish_anon_union (anon_union_decl)
- tree anon_union_decl;
-{
- tree type = TREE_TYPE (anon_union_decl);
- tree field, main_decl = NULL_TREE;
- tree elems = NULL_TREE;
- int public_p = TREE_PUBLIC (anon_union_decl);
- int static_p = TREE_STATIC (anon_union_decl);
- int external_p = DECL_EXTERNAL (anon_union_decl);
-
- if ((field = TYPE_FIELDS (type)) == NULL_TREE)
- return;
-
- if (public_p && (static_p || external_p))
- error ("optimizer cannot handle global anonymous unions");
-
- while (field)
- {
- tree decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
- /* tell `pushdecl' that this is not tentative. */
- DECL_INITIAL (decl) = error_mark_node;
- TREE_PUBLIC (decl) = public_p;
- TREE_STATIC (decl) = static_p;
- DECL_EXTERNAL (decl) = external_p;
- decl = pushdecl (decl);
-
- /* Only write out one anon union element--choose the one that
- can hold them all. */
- if (main_decl == NULL_TREE
- && DECL_SIZE (decl) == DECL_SIZE (anon_union_decl))
- {
- main_decl = decl;
- }
- else
- {
- /* ??? This causes there to be no debug info written out
- about this decl. */
- TREE_ASM_WRITTEN (decl) = 1;
- }
-
- DECL_INITIAL (decl) = NULL_TREE;
- /* If there's a cleanup to do, it belongs in the
- TREE_PURPOSE of the following TREE_LIST. */
- elems = tree_cons (NULL_TREE, decl, elems);
- TREE_TYPE (elems) = type;
- field = TREE_CHAIN (field);
- }
- if (static_p)
- {
- make_decl_rtl (main_decl, 0, global_bindings_p ());
- DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
- }
-
- /* The following call assumes that there are never any cleanups
- for anonymous unions--a reasonable assumption. */
- expand_anon_union_decl (anon_union_decl, NULL_TREE, elems);
-
- if (flag_cadillac)
- cadillac_finish_anon_union (anon_union_decl);
-}
-
-/* Finish and output a table which is generated by the compiler.
- NAME is the name to give the table.
- TYPE is the type of the table entry.
- INIT is all the elements in the table.
- PUBLICP is non-zero if this table should be given external visibility. */
-tree
-finish_table (name, type, init, publicp)
- tree name, type, init;
- int publicp;
-{
- tree itype, atype, decl;
- static tree empty_table;
- int is_empty = 0;
- tree asmspec;
-
- itype = build_index_type (size_int (list_length (init) - 1));
- atype = build_cplus_array_type (type, itype);
- layout_type (atype);
-
- if (TREE_VALUE (init) == integer_zero_node
- && TREE_CHAIN (init) == NULL_TREE)
- {
- if (empty_table == NULL_TREE)
- {
- empty_table = get_temp_name (atype, 1);
- init = build (CONSTRUCTOR, atype, NULL_TREE, init);
- TREE_CONSTANT (init) = 1;
- TREE_STATIC (init) = 1;
- DECL_INITIAL (empty_table) = init;
- asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)),
- IDENTIFIER_POINTER (DECL_NAME (empty_table)));
- finish_decl (empty_table, init, asmspec, 0);
- }
- is_empty = 1;
- }
-
- if (name == NULL_TREE)
- {
- if (is_empty)
- return empty_table;
- decl = get_temp_name (atype, 1);
- }
- else
- {
- decl = build_decl (VAR_DECL, name, atype);
- decl = pushdecl (decl);
- TREE_STATIC (decl) = 1;
- }
-
- if (is_empty == 0)
- {
- TREE_PUBLIC (decl) = publicp;
- init = build (CONSTRUCTOR, atype, NULL_TREE, init);
- TREE_CONSTANT (init) = 1;
- TREE_STATIC (init) = 1;
- DECL_INITIAL (decl) = init;
- asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (decl)),
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- }
- else
- {
- /* This will cause DECL to point to EMPTY_TABLE in rtl-land. */
- DECL_EXTERNAL (decl) = 1;
- TREE_STATIC (decl) = 0;
- init = 0;
- asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)),
- IDENTIFIER_POINTER (DECL_NAME (empty_table)));
- }
-
- finish_decl (decl, init, asmspec, 0);
- return decl;
-}
-
-/* Finish processing a builtin type TYPE. It's name is NAME,
- its fields are in the array FIELDS. LEN is the number of elements
- in FIELDS.
-
- It is given the same alignment as ALIGN_TYPE. */
-void
-finish_builtin_type (type, name, fields, len, align_type)
- tree type;
- char *name;
- tree fields[];
- int len;
- tree align_type;
-{
- register int i;
-
- TYPE_FIELDS (type) = fields[0];
- for (i = 0; i < len; i++)
- {
- layout_type (TREE_TYPE (fields[i]));
- DECL_FIELD_CONTEXT (fields[i]) = type;
- TREE_CHAIN (fields[i]) = fields[i+1];
- }
- DECL_FIELD_CONTEXT (fields[i]) = type;
- DECL_CLASS_CONTEXT (fields[i]) = type;
- TYPE_ALIGN (type) = TYPE_ALIGN (align_type);
- layout_type (type);
-#if 0 /* not yet, should get fixed properly later */
- TYPE_NAME (type) = make_type_decl (get_identifier (name), type);
-#else
- TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type);
-#endif
- layout_decl (TYPE_NAME (type), 0);
-}
-
-/* Auxiliary functions to make type signatures for
- `operator new' and `operator delete' correspond to
- what compiler will be expecting. */
-
-extern tree sizetype;
-
-tree
-coerce_new_type (type)
- tree type;
-{
- int e1 = 0, e2 = 0;
-
- if (TREE_CODE (type) == METHOD_TYPE)
- type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type)));
- if (TREE_TYPE (type) != ptr_type_node)
- e1 = 1, error ("`operator new' must return type `void *'");
-
- /* Technically the type must be `size_t', but we may not know
- what that is. */
- if (TYPE_ARG_TYPES (type) == NULL_TREE)
- e1 = 1, error ("`operator new' takes type `size_t' parameter");
- else if (TREE_CODE (TREE_VALUE (TYPE_ARG_TYPES (type))) != INTEGER_TYPE
- || TYPE_PRECISION (TREE_VALUE (TYPE_ARG_TYPES (type))) != TYPE_PRECISION (sizetype))
- e2 = 1, error ("`operator new' takes type `size_t' as first parameter");
- if (e2)
- type = build_function_type (ptr_type_node, tree_cons (NULL_TREE, sizetype, TREE_CHAIN (TYPE_ARG_TYPES (type))));
- else if (e1)
- type = build_function_type (ptr_type_node, TYPE_ARG_TYPES (type));
- return type;
-}
-
-tree
-coerce_delete_type (type)
- tree type;
-{
- int e1 = 0, e2 = 0, e3 = 0;
- tree arg_types = TYPE_ARG_TYPES (type);
-
- if (TREE_CODE (type) == METHOD_TYPE)
- {
- type = build_function_type (TREE_TYPE (type), TREE_CHAIN (arg_types));
- arg_types = TREE_CHAIN (arg_types);
- }
- if (TREE_TYPE (type) != void_type_node)
- e1 = 1, error ("`operator delete' must return type `void'");
- if (arg_types == NULL_TREE
- || TREE_VALUE (arg_types) != ptr_type_node)
- e2 = 1, error ("`operator delete' takes type `void *' as first parameter");
-
- if (arg_types
- && TREE_CHAIN (arg_types)
- && TREE_CHAIN (arg_types) != void_list_node)
- {
- /* Again, technically this argument must be `size_t', but again
- we may not know what that is. */
- tree t2 = TREE_VALUE (TREE_CHAIN (arg_types));
- if (TREE_CODE (t2) != INTEGER_TYPE
- || TYPE_PRECISION (t2) != TYPE_PRECISION (sizetype))
- e3 = 1, error ("second argument to `operator delete' must be of type `size_t'");
- else if (TREE_CHAIN (TREE_CHAIN (arg_types)) != void_list_node)
- {
- e3 = 1;
- if (TREE_CHAIN (TREE_CHAIN (arg_types)))
- error ("too many arguments in declaration of `operator delete'");
- else
- error ("`...' invalid in specification of `operator delete'");
- }
- }
- if (e3)
- arg_types = tree_cons (NULL_TREE, ptr_type_node, build_tree_list (NULL_TREE, sizetype));
- else if (e3 |= e2)
- {
- if (arg_types == NULL_TREE)
- arg_types = void_list_node;
- else
- arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types));
- }
- else e3 |= e1;
-
- if (e3)
- type = build_function_type (void_type_node, arg_types);
-
- return type;
-}
-
-static void
-write_vtable_entries (decl)
- tree decl;
-{
- tree entries = TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)));
-
- if (flag_dossier)
- entries = TREE_CHAIN (entries);
-
- for (; entries; entries = TREE_CHAIN (entries))
- {
- tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries));
- tree fn = TREE_OPERAND (fnaddr, 0);
- if (! DECL_EXTERNAL (fn) && ! TREE_ASM_WRITTEN (fn)
- && DECL_SAVED_INSNS (fn))
- {
- if (TREE_PUBLIC (DECL_CLASS_CONTEXT (fn)))
- TREE_PUBLIC (fn) = 1;
- TREE_ADDRESSABLE (fn) = 1;
- output_inline_function (fn);
- }
- else
- assemble_external (fn);
- }
-}
-
-/* Note even though prev is never used in here, walk_vtables
- expects this to have two arguments, so concede. */
-static void
-finish_vtable_typedecl (prev, vars)
- tree prev, vars;
-{
- tree decl = TYPE_BINFO_VTABLE (TREE_TYPE (vars));
-
- /* If we are controlled by `+e2', obey. */
- if (write_virtuals == 2)
- {
- tree binfo = value_member (DECL_NAME (vars), pending_vtables);
- if (binfo)
- TREE_PURPOSE (binfo) = void_type_node;
- else
- decl = NULL_TREE;
- }
- /* If this type has inline virtual functions, then
- write those functions out now. */
- if (decl && write_virtuals >= 0
- && ! DECL_EXTERNAL (decl) && (TREE_PUBLIC (decl) || TREE_USED (decl)))
- write_vtable_entries (decl);
-}
-
-static void
-finish_vtable_vardecl (prev, vars)
- tree prev, vars;
-{
- if (write_virtuals >= 0
- && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
- {
- extern tree the_null_vtable_entry;
-
- /* Stuff this virtual function table's size into
- `pfn' slot of `the_null_vtable_entry'. */
- tree nelts = array_type_nelts (TREE_TYPE (vars));
- SET_FNADDR_FROM_VTABLE_ENTRY (the_null_vtable_entry, nelts);
- /* Kick out the dossier before writing out the vtable. */
- if (flag_dossier)
- rest_of_decl_compilation (TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))))), 0), 0, 1, 1);
-
- /* Write it out. */
- write_vtable_entries (vars);
- if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
- store_init_value (vars, DECL_INITIAL (vars));
- rest_of_decl_compilation (vars, 0, 1, 1);
- }
- /* We know that PREV must be non-zero here. */
- TREE_CHAIN (prev) = TREE_CHAIN (vars);
-}
-
-void
-walk_vtables (typedecl_fn, vardecl_fn)
- register void (*typedecl_fn)();
- register void (*vardecl_fn)();
-{
- tree prev, vars;
-
- for (prev = 0, vars = getdecls (); vars; vars = TREE_CHAIN (vars))
- {
- if (TREE_CODE (vars) == TYPE_DECL
- && TYPE_LANG_SPECIFIC (TREE_TYPE (vars))
- && CLASSTYPE_VSIZE (TREE_TYPE (vars)))
- {
- if (typedecl_fn) (*typedecl_fn) (prev, vars);
- }
- else if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars))
- {
- if (vardecl_fn) (*vardecl_fn) (prev, vars);
- }
- else
- prev = vars;
- }
-}
-
-extern int parse_time, varconst_time;
-
-#define TIMEVAR(VAR, BODY) \
-do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
-
-/* This routine is called from the last rule in yyparse ().
- Its job is to create all the code needed to initialize and
- destroy the global aggregates. We do the destruction
- first, since that way we only need to reverse the decls once. */
-
-void
-finish_file ()
-{
- extern int lineno;
- int start_time, this_time;
-
- char *buf;
- char *p;
- tree fnname;
- tree vars = static_aggregates;
- int needs_cleaning = 0, needs_messing_up = 0;
-
- if (main_input_filename == 0)
- main_input_filename = input_filename;
- if (!first_global_object_name)
- first_global_object_name = main_input_filename;
-
- buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT)
- + strlen (first_global_object_name));
-
- if (flag_detailed_statistics)
- dump_tree_statistics ();
-
- /* Bad parse errors. Just forget about it. */
- if (! global_bindings_p () || current_class_type)
- return;
-
- start_time = get_run_time ();
-
- /* Push into C language context, because that's all
- we'll need here. */
- push_lang_context (lang_name_c);
-
- /* Set up the name of the file-level functions we may need. */
- /* Use a global object (which is already required to be unique over
- the program) rather than the file name (which imposes extra
- constraints). -- Raeburn@MIT.EDU, 10 Jan 1990. */
- sprintf (buf, FILE_FUNCTION_FORMAT, first_global_object_name);
-
- /* Don't need to pull wierd characters out of global names. */
- if (first_global_object_name == main_input_filename)
- {
- for (p = buf+11; *p; p++)
- if (! ((*p >= '0' && *p <= '9')
-#if 0 /* we always want labels, which are valid C++ identifiers (+ `$') */
-#ifndef ASM_IDENTIFY_GCC /* this is required if `.' is invalid -- k. raeburn */
- || *p == '.'
-#endif
-#endif
-#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */
- || *p == '$'
-#endif
-#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */
- || *p == '.'
-#endif
- || (*p >= 'A' && *p <= 'Z')
- || (*p >= 'a' && *p <= 'z')))
- *p = '_';
- }
-
- /* See if we really need the hassle. */
- while (vars && needs_cleaning == 0)
- {
- tree decl = TREE_VALUE (vars);
- tree type = TREE_TYPE (decl);
- if (TYPE_NEEDS_DESTRUCTOR (type))
- {
- needs_cleaning = 1;
- needs_messing_up = 1;
- break;
- }
- else
- needs_messing_up |= TYPE_NEEDS_CONSTRUCTING (type);
- vars = TREE_CHAIN (vars);
- }
- if (needs_cleaning == 0)
- goto mess_up;
-
- /* Otherwise, GDB can get confused, because in only knows
- about source for LINENO-1 lines. */
- lineno -= 1;
-
- fnname = get_identifier (buf);
- start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0);
- fnname = DECL_ASSEMBLER_NAME (current_function_decl);
- store_parm_decls ();
-
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
-
- /* These must be done in backward order to destroy,
- in which they happen to be! */
- while (vars)
- {
- tree decl = TREE_VALUE (vars);
- tree type = TREE_TYPE (decl);
- tree temp = TREE_PURPOSE (vars);
-
- if (TYPE_NEEDS_DESTRUCTOR (type))
- {
- if (TREE_STATIC (vars))
- expand_start_cond (build_binary_op (NE_EXPR, temp, integer_zero_node, 1), 0);
- if (TREE_CODE (type) == ARRAY_TYPE)
- temp = decl;
- else
- {
- mark_addressable (decl);
- temp = build1 (ADDR_EXPR, TYPE_POINTER_TO (type), decl);
- }
- temp = build_delete (TREE_TYPE (temp), temp,
- integer_two_node, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0, 0);
- expand_expr_stmt (temp);
-
- if (TREE_STATIC (vars))
- expand_end_cond ();
- }
- vars = TREE_CHAIN (vars);
- }
-
- expand_end_bindings (getdecls (), 1, 0);
- poplevel (1, 0, 0);
- pop_momentary ();
-
- finish_function (lineno, 0);
-
- assemble_destructor (IDENTIFIER_POINTER (fnname));
-
- /* if it needed cleaning, then it will need messing up: drop through */
-
- mess_up:
- /* Must do this while we think we are at the top level. */
- vars = nreverse (static_aggregates);
- if (vars != NULL_TREE)
- {
- buf[FILE_FUNCTION_PREFIX_LEN] = 'I';
-
- fnname = get_identifier (buf);
- start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0);
- fnname = DECL_ASSEMBLER_NAME (current_function_decl);
- store_parm_decls ();
-
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
-
- while (vars)
- {
- tree decl = TREE_VALUE (vars);
- tree init = TREE_PURPOSE (vars);
-
- /* If this was a static attribute within some function's scope,
- then don't initialize it here. Also, don't bother
- with initializers that contain errors. */
- if (TREE_STATIC (vars)
- || (init && TREE_CODE (init) == TREE_LIST
- && value_member (error_mark_node, init)))
- {
- vars = TREE_CHAIN (vars);
- continue;
- }
-
- if (TREE_CODE (decl) == VAR_DECL)
- {
- /* Set these global variables so that GDB at least puts
- us near the declaration which required the initialization. */
- input_filename = DECL_SOURCE_FILE (decl);
- lineno = DECL_SOURCE_LINE (decl);
- emit_note (input_filename, lineno);
-
- if (init)
- {
- if (TREE_CODE (init) == VAR_DECL)
- {
- /* This behavior results when there are
- multiple declarations of an aggregate,
- the last of which defines it. */
- if (DECL_RTL (init) == DECL_RTL (decl))
- {
- my_friendly_assert (DECL_INITIAL (decl) == error_mark_node
- || (TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
- && CONSTRUCTOR_ELTS (DECL_INITIAL (decl)) == NULL_TREE),
- 199);
- init = DECL_INITIAL (init);
- if (TREE_CODE (init) == CONSTRUCTOR
- && CONSTRUCTOR_ELTS (init) == NULL_TREE)
- init = NULL_TREE;
- }
-#if 0
- else if (TREE_TYPE (decl) == TREE_TYPE (init))
- {
-#if 1
- my_friendly_abort (200);
-#else
- /* point to real decl's rtl anyway. */
- DECL_RTL (init) = DECL_RTL (decl);
- my_friendly_assert (DECL_INITIAL (decl) == error_mark_node,
- 201);
- init = DECL_INITIAL (init);
-#endif /* 1 */
- }
-#endif /* 0 */
- }
- }
- if (IS_AGGR_TYPE (TREE_TYPE (decl))
- || init == 0
- || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- {
- /* Set this up so is_friend() works properly on _GLOBAL_ fns. */
- tree old_dcc = DECL_CLASS_CONTEXT (current_function_decl);
- if (old_dcc == NULL_TREE)
- DECL_CLASS_CONTEXT (current_function_decl) = TREE_TYPE (decl);
- expand_aggr_init (decl, init, 0);
- DECL_CLASS_CONTEXT (current_function_decl) = old_dcc;
- }
- else if (TREE_CODE (init) == TREE_VEC)
- {
- expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
- TREE_VEC_ELT (init, 1),
- TREE_VEC_ELT (init, 2), 0),
- const0_rtx, VOIDmode, 0);
- free_temp_slots ();
- }
- else
- expand_assignment (decl, init, 0, 0);
- }
- else if (TREE_CODE (decl) == SAVE_EXPR)
- {
- if (! PARM_DECL_EXPR (decl))
- {
- /* a `new' expression at top level. */
- expand_expr (decl, const0_rtx, VOIDmode, 0);
- free_temp_slots ();
- expand_aggr_init (build_indirect_ref (decl, 0), init, 0);
- }
- }
- else if (decl == error_mark_node)
- ;
- else my_friendly_abort (22);
- vars = TREE_CHAIN (vars);
- }
-
- expand_end_bindings (getdecls (), 1, 0);
- poplevel (1, 0, 0);
- pop_momentary ();
-
- finish_function (lineno, 0);
- assemble_constructor (IDENTIFIER_POINTER (fnname));
- }
-
- /* Done with C language context needs. */
- pop_lang_context ();
-
- /* Now write out any static class variables (which may have since
- learned how to be initialized). */
- while (pending_statics)
- {
- tree decl = TREE_VALUE (pending_statics);
- if (TREE_USED (decl) == 1
- || TREE_READONLY (decl) == 0
- || DECL_INITIAL (decl) == 0)
- rest_of_decl_compilation (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1);
- pending_statics = TREE_CHAIN (pending_statics);
- }
-
- this_time = get_run_time ();
- parse_time -= this_time - start_time;
- varconst_time += this_time - start_time;
-
- /* Now write out inline functions which had their addresses taken
- and which were not declared virtual and which were not declared
- `extern inline'. */
- while (pending_addressable_inlines)
- {
- tree decl = TREE_VALUE (pending_addressable_inlines);
- if (! TREE_ASM_WRITTEN (decl)
- && ! DECL_EXTERNAL (decl)
- && DECL_SAVED_INSNS (decl))
- output_inline_function (decl);
- pending_addressable_inlines = TREE_CHAIN (pending_addressable_inlines);
- }
-
- start_time = get_run_time ();
-
- /* Now delete from the chain of variables all virtual function tables.
- We output them all ourselves, because each will be treated specially. */
-
-#if 1
- /* The reason for pushing garbage onto the global_binding_level is to
- ensure that we can slice out _DECLs which pertain to virtual function
- tables. If the last thing pushed onto the global_binding_level was a
- virtual function table, then slicing it out would slice away all the
- decls (i.e., we lose the head of the chain).
-
- There are several ways of getting the same effect, from changing the
- way that iterators over the chain treat the elements that pertain to
- virtual function tables, moving the implementation of this code to
- cp-decl.c (where we can manipulate global_binding_level directly),
- popping the garbage after pushing it and slicing away the vtable
- stuff, or just leaving it alone. */
-
- /* Make last thing in global scope not be a virtual function table. */
-#if 0 /* not yet, should get fixed properly later */
- vars = make_type_decl (get_identifier (" @%$#@!"), integer_type_node);
-#else
- vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node);
-#endif
- DECL_IGNORED_P (vars) = 1;
- DECL_SOURCE_LINE (vars) = 0;
- pushdecl (vars);
-#endif
-
- walk_vtables (finish_vtable_typedecl, finish_vtable_vardecl);
-
- if (write_virtuals == 2)
- {
- /* Now complain about an virtual function tables promised
- but not delivered. */
- while (pending_vtables)
- {
- if (TREE_PURPOSE (pending_vtables) == NULL_TREE)
- error ("virtual function table for `%s' not defined",
- IDENTIFIER_POINTER (TREE_VALUE (pending_vtables)));
- pending_vtables = TREE_CHAIN (pending_vtables);
- }
- }
-
- permanent_allocation ();
- this_time = get_run_time ();
- parse_time -= this_time - start_time;
- varconst_time += this_time - start_time;
-
- if (flag_detailed_statistics)
- dump_time_statistics ();
-}
diff --git a/gnu/gcc2/cc1plus/cp-edsel.c b/gnu/gcc2/cc1plus/cp-edsel.c
deleted file mode 100644
index 78b2637f78d2..000000000000
--- a/gnu/gcc2/cc1plus/cp-edsel.c
+++ /dev/null
@@ -1,927 +0,0 @@
-/* Interface to LUCID Cadillac system for GNU compiler.
- Copyright (C) 1988, 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "config.h"
-
-#include "tree.h"
-#include "flags.h"
-#include <stdio.h>
-#include "cp-tree.h"
-#include "obstack.h"
-
-#ifdef CADILLAC
-#include <compilerreq.h>
-#include <compilerconn.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <sys/file.h>
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-void init_cadillac ();
-
-extern char *input_filename;
-extern int lineno;
-
-/* Put random information we might want to get back from
- Cadillac here. */
-typedef struct
-{
- /* The connection to the Cadillac kernel. */
- Connection *conn;
-
- /* Input and output file descriptors for Cadillac. */
- short fd_input, fd_output;
-
- /* #include nesting of current file. */
- short depth;
-
- /* State variables for the connection. */
- char messages;
- char conversion;
- char emission;
- char process_until;
-
- /* #if level of current file. */
- int iflevel;
-
- /* Line number that starts current source file. */
- int lineno;
-
- /* Name of current file. */
- char *filename;
-
- /* Where to stop processing (if process_until is set). */
- char *end_filename;
- int end_position;
-
-} cadillac_struct;
-static cadillac_struct cadillacObj;
-
-/* Nonzero if in the process of exiting. */
-static int exiting;
-
-void cadillac_note_source ();
-static void CWriteLanguageDecl ();
-static void CWriteLanguageType ();
-static void CWriteTopLevel ();
-static void cadillac_note_filepos ();
-static void cadillac_process_request (), cadillac_process_requests ();
-static void cadillac_switch_source ();
-static void exit_cadillac ();
-
-/* Blocking test. */
-static int
-readable_p (fd)
- int fd;
-{
- fd_set f;
-
- FD_ZERO (&f);
- FD_SET (fd, &f);
-
- return select (32, &f, NULL, NULL, 0) == 1;
-}
-
-static CObjectType *tree_to_cadillac_map;
-struct obstack cadillac_obstack;
-
-
-#include "stack.h"
-
-struct context_level
-{
- struct stack_level base;
-
- tree context;
-};
-
-/* Stack for maintaining contexts (in case functions or types are nested).
- When defining a struct type, the `context' field is the RECORD_TYPE.
- When defining a function, the `context' field is the FUNCTION_DECL. */
-
-static struct context_level *context_stack;
-
-static struct context_level *
-push_context_level (stack, obstack)
- struct stack_level *stack;
- struct obstack *obstack;
-{
- struct context_level tem;
-
- tem.base.prev = stack;
- return (struct context_level *)push_stack_level (obstack, &tem, sizeof (tem));
-}
-
-/* Discard a level of search allocation. */
-
-static struct context_level *
-pop_context_level (stack)
- struct context_level *stack;
-{
- stack = (struct context_level *)pop_stack_level (stack);
- return stack;
-}
-
-void
-init_cadillac ()
-{
- extern FILE *finput;
- extern int errno;
- CCompilerMessage* req;
- cadillac_struct *cp = &cadillacObj;
- int i;
-
- if (! flag_cadillac)
- return;
-
- tree_to_cadillac_map = (CObjectType*) xmalloc (sizeof (CObjectType) * LAST_CPLUS_TREE_CODE);
- for (i = 0; i < LAST_CPLUS_TREE_CODE; i++)
- tree_to_cadillac_map[i] = MiscOType;
- tree_to_cadillac_map[RECORD_TYPE] = StructOType;
- tree_to_cadillac_map[UNION_TYPE] = UnionOType;
- tree_to_cadillac_map[ENUMERAL_TYPE] = EnumTypeOType;
- tree_to_cadillac_map[TYPE_DECL] = TypedefOType;
- tree_to_cadillac_map[VAR_DECL] = VariableOType;
- tree_to_cadillac_map[CONST_DECL] = EnumConstantOType;
- tree_to_cadillac_map[FUNCTION_DECL] = FunctionOType;
- tree_to_cadillac_map[FIELD_DECL] = FieldOType;
-
-#ifdef sun
- on_exit (&exit_cadillac, 0);
-#endif
-
- gcc_obstack_init (&cadillac_obstack);
-
- /* Yow! This is the way Cadillac was designed to deal with
- Oregon C++ compiler! */
- cp->fd_input = flag_cadillac;
- cp->fd_output = flag_cadillac;
-
- /* Start in "turned-on" state. */
- cp->messages = 1;
- cp->conversion = 1;
- cp->emission = 1;
-
- /* Establish a connection with Cadillac here. */
- cp->conn = NewConnection (cp, cp->fd_input, cp->fd_output);
-
- CWriteHeader (cp->conn, WaitingMType, 0);
- CWriteRequestBuffer (cp->conn);
-
- if (!readable_p (cp->fd_input))
- ;
-
- req = CReadCompilerMessage (cp->conn);
-
- if (!req)
- switch (errno)
- {
- case EWOULDBLOCK:
- sleep (5);
- return;
-
- case 0:
- fatal ("init_cadillac: EOF on connection to kernel, exiting\n");
- break;
-
- default:
- perror ("Editor to kernel connection");
- exit (0);
- }
-}
-
-static void
-cadillac_process_requests (conn)
- Connection *conn;
-{
- CCompilerMessage *req;
- while (req = (CCompilerMessage*) CPeekNextRequest (conn))
- {
- req = CReadCompilerMessage (conn);
- cadillac_process_request (&cadillacObj, req);
- }
-}
-
-static void
-cadillac_process_request (cp, req)
- cadillac_struct *cp;
- CCompilerMessage *req;
-{
- if (! req)
- return;
-
- switch (req->reqType)
- {
- case ProcessUntilMType:
- if (cp->process_until)
- my_friendly_abort (23);
- cp->process_until = 1;
- /* This is not really right. */
- cp->end_position = ((CCompilerCommand*)req)->processuntil.position;
-#if 0
- cp->end_filename = req->processuntil.filename;
-#endif
- break;
-
- case CommandMType:
- switch (req->header.data)
- {
- case MessagesOnCType:
- cp->messages = 1;
- break;
- case MessagesOffCType:
- cp->messages = 0;
- break;
- case ConversionOnCType:
- cp->conversion = 1;
- break;
- case ConversionOffCType:
- cp->conversion = 0;
- break;
- case EmissionOnCType:
- cp->emission = 1;
- break;
- case EmissionOffCType:
- cp->emission = 0;
- break;
-
- case FinishAnalysisCType:
- return;
-
- case PuntAnalysisCType:
- case ContinueAnalysisCType:
- case GotoFileposCType:
- case OpenSucceededCType:
- case OpenFailedCType:
- fprintf (stderr, "request type %d not implemented\n", req->reqType);
- return;
-
- case DieCType:
- if (! exiting)
- my_friendly_abort (24);
- return;
-
- }
- break;
-
- default:
- fatal ("unknown request type %d", req->reqType);
- }
-}
-
-void
-cadillac_start ()
-{
- Connection *conn = cadillacObj.conn;
- CCompilerMessage *req;
-
- /* Let Cadillac know that we start in C++ language scope. */
- CWriteHeader (conn, ForeignLinkageMType, LinkCPlus);
- CWriteLength (conn);
- CWriteRequestBuffer (conn);
-
- cadillac_process_requests (conn);
-}
-
-static void
-cadillac_printf (msg, name)
-{
- if (cadillacObj.messages)
- printf ("[%s,%4d] %s `%s'\n", input_filename, lineno, msg, name);
-}
-
-void
-cadillac_start_decl (decl)
- tree decl;
-{
- Connection *conn = cadillacObj.conn;
- CObjectType object_type = tree_to_cadillac_map [TREE_CODE (decl)];
-
- if (context_stack)
- switch (TREE_CODE (context_stack->context))
- {
- case FUNCTION_DECL:
- /* Currently, cadillac only implements top-level forms. */
- return;
- case RECORD_TYPE:
- case UNION_TYPE:
- cadillac_printf ("start class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl)));
- break;
- default:
- my_friendly_abort (25);
- }
- else
- {
- cadillac_printf ("start top-level decl", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- CWriteTopLevel (conn, StartMType);
- }
-
- CWriteLanguageDecl (conn, decl, tree_to_cadillac_map[TREE_CODE (decl)]);
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_finish_decl (decl)
- tree decl;
-{
- Connection *conn = cadillacObj.conn;
-
- if (context_stack)
- switch (TREE_CODE (context_stack->context))
- {
- case FUNCTION_DECL:
- return;
- case RECORD_TYPE:
- case UNION_TYPE:
- cadillac_printf ("end class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl)));
- CWriteHeader (conn, EndDefMType, 0);
- CWriteLength (conn);
- break;
- default:
- my_friendly_abort (26);
- }
- else
- {
- cadillac_printf ("end top-level decl", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- CWriteHeader (conn, EndDefMType, 0);
- CWriteLength (conn);
- CWriteTopLevel (conn, StopMType);
- }
-
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_start_function (fndecl)
- tree fndecl;
-{
- Connection *conn = cadillacObj.conn;
-
- if (context_stack)
- /* nested functions not yet handled. */
- my_friendly_abort (27);
-
- cadillac_printf ("start top-level function", lang_printable_name (fndecl));
- context_stack = push_context_level (context_stack, &cadillac_obstack);
- context_stack->context = fndecl;
-
- CWriteTopLevel (conn, StartMType);
- my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 202);
- CWriteLanguageDecl (conn, fndecl,
- (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
- ? MemberFnOType : FunctionOType));
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_finish_function (fndecl)
- tree fndecl;
-{
- Connection *conn = cadillacObj.conn;
-
- cadillac_printf ("end top-level function", lang_printable_name (fndecl));
- context_stack = pop_context_level (context_stack);
-
- if (context_stack)
- /* nested functions not yet implemented. */
- my_friendly_abort (28);
-
- CWriteHeader (conn, EndDefMType, 0);
- CWriteLength (conn);
- CWriteTopLevel (conn, StopMType);
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_finish_anon_union (decl)
- tree decl;
-{
- Connection *conn = cadillacObj.conn;
-
- if (! global_bindings_p ())
- return;
- cadillac_printf ("finish top-level anon union", "");
- CWriteHeader (conn, EndDefMType, 0);
- CWriteLength (conn);
- CWriteTopLevel (conn, StopMType);
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_start_enum (type)
- tree type;
-{
- Connection *conn = cadillacObj.conn;
-
- tree name = TYPE_NAME (type);
-
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
-
- if (context_stack)
- switch (TREE_CODE (context_stack->context))
- {
- case FUNCTION_DECL:
- return;
- case RECORD_TYPE:
- case UNION_TYPE:
- break;
- default:
- my_friendly_abort (29);
- }
- else
- {
- cadillac_printf ("start top-level enum", IDENTIFIER_POINTER (name));
- CWriteTopLevel (conn, StartMType);
- }
-
- CWriteLanguageType (conn, type, tree_to_cadillac_map[ENUMERAL_TYPE]);
-}
-
-void
-cadillac_finish_enum (type)
- tree type;
-{
- Connection *conn = cadillacObj.conn;
- tree name = TYPE_NAME (type);
-
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
-
- if (context_stack)
- switch (TREE_CODE (context_stack->context))
- {
- case FUNCTION_DECL:
- return;
- case RECORD_TYPE:
- case UNION_TYPE:
- CWriteHeader (conn, EndDefMType, 0);
- CWriteLength (conn);
- break;
- default:
- my_friendly_abort (30);
- }
- else
- {
- CWriteHeader (conn, EndDefMType, 0);
- CWriteLength (conn);
- cadillac_printf ("finish top-level enum", IDENTIFIER_POINTER (name));
- CWriteTopLevel (conn, StopMType);
- }
-
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_start_struct (type)
- tree type;
-{
- Connection *conn = cadillacObj.conn;
- tree name = TYPE_NAME (type);
-
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
-
- if (context_stack)
- switch (TREE_CODE (context_stack->context))
- {
- case FUNCTION_DECL:
- return;
- case RECORD_TYPE:
- case UNION_TYPE:
- return;
- default:
- my_friendly_abort (31);
- }
- else
- {
- cadillac_printf ("start struct", IDENTIFIER_POINTER (name));
- CWriteTopLevel (conn, StartMType);
- }
-
- context_stack = push_context_level (context_stack, &cadillac_obstack);
- context_stack->context = type;
-
- CWriteLanguageType (conn, type,
- TYPE_LANG_SPECIFIC (type) && CLASSTYPE_DECLARED_CLASS (type) ? ClassOType : tree_to_cadillac_map[TREE_CODE (type)]);
-}
-
-void
-cadillac_finish_struct (type)
- tree type;
-{
- Connection *conn = cadillacObj.conn;
- tree name = TYPE_NAME (type);
-
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
-
- context_stack = pop_context_level (context_stack);
- if (context_stack)
- return;
-
- cadillac_printf ("finish struct", IDENTIFIER_POINTER (name));
- CWriteHeader (conn, EndDefMType, 0);
- CWriteLength (conn);
- CWriteTopLevel (conn, StopMType);
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_finish_exception (type)
- tree type;
-{
- Connection *conn = cadillacObj.conn;
-
- fatal ("cadillac_finish_exception");
- CWriteHeader (conn, EndDefMType, 0);
- CWriteLength (conn);
- CWriteTopLevel (conn, StopMType);
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_push_class (type)
- tree type;
-{
-}
-
-void
-cadillac_pop_class ()
-{
-}
-
-void
-cadillac_push_lang (name)
- tree name;
-{
- Connection *conn = cadillacObj.conn;
- CLinkLanguageType m;
-
- if (name == lang_name_cplusplus)
- m = LinkCPlus;
- else if (name == lang_name_c)
- m = LinkC;
- else
- my_friendly_abort (32);
- CWriteHeader (conn, ForeignLinkageMType, m);
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_pop_lang ()
-{
- Connection *conn = cadillacObj.conn;
-
- CWriteHeader (conn, ForeignLinkageMType, LinkPop);
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_finish_stmt ()
-{
-}
-
-void
-cadillac_note_source ()
-{
- cadillacObj.lineno = lineno;
- cadillacObj.filename = input_filename;
-}
-
-static void
-CWriteTopLevel (conn, m)
- Connection *conn;
- CMessageSubType m;
-{
- static context_id = 0;
- CWriteHeader (conn, TopLevelFormMType, m);
- cadillac_note_filepos ();
-
- /* Eventually, this will point somewhere into the digest file. */
- context_id += 1;
- CWriteSomething (conn, &context_id, sizeof (BITS32));
-
- CWriteSomething (conn, &cadillacObj.iflevel, sizeof (BITS32));
- CWriteLength (conn);
-}
-
-static void
-cadillac_note_filepos ()
-{
- extern FILE *finput;
- int pos = ftell (finput);
- CWriteSomething (cadillacObj.conn, &pos, sizeof (BITS32));
-}
-
-void
-cadillac_switch_source (startflag)
- int startflag;
-{
- Connection *conn = cadillacObj.conn;
- /* Send out the name of the source file being compiled. */
-
- CWriteHeader (conn, SourceFileMType, startflag ? StartMType : StopMType);
- CWriteSomething (conn, &cadillacObj.depth, sizeof (BITS16));
- CWriteVstring0 (conn, input_filename);
- CWriteLength (conn);
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-void
-cadillac_push_source ()
-{
- cadillacObj.depth += 1;
- cadillac_switch_source (1);
-}
-
-void
-cadillac_pop_source ()
-{
- cadillacObj.depth -= 1;
- cadillac_switch_source (0);
-}
-
-struct cadillac_mdep
-{
- short object_type;
- char linkage;
- char access;
- short length;
-};
-
-static void
-CWriteLanguageElem (conn, p, name)
- Connection *conn;
- struct cadillac_mdep *p;
- char *name;
-{
- CWriteSomething (conn, &p->object_type, sizeof (BITS16));
- CWriteSomething (conn, &p->linkage, sizeof (BITS8));
- CWriteSomething (conn, &p->access, sizeof (BITS8));
- CWriteSomething (conn, &p->length, sizeof (BITS16));
- CWriteVstring0 (conn, name);
-
-#if 0
- /* Don't write date_type. */
- CWriteVstring0 (conn, "");
-#endif
- CWriteLength (conn);
-}
-
-static void
-CWriteLanguageDecl (conn, decl, object_type)
- Connection *conn;
- tree decl;
- CObjectType object_type;
-{
- struct cadillac_mdep foo;
- tree name;
-
- CWriteHeader (conn, LanguageElementMType, StartDefineMType);
- foo.object_type = object_type;
- if (decl_type_context (decl))
- {
- foo.linkage = ParentLinkage;
- if (TREE_PRIVATE (decl))
- foo.access = PrivateAccess;
- else if (TREE_PROTECTED (decl))
- foo.access = ProtectedAccess;
- else
- foo.access = PublicAccess;
- }
- else
- {
- if (TREE_PUBLIC (decl))
- foo.linkage = GlobalLinkage;
- else
- foo.linkage = FileLinkage;
- foo.access = PublicAccess;
- }
- name = DECL_NAME (decl);
- foo.length = IDENTIFIER_LENGTH (name);
-
- CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name));
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-static void
-CWriteLanguageType (conn, type, object_type)
- Connection *conn;
- tree type;
- CObjectType object_type;
-{
- struct cadillac_mdep foo;
- tree name = TYPE_NAME (type);
-
- CWriteHeader (conn, LanguageElementMType, StartDefineMType);
- foo.object_type = object_type;
- if (current_class_type)
- {
- foo.linkage = ParentLinkage;
- if (TREE_PRIVATE (type))
- foo.access = PrivateAccess;
- else if (TREE_PROTECTED (type))
- foo.access = ProtectedAccess;
- else
- foo.access = PublicAccess;
- }
- else
- {
- foo.linkage = NoLinkage;
- foo.access = PublicAccess;
- }
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
-
- foo.length = IDENTIFIER_LENGTH (name);
-
- CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name));
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-static void
-CWriteUseObject (conn, type, object_type, use)
- Connection *conn;
- tree type;
- CObjectType object_type;
- CMessageSubType use;
-{
- struct cadillac_mdep foo;
- tree name = NULL_TREE;
-
- CWriteHeader (conn, LanguageElementMType, use);
- foo.object_type = object_type;
- if (current_class_type)
- {
- foo.linkage = ParentLinkage;
- if (TREE_PRIVATE (type))
- foo.access = PrivateAccess;
- else if (TREE_PROTECTED (type))
- foo.access = ProtectedAccess;
- else
- foo.access = PublicAccess;
- }
- else
- {
- foo.linkage = NoLinkage;
- foo.access = PublicAccess;
- }
- switch (TREE_CODE (type))
- {
- case VAR_DECL:
- case FIELD_DECL:
- case TYPE_DECL:
- case CONST_DECL:
- case FUNCTION_DECL:
- name = DECL_NAME (type);
- break;
-
- default:
- my_friendly_abort (33);
- }
-
- foo.length = IDENTIFIER_LENGTH (name);
-
- CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name));
- CWriteRequestBuffer (conn);
- cadillac_process_requests (conn);
-}
-
-/* Here's how we exit under cadillac. */
-
-static void
-exit_cadillac ()
-{
- extern int errorcount;
-
- Connection *conn = cadillacObj.conn;
-
- if (flag_cadillac)
- {
- CCompilerMessage *req;
-
- CWriteHeader (conn, FinishedMType,
- errorcount ? 0 : CsObjectWritten | CsComplete);
- /* Bye, bye! */
- CWriteRequestBuffer (conn);
-
- /* Block on read. */
- while (! readable_p (cadillacObj.fd_input))
- {
- if (exiting)
- my_friendly_abort (34);
- exiting = 1;
- }
- exiting = 1;
-
- req = CReadCompilerMessage (conn);
- cadillac_process_request (&cadillacObj, req);
- }
-}
-
-#else
-/* Stubs. */
-void init_cadillac () {}
-void cadillac_start () {}
-void cadillac_start_decl (decl)
- tree decl;
-{}
-void
-cadillac_finish_decl (decl)
- tree decl;
-{}
-void
-cadillac_start_function (fndecl)
- tree fndecl;
-{}
-void
-cadillac_finish_function (fndecl)
- tree fndecl;
-{}
-void
-cadillac_finish_anon_union (decl)
- tree decl;
-{}
-void
-cadillac_start_enum (type)
- tree type;
-{}
-void
-cadillac_finish_enum (type)
- tree type;
-{}
-void
-cadillac_start_struct (type)
- tree type;
-{}
-void
-cadillac_finish_struct (type)
- tree type;
-{}
-void
-cadillac_finish_exception (type)
- tree type;
-{}
-void
-cadillac_push_class (type)
- tree type;
-{}
-void
-cadillac_pop_class ()
-{}
-void
-cadillac_push_lang (name)
- tree name;
-{}
-void
-cadillac_pop_lang ()
-{}
-void
-cadillac_note_source ()
-{}
-void
-cadillac_finish_stmt ()
-{}
-void
-cadillac_switch_source ()
-{}
-void
-cadillac_push_source ()
-{}
-void
-cadillac_pop_source ()
-{}
-#endif
diff --git a/gnu/gcc2/cc1plus/cp-except.c b/gnu/gcc2/cc1plus/cp-except.c
deleted file mode 100644
index 6f5dc3b09796..000000000000
--- a/gnu/gcc2/cc1plus/cp-except.c
+++ /dev/null
@@ -1,1221 +0,0 @@
-/* Handle exceptional things in C++.
- Copyright (C) 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. */
-
-
-/* High-level class interface. */
-
-#include "config.h"
-#include "tree.h"
-#include "rtl.h"
-#include "cp-tree.h"
-#include "flags.h"
-/* On Suns this can get you to the right definition if you
- set the right value for TARGET. */
-#include <setjmp.h>
-#ifdef sequent
-/* Can you believe they forgot this? */
-#define _JBLEN 11
-#endif
-
-#ifndef _JBLEN
-#define _JBLEN (sizeof(jmp_buf)/sizeof(int))
-#endif
-
-#undef NULL
-#define NULL (char *)0
-
-/* 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
-
-void init_exception_processing ();
-void init_exception_processing_1 ();
-
-/* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
- next exception handler. Its value says whether to throw or not.
- In the case of functions which do not issue a RAISE, it should be
- possible to optimize away this VAR_DECL (and overhead associated
- with it). */
-tree exception_throw_decl;
-/* Use this to know that we did not set `exception_throw_decl',
- until GCC optimizer is smart enough to figure it out for itself. */
-int sets_exception_throw_decl;
-
-/* The exception `type' currently in scope, or NULL_TREE if none. */
-tree current_exception_type;
-
-/* The exception handler object for the given scope. */
-tree current_exception_decl;
-rtx current_exception_name_as_rtx;
-rtx current_exception_parms_as_rtx;
-
-/* The ``object'' view of the current exception parameters.
- We cast up from the `parms' field to `current_exception_type'. */
-tree current_exception_object;
-
-/* Cache `setjmp', `longjmp', `raise_exception', and `unhandled_exception'
- after default conversion. Maybe later they will get built-in. */
-static tree BISJ, BILJ, BIR, BIUE;
-
-/* Local variables which give the appearance that exception
- handling is part of the language and the execution model. */
-
-/* The type of the exception handler stack. */
-static tree EHS_type;
-
-/* The global handler stack. */
-tree EHS_decl;
-
-/* Cached component refs to fields of `EHS_decl'. */
-static tree EHS_prev, EHS_handler, EHS_parms, EHS_name;
-static rtx EHS_parms_as_rtx, EHS_name_as_rtx;
-
-/* The parameter names of this exception type. */
-
-static tree last_exception_fields;
-static tree last_exception_field_types;
-
-/* When ID is VOID_TYPE_NODE, it means ``raise all''.
- Cannot be inline, since it uses `alloca', and that
- breaks code which pushes the result of this function
- on the stack. */
-static tree
-exception_object_name (prefix, id)
- tree prefix;
- tree id;
-{
- /* First, cons up the `name' of this exception. */
- char *name;
- int length = (id == void_type_node ? 3 : IDENTIFIER_LENGTH (id)) + EXCEPTION_NAME_LENGTH;
-
- if (prefix)
- length += IDENTIFIER_LENGTH (prefix) + 2;
-
- name = (char *)alloca (length);
- strcpy (name, EXCEPTION_NAME_PREFIX);
- length = EXCEPTION_NAME_LENGTH;
- if (prefix)
- {
- strcpy (name + length, IDENTIFIER_POINTER (prefix));
-#ifdef JOINER
- name[length + IDENTIFIER_LENGTH (prefix)] = JOINER;
-#else
- name[length + IDENTIFIER_LENGTH (prefix)] = '_';
-#endif
- length += IDENTIFIER_LENGTH (prefix) + 1;
- }
- if (id == void_type_node)
- strcpy (name + length, "all");
- else
- strcpy (name + length, IDENTIFIER_POINTER (id));
- return get_identifier (name);
-}
-
-tree
-lookup_exception_cname (ctype, cname, raise_id)
- tree ctype, cname;
- tree raise_id;
-{
- tree this_cname = TREE_PURPOSE (raise_id);
- if (this_cname == NULL_TREE)
- {
- if (cname)
- {
- tree name = TREE_VALUE (raise_id);
- if (purpose_member (name, CLASSTYPE_TAGS (ctype)))
- this_cname = cname;
- }
- }
- else if (this_cname == void_type_node)
- this_cname = NULL_TREE;
- else if (TREE_CODE (this_cname) != IDENTIFIER_NODE)
- {
- sorry ("multiple scope refs in `cplus_expand_raise_stmt'");
- this_cname = error_mark_node;
- }
- return this_cname;
-}
-
-tree
-lookup_exception_tname (oname)
- tree oname;
-{
- return get_identifier (IDENTIFIER_POINTER (oname) + EXCEPTION_NAME_LENGTH);
-}
-
-tree
-lookup_exception_object (cname, name, complain)
- tree cname, name;
- int complain;
-{
- tree oname;
- tree decl;
-
- if (cname == void_type_node)
- cname = NULL_TREE;
- else if (cname && TREE_CODE (cname) != IDENTIFIER_NODE)
- {
- sorry ("multiple scope refs in `lookup_exception_object'");
- cname = NULL_TREE;
- }
- oname = exception_object_name (cname, name);
- decl = IDENTIFIER_GLOBAL_VALUE (oname);
- if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL)
- {
- if (complain)
- {
- push_obstacks_nochange ();
-
- if (cname)
- error ("no exception name object for name `%s::%s'",
- IDENTIFIER_POINTER (cname),
- IDENTIFIER_POINTER (name));
- else
- error ("no exception name object for name `%s'",
- IDENTIFIER_POINTER (name));
- end_temporary_allocation ();
- /* Avoid further error messages. */
- pushdecl_top_level (build_lang_field_decl (VAR_DECL,
- exception_object_name (cname, name),
- error_mark_node));
- pop_obstacks ();
- }
- return NULL_TREE;
- }
- return decl;
-}
-
-tree
-lookup_exception_type (ctype, cname, raise_id)
- tree ctype, cname;
- tree raise_id;
-{
- tree name = TREE_VALUE (raise_id);
- tree purpose = TREE_PURPOSE (raise_id);
-
- if (cname && purpose == NULL_TREE)
- purpose = cname;
-
- if (purpose && purpose != void_type_node)
- {
- tree link = NULL_TREE;
-
- if (TREE_CODE (purpose) != IDENTIFIER_NODE)
- {
- sorry ("multiple scope refs in `lookup_exception_type'");
- TREE_PURPOSE (raise_id) = NULL_TREE;
- return NULL_TREE;
- }
- if (! is_aggr_typedef (purpose, 1))
- return NULL_TREE;
- ctype = IDENTIFIER_TYPE_VALUE (purpose);
- link = purpose_member (name, CLASSTYPE_TAGS (ctype));
- if (link)
- return TREE_VALUE (link);
- }
-
- ctype = lookup_name (name, 1);
- if (ctype && TREE_CODE (ctype) == TYPE_DECL)
- ctype = TREE_TYPE (ctype);
- if (ctype && TREE_CODE (ctype) == RECORD_TYPE
- && CLASSTYPE_DECLARED_EXCEPTION (ctype))
- return ctype;
- return NULL_TREE;
-}
-
-tree
-finish_exception (e, list_of_fieldlists)
- tree e;
- tree list_of_fieldlists;
-{
- tree parmtypes = NULL_TREE, name_field;
- tree cname = TYPE_NAME (e);
-
- if (TREE_CODE (cname) == TYPE_DECL)
- cname = DECL_NAME (cname);
-
- if (last_exception_fields)
- error ("cannot declare exceptions within exceptions");
- if (list_of_fieldlists && ! ANON_AGGRNAME_P (cname))
- error_with_aggr_type (e, "exception name `%s' must follow body declaration");
- if (list_of_fieldlists)
- {
- tree prev, field;
-
- /* Note: no public, private, or protected allowed. */
- if (TREE_CHAIN (list_of_fieldlists))
- error ("visibility declarations invalid in exception declaration");
- else if (TREE_PURPOSE (list_of_fieldlists) != (tree)visibility_default)
- error ("visibility declarations invalid in exception declaration");
- TREE_PURPOSE (list_of_fieldlists) = (tree)visibility_default;
-
- /* Note also: no member function declarations allowed. */
- for (prev = 0, field = TREE_VALUE (list_of_fieldlists);
- field; prev = field, field = TREE_CHAIN (field))
- {
- switch (TREE_CODE (field))
- {
- case FIELD_DECL:
- /* ok. */
- parmtypes = tree_cons (NULL_TREE, TREE_TYPE (field), parmtypes);
- continue;
- case FUNCTION_DECL:
- error_with_decl (field, "declaration of function `%s' in exception invalid");
- break;
- case VAR_DECL:
- if (TREE_STATIC (field))
- error_with_decl (field, "declaration of static variable `%s' in exception invalid");
- else
- error_with_decl (field, "declaration of constant field `%s' in exception invalid");
- break;
- case CONST_DECL:
- error_with_decl (field, "declaration of enum value `%s' in exception invalid");
- break;
- case SCOPE_REF:
- error ("use of `::' in exception context invalid");
- break;
- }
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (field);
- else
- TREE_VALUE (list_of_fieldlists) = TREE_CHAIN (field);
- }
- }
-
- /* Now that we've cleaned up the fields, add a name identifier at front. */
- name_field = build_lang_field_decl (FIELD_DECL, get_identifier ("__name"),
- ptr_type_node);
- if (list_of_fieldlists)
- {
- TREE_CHAIN (name_field) = TREE_VALUE (list_of_fieldlists);
- TREE_VALUE (list_of_fieldlists) = name_field;
- }
- else
- list_of_fieldlists = build_tree_list (NULL_TREE, name_field);
-
- last_exception_fields = TREE_VALUE (list_of_fieldlists);
- if (parmtypes)
- {
- last_exception_field_types = nreverse (parmtypes);
- /* Set the TREE_CHAIN of what is now at the end of the
- list to `void_list_node'. */
- TREE_CHAIN (parmtypes) = void_list_node;
- }
- else
- last_exception_field_types = void_list_node;
-
- popclass (0);
-
-#if 0
- /* Remove aggregate types from the list of tags,
- since these appear at global scope. */
- while (x && IS_AGGR_TYPE (TREE_VALUE (x)))
- x = TREE_CHAIN (x);
- CLASSTYPE_TAGS (t) = x;
- y = x;
- while (x)
- {
- if (IS_AGGR_TYPE (TREE_VALUE (x)))
- TREE_CHAIN (y) = TREE_CHAIN (x);
- x = TREE_CHAIN (x);
- }
-#endif
-
- if (flag_cadillac)
- cadillac_finish_exception (e);
-
- return e;
-}
-
-void
-finish_exception_decl (cname, decl)
- tree cname, decl;
-{
- /* In cp-decl.h. */
- extern tree last_function_parms;
-
- /* An exception declaration. */
- tree t, ctor;
- tree parmdecls = NULL_TREE, fields;
- tree list_of_fieldlists = temp_tree_cons (NULL_TREE,
- copy_list (last_exception_fields),
- NULL_TREE);
- tree edecl = build_lang_field_decl (VAR_DECL,
- exception_object_name (cname, DECL_NAME (decl)),
- ptr_type_node);
-
- DECL_LANGUAGE (edecl) = lang_c;
- TREE_STATIC (edecl) = 1;
- TREE_PUBLIC (edecl) = 1;
- finish_decl (pushdecl (edecl), NULL_TREE, NULL_TREE, 0);
-
- /* Now instantiate the exception decl. */
- t = xref_tag (exception_type_node, DECL_NAME (decl), NULL_TREE);
-
- /* finish_struct will pop this. */
- pushclass (t, 0);
-
- /* Now add a constructor which takes as parameters all the types we
- just defined. */
- ctor = build_lang_decl (FUNCTION_DECL, DECL_NAME (decl),
- build_cplus_method_type (t, TYPE_POINTER_TO (t),
- last_exception_field_types));
- /* Don't take `name'. The constructor handles that. */
- fields = TREE_CHAIN (TREE_VALUE (list_of_fieldlists));
- while (fields)
- {
- tree parm = build_decl (PARM_DECL, DECL_NAME (fields), TREE_TYPE (fields));
- /* Since there is a prototype, args are passed in their own types. */
- DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
-#ifdef PROMOTE_PROTOTYPES
- if (TREE_CODE (TREE_TYPE (fields)) == INTEGER_TYPE
- && TYPE_PRECISION (TREE_TYPE (fields)) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (parm) = integer_type_node;
-#endif
- TREE_CHAIN (parm) = parmdecls;
- parmdecls = parm;
- fields = TREE_CHAIN (fields);
- }
- fields = TREE_VALUE (list_of_fieldlists);
- last_function_parms = nreverse (parmdecls);
-
- DECL_CONSTRUCTOR_P (ctor) = 1;
- TYPE_HAS_CONSTRUCTOR (t) = 1;
- grokclassfn (t, DECL_NAME (decl), ctor, NO_SPECIAL, NULL_TREE);
- DECL_EXTERNAL (ctor) = 1;
- TREE_STATIC (ctor) = 1;
- TREE_PUBLIC (ctor) = 0;
- DECL_INLINE (ctor) = 1;
- make_decl_rtl (ctor, NULL_PTR, 1);
- finish_decl (ctor, NULL_TREE, NULL_TREE, 0);
- TREE_CHAIN (ctor) = TREE_VALUE (list_of_fieldlists);
- TREE_VALUE (list_of_fieldlists) = ctor;
-
- finish_struct (t, list_of_fieldlists, 0);
-
- if (current_function_decl)
- error ("cannot define exception inside function scope");
- else
- {
- enum debug_info_type old_write_symbols = write_symbols;
- write_symbols = NO_DEBUG;
-
- /* Now build the constructor for this exception. */
- parmdecls = DECL_ARGUMENTS (ctor);
- start_function (NULL_TREE, ctor, 0, 1);
- store_parm_decls ();
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
-
- /* Move all the parameters to the fields, skipping `this'. */
- parmdecls = TREE_CHAIN (parmdecls);
- /* Install `name' of this exception handler. */
- DECL_INITIAL (fields) = build_unary_op (ADDR_EXPR, edecl, 0);
- fields = TREE_CHAIN (fields);
- /* Install all the values. */
- while (fields)
- {
- /* Set up the initialization for this field. */
- DECL_INITIAL (fields) = parmdecls;
- fields = TREE_CHAIN (fields);
- parmdecls = TREE_CHAIN (parmdecls);
- }
- emit_base_init (t, 0);
-
- finish_function (DECL_SOURCE_LINE (ctor), 1);
- write_symbols = old_write_symbols;
- }
-}
-
-void
-end_exception_decls ()
-{
- last_exception_field_types = NULL_TREE;
- last_exception_fields = NULL_TREE;
-}
-
-/* Statement-level exception semantics. */
-
-void
-cplus_expand_start_try (implicit)
- int implicit;
-{
- tree call_to_setjmp;
- tree handler, ref;
-
- /* Start a new block enclosing the whole handler. */
- if (implicit)
- {
- pushlevel_temporary (1);
- }
- else
- {
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
-
- /* Encompass whole exception handler in one big binding contour.
- If RAISE should throw out of the whole TRY/EXCEPT block, call
- `expand_start_bindings' with argument of 1. */
- expand_start_bindings (0);
- }
-
- /* Allocate handler in that block. It's real name will come later.
- Note that it will be the first name in this binding contour. */
- handler = get_temp_name (EHS_type, 0);
- DECL_INITIAL (handler) = error_mark_node;
- finish_decl (handler, NULL_TREE, NULL_TREE, 0);
-
- /* Must come after call to `finish_decl', else the cleanup for the temp
- for the handler will cause the contour we just created to be popped. */
- if (implicit)
- declare_implicit_exception ();
-
- /* Catch via `setjmp'. */
- ref = build_component_ref (handler, get_identifier ("handler"), NULL_TREE, 0);
- call_to_setjmp = build_function_call (BISJ, build_tree_list (NULL_TREE, ref));
-
- /* RAISE throws to EXCEPT part. */
- expand_start_try (build_binary_op (EQ_EXPR, call_to_setjmp, integer_zero_node, 1), 0, 1);
-}
-
-/* If KEEP is 1, then declarations in the TRY statement are worth keeping.
- If KEEP is 2, then the TRY statement was generated by the compiler.
- If KEEP is 0, the declarations in the TRY statement contain errors. */
-
-tree
-cplus_expand_end_try (keep)
- int keep;
-{
- tree decls, decl, block;
-
- if (keep < 2)
- pop_implicit_try_blocks (NULL_TREE);
-
- decls = getdecls ();
-
- /* Emit code to avoid falling through into a default
- handler that might come later. */
- expand_end_try ();
-
- /* Pops binding contour local to TRY, and get the exception handler
- object built by `...start_try'. */
- switch (keep)
- {
- case 0:
- expand_end_bindings (decls, 0, 1);
- block = poplevel (0, 0, 0);
- pop_momentary ();
- decl = getdecls ();
- break;
-
- case 1:
- expand_end_bindings (decls, 1, 1);
- block = poplevel (1, 1, 0);
- pop_momentary ();
- decl = getdecls ();
- break;
-
- default:
- decl = tree_last (decls);
- block = NULL_TREE;
- break;
- }
-
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL
- && TREE_TYPE (decl) == EHS_type, 203);
- if (block)
- {
- BLOCK_HANDLER_BLOCK (block) = 1;
- TREE_USED (block) = 1;
- }
-
- /* Pass it back so that its rtl can be bound to its name
- (or vice versa). */
- return decl;
-}
-
-void
-cplus_expand_start_except (name, decl)
- tree name, decl;
-{
- int yes;
- tree tmp, init;
-
- expand_start_except (0, 1);
-
- /* This is internal `eh'. */
- current_exception_decl = decl;
- current_exception_name_as_rtx
- = expand_expr (build (COMPONENT_REF, ptr_type_node,
- current_exception_decl, TREE_OPERAND (EHS_name, 1)),
- 0, 0, 0);
- init = build (COMPONENT_REF, ptr_type_node, decl, TREE_OPERAND (EHS_parms, 1));
- current_exception_parms_as_rtx = expand_expr (init, 0, 0, 0);
-
- if (name)
- {
- /* Get the exception object into scope (user declared `ex'). */
- tmp = pushdecl (build_decl (VAR_DECL, name, ptr_type_node));
- DECL_INITIAL (tmp) = error_mark_node;
- finish_decl (tmp, init, 0, 0);
- }
- current_exception_type = NULL_TREE;
- yes = suspend_momentary ();
- if (name)
- {
- /* From now on, send the user to our faked-up object. */
- current_exception_object = build1 (INDIRECT_REF, void_type_node, tmp);
- IDENTIFIER_LOCAL_VALUE (name) = current_exception_object;
- }
- resume_momentary (yes);
-
- /* Pop exception handler stack. */
- expand_assignment (EHS_decl, EHS_prev, 0, 0);
-}
-
-/* Generate the call to `unhandled_exception' that is appropriate
- for this particular unhandled exception. */
-static tree
-call_to_unhandled_exception ()
-{
- extern int lineno;
- extern tree combine_strings ();
- tree parms = tree_cons (NULL_TREE,
- combine_strings (build_string (strlen (input_filename + 1), input_filename)),
- build_tree_list (NULL_TREE, build_int_2 (lineno, 0)));
- return build_function_call (BIUE, parms);
-}
-
-/* Note that this must be mirror image of `...start_try'.
- DFAULT is the default clause, if there was one.
- DFAULT is ERROR_MARK_NODE when this ends an implicit handler. */
-void
-cplus_expand_end_except (dfault)
- tree dfault;
-{
- extern tree expand_end_except (); /* stmt.c. */
- tree decls, raised;
-
- if (dfault == NULL_TREE)
- {
- /* Uncaught exception at outermost level. If raised locally,
- reraise the exception. Otherwise, generate code to call `abort'. */
- if (in_try_block (1) == 0)
- {
- expand_start_cond (build (EQ_EXPR, integer_type_node,
- exception_throw_decl, integer_zero_node), 0);
- expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
- expand_end_cond ();
- }
- /* Try the next handler. */
- if (! expand_escape_except ())
- compiler_error ("except nesting botch");
- }
-
- raised = expand_end_except ();
-
- decls = getdecls ();
- expand_end_bindings (decls, decls != 0, 1);
- poplevel (decls != 0, 1, 0);
-
- /* Implicit handlers do not use the momentary obstack. */
- if (dfault != error_mark_node)
- pop_momentary ();
-
- if (! in_try_block (1))
- {
- /* Check that this function is not raising exceptions
- it is not supposed to. */
- while (raised)
- {
- error_with_decl (TREE_VALUE (raised), "exception `%s' raised but not declared raisable");
- raised = TREE_CHAIN (raised);
- }
- }
- else if (dfault == NULL_TREE || dfault == error_mark_node)
- {
- expand_start_cond (build (NE_EXPR, integer_type_node,
- exception_throw_decl,
- integer_zero_node), 0);
- /* We fell off the end of this try block. Try going to the next.
- The escape_label will be the beginning of the next try block. */
- if (! expand_escape_except ())
- compiler_error ("except nesting botch");
- expand_end_cond ();
- }
-}
-
-/* Generate code to raise exception RAISE_ID.
- If EXP is NULL_TREE, then PARMS is the list of parameters to use
- for constructing this exception.
- If EXP is non-NULL, then it is an already constructed object
- of the kind that we want.
-
- FOR_RERAISE is non-zero if this raise is called by reraise. In
- this case we do not need to emit extra gotos to avoid warning messages;
- the caller will do that once after all the exceptions it reraises
- are handled and raised. */
-void
-cplus_expand_raise (raise_id, parms, exp, for_reraise)
- tree raise_id;
- tree parms;
- tree exp;
- int for_reraise;
-{
- /* Allocate new exception of appropriate type, passing
- PARMS to its constructor. */
- tree cname, name;
- tree decl;
- tree xexp = exp;
-
- cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
- if (cname == error_mark_node)
- return;
- name = TREE_VALUE (raise_id);
-
- decl = lookup_exception_object (cname, name, 1);
- if (decl == NULL_TREE)
- return;
-
- if (exp == NULL_TREE)
- {
- exp = build_method_call (NULL_TREE, name, parms, NULL_TREE, LOOKUP_COMPLAIN);
- if (exp == error_mark_node)
- return;
- }
-
- if (in_try_block (1))
- {
- expand_raise (decl);
- }
- else if (! current_function_decl)
- {
- if (xexp == NULL_TREE)
- error_with_decl (decl, "invalid raise of `%s' outside of functions");
- else
- error_with_decl (decl, "invalid reraise of `%s' outside of functions");
- }
- else
- {
- /* Test this raise against what this function permits. */
- tree names = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl));
- while (names)
- {
- if (decl == TREE_TYPE (names))
- break;
- names = TREE_CHAIN (names);
- }
- if (names == NULL_TREE)
- {
- error ("current function not declared to raise exception `%s'",
- IDENTIFIER_POINTER (name));
- return;
- }
- }
-
- store_expr (exp, EHS_parms_as_rtx, 0);
-
- /* Set the global exception handler stack's NAME field
- to the `name' of this exception. The global exception
- handler stack is the container for the exception object
- we just built.
-
- We go through a function call to make life easier when debugging. */
-#if 0
- expand_assignment (EHS_name, build_unary_op (ADDR_EXPR, decl, 0), 0, 0);
-#else
- parms = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, EHS_name, 0),
- build_tree_list (NULL_TREE,
- build_unary_op (ADDR_EXPR, decl, 0)));
- expand_expr (build_function_call (BIR, parms), 0, 0, 0);
-#endif
-
- /* Activate thrower. If we are inside a TRY statement,
- we can cheat and not do this, saving a longjmp. */
- if (in_try_block (1) == 0)
- {
- sets_exception_throw_decl = 1;
- emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);
- }
-
- if (xexp == NULL_TREE)
- {
- /* Invoke destructors for current procedure or handler. */
- if (! expand_escape_except ())
- compiler_error ("except nesting botch");
- /* Throw via `longjmp'... Done as side-effect of goto. */
- }
- /* To avoid spurious warning messages, we add a goto to the end
- of the function. This code is dead, and the compiler should
- know how to delete it, but for now, we are stuck with it. */
- if (! for_reraise
- && TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
- expand_null_return ();
-}
-
-extern tree cplus_exception_name ();
-
-tree
-ansi_exception_object_lookup (type)
- tree type;
-{
- tree raise_id = cplus_exception_name (type);
- tree decl;
-
- decl = IDENTIFIER_GLOBAL_VALUE (raise_id);
- if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL)
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- decl = build_decl (VAR_DECL, raise_id, ptr_type_node);
- TREE_PUBLIC (decl) = 1;
- TREE_STATIC (decl) = 1;
- pushdecl_top_level (decl);
- make_decl_rtl (decl, (char*)0, 1);
- pop_obstacks ();
- }
- return decl;
-}
-
-/* Generate code to throw an exception using EXP.
- Usng ANSI syntax and semantics.
- If EXP is NULL_TREE< re-raise instead. */
-
-void
-cplus_expand_throw (exp)
- tree exp;
-{
- tree parms;
- int for_reraise;
- /* Allocate new exception of appropriate type, passing
- PARMS to its constructor. */
- tree decl = ansi_exception_object_lookup (TREE_TYPE (exp));
- tree xexp = exp;
-
- if (in_try_block (1))
- {
-#if 1
- my_friendly_abort (35);
-#else
- expand_raise (decl);
-#endif
- }
- else if (! current_function_decl)
- error ("invalid throw outside of functions");
- else
- {
-#if 0
- /* Test this raise against what this function permits. */
- tree names = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl));
- while (names)
- {
- if (decl == TREE_TYPE (names))
- break;
- names = TREE_CHAIN (names);
- }
- if (names == NULL_TREE)
- {
- error ("current function not declared to raise exception `%s'",
- IDENTIFIER_POINTER (name));
- return;
- }
-#endif
- }
-
- store_expr (exp, EHS_parms_as_rtx, 0);
-
- /* Set the global exception handler stack's NAME field
- to the `name' of this exception. The global exception
- handler stack is the container for the exception object
- we just built.
-
- We go through a function call to make life easier when debugging. */
-#if 0
- expand_assignment (EHS_name, build_unary_op (ADDR_EXPR, decl, 0), 0, 0);
-#else
- parms = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, EHS_name, 0),
- build_tree_list (NULL_TREE,
- build_unary_op (ADDR_EXPR, decl, 0)));
- expand_expr (build_function_call (BIR, parms), 0, 0, 0);
-#endif
-
- /* Activate thrower. If we are inside a TRY statement,
- we can cheat and not do this, saving a longjmp. */
- if (in_try_block (1) == 0)
- {
- sets_exception_throw_decl = 1;
- emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);
- }
-
- if (xexp == NULL_TREE)
- {
- /* Invoke destructors for current procedure or handler. */
- if (! expand_escape_except ())
- compiler_error ("except nesting botch");
- /* Throw via `longjmp'... Done as side-effect of goto. */
- }
-
- /* XXX: for_reraise is never set above here. */
- /* To avoid spurious warning messages, we add a goto to the end
- of the function. This code is dead, and the compiler should
- know how to delete it, but for now, we are stuck with it. */
- if (! for_reraise
- && TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
- expand_null_return ();
-}
-
-tree
-cplus_expand_start_catch (raise_id)
- tree raise_id;
-{
- tree cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
- tree decl;
- tree cond;
-
- if (cname == error_mark_node)
- {
- decl = error_mark_node;
- cond = error_mark_node;
- }
- else
- {
- decl = lookup_exception_object (cname, TREE_VALUE (raise_id), 1);
- if (decl == NULL_TREE)
- cond = error_mark_node;
- else
- cond = build_binary_op (EQ_EXPR, build_unary_op (ADDR_EXPR, decl, 0),
- build (COMPONENT_REF, ptr_type_node,
- current_exception_decl,
- TREE_OPERAND (EHS_name, 1)),
- 1);
- }
- expand_start_cond (cond, 0);
-
- /* Does nothing right now. */
- expand_catch (decl);
- if (current_exception_type
- && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
- {
- /* Make a cleanup for the name-specific exception object now in scope. */
- tree cleanup = maybe_build_cleanup (current_exception_object);
- expand_start_bindings (0);
- expand_decl_cleanup (NULL_TREE, cleanup);
- }
- return decl;
-}
-tree
-ansi_expand_start_catch (raise_type)
- tree raise_type;
-{
- tree decl = ansi_exception_object_lookup (raise_type);
- tree cond;
-
- if (decl == NULL_TREE)
- cond = error_mark_node;
- else
- cond = build_binary_op (EQ_EXPR, build_unary_op (ADDR_EXPR, decl, 0),
- build (COMPONENT_REF, ptr_type_node,
- current_exception_decl,
- TREE_OPERAND (EHS_name, 1)),
- 1);
- expand_start_cond (cond, 0);
-
- /* Does nothing right now. */
- expand_catch (decl);
- return decl;
-}
-
-void
-cplus_expand_end_catch (for_reraise)
- int for_reraise;
-{
- if (current_exception_type
- && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
- {
- /* Destroy the specific exception object now in scope. */
- expand_end_bindings (getdecls (), 0, 1);
- }
- if (for_reraise)
- {
- if (! expand_escape_except ())
- my_friendly_abort (36);
- }
- else
- {
- if (! expand_end_catch ())
- my_friendly_abort (37);
- }
- expand_end_cond ();
-}
-
-/* Reraise an exception.
- If EXCEPTIONS is NULL_TREE, it means reraise whatever exception was caught.
- If EXCEPTIONS is an IDENTIFIER_NODE, it means reraise the exception
- object named by EXCEPTIONS. This must be a variable declared in
- an `except' clause.
- If EXCEPTIONS is a TREE_LIST, it is the list of exceptions we are
- willing to reraise. */
-
-void
-cplus_expand_reraise (exceptions)
- tree exceptions;
-{
- tree ex_ptr;
- tree ex_object = current_exception_object;
- rtx ex_ptr_as_rtx;
-
- if (exceptions && TREE_CODE (exceptions) == IDENTIFIER_NODE)
- {
- /* Don't get tripped up if its TREE_TYPE is `error_mark_node'. */
- ex_object = IDENTIFIER_LOCAL_VALUE (exceptions);
- if (ex_object == NULL_TREE || TREE_CODE (ex_object) != INDIRECT_REF)
- {
- error ("`%s' is not an exception decl", IDENTIFIER_POINTER (exceptions));
- return;
- }
- my_friendly_assert (TREE_CODE (TREE_OPERAND (ex_object, 0)) == VAR_DECL,
- 204);
- exceptions = NULL_TREE;
- }
-
- ex_ptr = build1 (NOP_EXPR, ptr_type_node, TREE_OPERAND (ex_object, 0));
- ex_ptr_as_rtx = expand_expr (ex_ptr, 0, 0, 0);
-
- /* reraise ALL, used by compiler. */
- if (exceptions == NULL_TREE)
- {
- /* Now treat reraise like catch/raise. */
- expand_catch (error_mark_node);
- expand_raise (error_mark_node);
- emit_move_insn (EHS_name_as_rtx, current_exception_name_as_rtx);
- store_expr ((tree) EHS_parms_as_rtx, current_exception_parms_as_rtx, 0);
- if (in_try_block (1) == 0)
- {
- sets_exception_throw_decl = 1;
- emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);
- }
- /* Set to zero so that destructor will not be called. */
- emit_move_insn (ex_ptr_as_rtx, const0_rtx);
- if (! expand_escape_except ())
- my_friendly_abort (38);
-
- /* To avoid spurious warning messages, we add a goto to the end
- of the function. This code is dead, and the compiler should
- know how to delete it, but for now, we are stuck with it. */
- if (TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
- expand_null_return ();
-
- return;
- }
-
- /* reraise from a list of exceptions. */
- while (exceptions)
- {
- tree type = lookup_exception_type (current_class_type, current_class_name,
- exceptions);
- if (type == NULL_TREE)
- {
- error ("`%s' is not an exception type",
- IDENTIFIER_POINTER (TREE_VALUE (exceptions)));
- current_exception_type = NULL_TREE;
- TREE_TYPE (ex_object) = error_mark_node;
- TREE_TYPE (ex_ptr) = error_mark_node;
- }
- else
- {
- current_exception_type = type;
- /* In-place union. */
- TREE_TYPE (ex_object) = type;
- TREE_TYPE (ex_ptr) = TYPE_POINTER_TO (type);
- }
-
- /* Now treat reraise like catch/raise. */
- cplus_expand_start_catch (exceptions);
- cplus_expand_raise (exceptions, NULL_TREE, ex_ptr, 1);
- /* Set to zero so that destructor will not be called. */
- if (TREE_TYPE (ex_ptr) != error_mark_node)
- emit_move_insn (ex_ptr_as_rtx, const0_rtx);
- cplus_expand_end_catch (1);
- exceptions = TREE_CHAIN (exceptions);
- }
- /* Don't propagate any unhandled exceptions. */
- expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
-
- /* To avoid spurious warning messages, we add a goto to the end
- of the function. This code is dead, and the compiler should
- know how to delete it, but for now, we are stuck with it. */
- if (TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
- expand_null_return ();
-}
-
-void
-setup_exception_throw_decl ()
-{
- tree call_to_longjmp, parms;
-
- int old = suspend_momentary ();
-
- exception_throw_decl = build_decl (VAR_DECL, get_identifier (THROW_NAME), integer_type_node);
- pushdecl (exception_throw_decl);
- parms = tree_cons (NULL_TREE, EHS_handler,
- build_tree_list (0, integer_one_node));
- call_to_longjmp = build_function_call (BILJ, parms);
-
- expand_decl (exception_throw_decl);
- expand_decl_cleanup (exception_throw_decl,
- build (COND_EXPR, void_type_node,
- exception_throw_decl,
- call_to_longjmp, integer_zero_node));
- DECL_INITIAL (exception_throw_decl) = integer_zero_node;
- sets_exception_throw_decl = 0;
- resume_momentary (old);
-
- /* Cache these, since they won't change throughout the function. */
- EHS_parms_as_rtx = expand_expr (EHS_parms, 0, 0, 0);
- EHS_name_as_rtx = expand_expr (EHS_name, 0, 0, 0);
-}
-
-void
-init_exception_processing ()
-{
- extern tree build_function_type (), define_function ();
- extern tree unhandled_exception_fndecl;
- tree cname = get_identifier ("ExceptionHandler");
- tree field, chain;
- tree ctor, dtor;
- tree jmp_buf_type = build_array_type (integer_type_node,
- build_index_type (build_int_2 (_JBLEN-1, 0)));
- tree jmp_buf_arg_type = build_pointer_type (integer_type_node);
-
- tree parmtypes = hash_tree_chain (jmp_buf_arg_type, void_list_node);
- tree setjmp_fndecl, longjmp_fndecl, raise_fndecl;
-
- int old_interface_only = interface_only;
- int old_interface_unknown = interface_unknown;
- interface_only = 1;
- interface_unknown = 0;
- EHS_type = xref_tag (record_type_node, cname, NULL_TREE);
- push_lang_context (lang_name_c);
- setjmp_fndecl = define_function ("setjmp",
- build_function_type (integer_type_node,
- parmtypes),
- NOT_BUILT_IN, pushdecl, 0);
- BISJ = default_conversion (setjmp_fndecl);
- parmtypes = hash_tree_chain (jmp_buf_arg_type,
- hash_tree_chain (integer_type_node, void_list_node));
- longjmp_fndecl = define_function ("longjmp",
- build_function_type (void_type_node, parmtypes),
- NOT_BUILT_IN, pushdecl, 0);
- raise_fndecl = define_function ("__raise_exception",
- build_function_type (void_type_node,
- hash_tree_chain (ptr_type_node,
- hash_tree_chain (build_pointer_type (ptr_type_node), void_list_node))),
- NOT_BUILT_IN, pushdecl, 0);
- BILJ = default_conversion (longjmp_fndecl);
- BIR = default_conversion (raise_fndecl);
- BIUE = default_conversion (unhandled_exception_fndecl);
-
- pop_lang_context ();
-
- /* finish_struct will pop this. */
- pushclass (EHS_type, 0);
- field = build_lang_field_decl (FIELD_DECL, get_identifier ("parms"), ptr_type_node);
- chain = field;
- field = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
- build_pointer_type (default_function_type));
- TREE_CHAIN (field) = chain;
- chain = field;
- field = build_lang_field_decl (FIELD_DECL, get_identifier ("handler"), jmp_buf_type);
- TREE_CHAIN (field) = chain;
- chain = field;
- field = build_lang_field_decl (FIELD_DECL, get_identifier ("prev"),
- TYPE_POINTER_TO (EHS_type));
- TREE_CHAIN (field) = chain;
- chain = field;
-
- ctor = build_lang_decl (FUNCTION_DECL, cname,
- build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
- DECL_CONSTRUCTOR_P (ctor) = 1;
- TREE_STATIC (ctor) = 1;
- TREE_PUBLIC (ctor) = 1;
- DECL_EXTERNAL (ctor) = 1;
- grokclassfn (EHS_type, cname, ctor, NO_SPECIAL, 0);
- grok_ctor_properties (EHS_type, ctor);
- finish_decl (pushdecl (ctor), NULL_TREE, NULL_TREE, 0);
- /* Must copy the node here because the FUNCTION_DECL
- used inside the struct ain't the same as the
- FUNCTION_DECL we stick into the global binding
- contour. */
- ctor = copy_node (ctor);
- TREE_CHAIN (ctor) = chain;
- chain = ctor;
- dtor = build_lang_decl (FUNCTION_DECL, cname,
- build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
- TREE_STATIC (dtor) = 1;
- TREE_PUBLIC (dtor) = 1;
- DECL_EXTERNAL (dtor) = 1;
- grokclassfn (EHS_type, cname, dtor, DTOR_FLAG, 0);
- finish_decl (pushdecl (dtor), NULL_TREE, NULL_TREE, 0);
- /* Copy for the same reason as copying ctor. */
- dtor = copy_node (dtor);
- TREE_CHAIN (dtor) = chain;
- chain = dtor;
- TYPE_HAS_CONSTRUCTOR (EHS_type) = 1;
- TYPE_HAS_DESTRUCTOR (EHS_type) = 1;
- finish_struct (EHS_type, temp_tree_cons (NULL_TREE, chain, NULL_TREE), 0);
- interface_only = old_interface_only;
- interface_unknown = old_interface_unknown;
-}
-
-void
-init_exception_processing_1 ()
-{
- register tree EHS_id = get_identifier ("exceptionHandlerStack");
-
- EHS_decl = IDENTIFIER_GLOBAL_VALUE (EHS_id);
-
- /* If we have no other definition, default to library implementation. */
- if (EHS_decl == NULL_TREE)
- {
- EHS_decl = build_decl (VAR_DECL, EHS_id, TYPE_POINTER_TO (EHS_type));
- /* If we don't push this, its definition, should it be encountered,
- will not be seen. */
- EHS_decl = pushdecl (EHS_decl);
- DECL_EXTERNAL (EHS_decl) = 1;
- TREE_STATIC (EHS_decl) = 1;
- TREE_PUBLIC (EHS_decl) = 1;
- finish_decl (EHS_decl, NULL_TREE, NULL_TREE, 0);
- }
- else if (TREE_CODE (EHS_decl) != VAR_DECL
- || TREE_TYPE (EHS_decl) != TYPE_POINTER_TO (EHS_type))
- fatal ("exception handling declarations conflict with compiler's internal model");
-
- if (EHS_prev == NULL_TREE)
- {
- register tree EHS_DECL = build1 (INDIRECT_REF, EHS_type, EHS_decl);
- EHS_prev = build_component_ref (EHS_DECL, get_identifier ("prev"), 0, 0);
- EHS_handler = build_component_ref (EHS_DECL, get_identifier ("handler"), 0, 0);
- EHS_parms = build_component_ref (EHS_DECL, get_identifier ("parms"), 0, 0);
- EHS_name = build_component_ref (EHS_DECL, get_identifier ("name"), 0, 0);
- }
-}
diff --git a/gnu/gcc2/cc1plus/cp-expr.c b/gnu/gcc2/cc1plus/cp-expr.c
deleted file mode 100644
index 77c0ab5e1623..000000000000
--- a/gnu/gcc2/cc1plus/cp-expr.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/* Convert language-specific tree expression to rtl instructions,
- for GNU compiler.
- Copyright (C) 1988, 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
-#include "config.h"
-#include "rtl.h"
-#include "tree.h"
-#include "flags.h"
-#include "expr.h"
-#include "cp-tree.h"
-
-#undef NULL
-#define NULL 0
-
-/* Hook used by expand_expr to expand language-specific tree codes. */
-
-rtx
-cplus_expand_expr (exp, target, tmode, modifier)
- tree exp;
- rtx target;
- enum machine_mode tmode;
- enum expand_modifier modifier;
-{
- tree type = TREE_TYPE (exp);
- register enum machine_mode mode = TYPE_MODE (type);
- register enum tree_code code = TREE_CODE (exp);
- rtx original_target = target;
- int ignore = target == const0_rtx;
-
- if (ignore) target = 0, original_target = 0;
-
- /* No sense saving up arithmetic to be done
- if it's all in the wrong mode to form part of an address.
- And force_operand won't know whether to sign-extend or zero-extend. */
-
- if (mode != Pmode && modifier == EXPAND_SUM)
- modifier = EXPAND_NORMAL;
-
- switch (code)
- {
- case NEW_EXPR:
- {
- /* Something needs to be initialized, but we didn't know
- where that thing was when building the tree. For example,
- it could be the return value of a function, or a parameter
- to a function which lays down in the stack, or a temporary
- variable which must be passed by reference.
-
- Cleanups are handled in a language-specific way: they
- might be run by the called function (true in GNU C++
- for parameters with cleanups), or they might be
- run by the caller, after the call (true in GNU C++
- for other cleanup needs). */
-
- tree func = TREE_OPERAND (exp, 0);
- tree args = TREE_OPERAND (exp, 1);
- tree type = TREE_TYPE (exp), slot;
- tree fn_type = TREE_TYPE (TREE_TYPE (func));
- tree return_type = TREE_TYPE (fn_type);
- rtx call_target, return_target;
-
- /* The expression `init' wants to initialize what
- `target' represents. SLOT holds the slot for TARGET. */
- slot = TREE_OPERAND (exp, 2);
-
- if (target == 0)
- {
- /* Should always be called with a target in BLKmode case. */
- my_friendly_assert (mode != BLKmode, 205);
- my_friendly_assert (DECL_RTL (slot) != 0, 206);
-
- target = gen_reg_rtx (mode);
- }
-
- /* The target the initializer will initialize (CALL_TARGET)
- must now be directed to initialize the target we are
- supposed to initialize (TARGET). The semantics for
- choosing what CALL_TARGET is is language-specific,
- as is building the call which will perform the
- initialization. It is left here to show the choices that
- exist for C++. */
-
- if (TREE_CODE (func) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
- && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
- {
- type = TYPE_POINTER_TO (type);
- /* Don't clobber a value that might be part of a default
- parameter value. */
- if (TREE_PERMANENT (args))
- args = tree_cons (0, build1 (ADDR_EXPR, type, slot),
- TREE_CHAIN (args));
- else
- TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot);
- call_target = 0;
- }
- else if (TREE_CODE (return_type) == REFERENCE_TYPE)
- {
- type = return_type;
- call_target = 0;
- }
- else
- {
- call_target = target;
- }
- if (call_target)
- preserve_temp_slots (call_target);
- preserve_temp_slots (DECL_RTL (slot));
- return_target = expand_expr (build (CALL_EXPR, type, func, args, 0), call_target, mode, 0);
- free_temp_slots ();
- if (call_target == 0)
- call_target = return_target;
- else if (call_target != return_target)
- {
- if (GET_MODE (return_target) == BLKmode)
- emit_block_move (call_target, return_target, expr_size (exp),
- TYPE_ALIGN (type) / BITS_PER_UNIT);
- else
- emit_move_insn (call_target, return_target);
- }
-
- if (TREE_CODE (return_type) == REFERENCE_TYPE)
- {
- tree init;
-
- if (GET_CODE (call_target) == REG
- && REGNO (call_target) < FIRST_PSEUDO_REGISTER)
- my_friendly_abort (39);
-
- type = TREE_TYPE (exp);
-
- init = build (RTL_EXPR, return_type, 0, call_target);
- /* We got back a reference to the type we want. Now initialize
- target with that. */
- expand_aggr_init (slot, init, 0);
- }
-
- if (DECL_RTL (slot) != target)
- emit_move_insn (DECL_RTL (slot), target);
- return DECL_RTL (slot);
- }
-
- case OFFSET_REF:
- {
- tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
- tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
- return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
- target, tmode, EXPAND_NORMAL);
- }
-
- default:
- break;
- }
- my_friendly_abort (40);
- /* NOTREACHED */
- return NULL;
-}
-
-void
-init_cplus_expand ()
-{
- lang_expand_expr = cplus_expand_expr;
-}
-
-/* If DECL had its rtl moved from where callers expect it
- to be, fix it up. RESULT is the nominal rtl for the RESULT_DECL,
- which may be a pseudo instead of a hard register. */
-
-void
-fixup_result_decl (decl, result)
- tree decl;
- rtx result;
-{
- if (REG_P (result))
- {
- if (REGNO (result) >= FIRST_PSEUDO_REGISTER)
- {
- rtx real_decl_result;
-
-#ifdef FUNCTION_OUTGOING_VALUE
- real_decl_result
- = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl), current_function_decl);
-#else
- real_decl_result
- = FUNCTION_VALUE (TREE_TYPE (decl), current_function_decl);
-#endif
- REG_FUNCTION_VALUE_P (real_decl_result) = 1;
- result = real_decl_result;
- }
- emit_move_insn (result, DECL_RTL (decl));
- emit_insn (gen_rtx (USE, VOIDmode, result));
- }
-}
-
-/* Return nonzero iff DECL is memory-based. The DECL_RTL of
- certain const variables might be a CONST_INT, or a REG
- in some cases. We cannot use `memory_operand' as a test
- here because on most RISC machines, a variable's address
- is not, by itself, a legitimate address. */
-int
-decl_in_memory_p (decl)
- tree decl;
-{
- return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
-}
diff --git a/gnu/gcc2/cc1plus/cp-gc.c b/gnu/gcc2/cc1plus/cp-gc.c
deleted file mode 100644
index f62832458390..000000000000
--- a/gnu/gcc2/cc1plus/cp-gc.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/* Garbage collection primitives for GNU C++.
- Copyright (C) 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. */
-
-
-#include "config.h"
-#include "tree.h"
-#include "cp-tree.h"
-#include "flags.h"
-
-#undef NULL
-#define NULL 0
-
-extern tree define_function ();
-extern tree build_t_desc_overload ();
-
-/* This is the function decl for the (pseudo-builtin) __gc_protect
- function. Args are (class *value, int index); Returns value. */
-tree gc_protect_fndecl;
-
-/* This is the function decl for the (pseudo-builtin) __gc_unprotect
- function. Args are (int index); void return. */
-tree gc_unprotect_fndecl;
-
-/* This is the function decl for the (pseudo-builtin) __gc_push
- function. Args are (int length); void return. */
-tree gc_push_fndecl;
-
-/* This is the function decl for the (pseudo-builtin) __gc_pop
- function. Args are void; void return. */
-tree gc_pop_fndecl;
-
-/* Special integers that are used to represent bits in gc-safe objects. */
-tree gc_nonobject;
-tree gc_visible;
-tree gc_white;
-tree gc_offwhite;
-tree gc_grey;
-tree gc_black;
-
-/* in c-common.c */
-extern tree combine_strings PROTO((tree));
-
-/* Predicate that returns non-zero if TYPE needs some kind of
- entry for the GC. Returns zero otherwise. */
-int
-type_needs_gc_entry (type)
- tree type;
-{
- tree ttype = type;
-
- if (! flag_gc || type == error_mark_node)
- return 0;
-
- /* Aggregate types need gc entries if any of their members
- need gc entries. */
- if (IS_AGGR_TYPE (type))
- {
- tree binfos;
- tree fields = TYPE_FIELDS (type);
- int i;
-
- /* We don't care about certain pointers. Pointers
- to virtual baseclasses are always up front. We also
- cull out virtual function table pointers because it's
- easy, and it simplifies the logic.*/
- while (fields
- && (DECL_NAME (fields) == NULL_TREE
- || VFIELD_NAME_P (DECL_NAME (fields))
- || VBASE_NAME_P (DECL_NAME (fields))
- || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fields)), "__bits")))
- fields = TREE_CHAIN (fields);
-
- while (fields)
- {
- if (type_needs_gc_entry (TREE_TYPE (fields)))
- return 1;
- fields = TREE_CHAIN (fields);
- }
-
- binfos = TYPE_BINFO_BASETYPES (type);
- if (binfos)
- for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
- if (type_needs_gc_entry (BINFO_TYPE (TREE_VEC_ELT (binfos, i))))
- return 1;
-
- return 0;
- }
-
- while (TREE_CODE (ttype) == ARRAY_TYPE
- && TREE_CODE (TREE_TYPE (ttype)) == ARRAY_TYPE)
- ttype = TREE_TYPE (ttype);
- if ((TREE_CODE (ttype) == POINTER_TYPE
- || TREE_CODE (ttype) == ARRAY_TYPE
- || TREE_CODE (ttype) == REFERENCE_TYPE)
- && IS_AGGR_TYPE (TREE_TYPE (ttype))
- && CLASSTYPE_DOSSIER (TREE_TYPE (ttype)))
- return 1;
-
- return 0;
-}
-
-/* Predicate that returns non-zero iff FROM is safe from the GC.
-
- If TO is nonzero, it means we know that FROM is being stored
- in TO, which make make it safe. */
-int
-value_safe_from_gc (to, from)
- tree to, from;
-{
- /* First, return non-zero for easy cases: parameters,
- static variables. */
- if (TREE_CODE (from) == PARM_DECL
- || (TREE_CODE (from) == VAR_DECL
- && TREE_STATIC (from)))
- return 1;
-
- /* If something has its address taken, it cannot be
- in the heap, so it doesn't need to be protected. */
- if (TREE_CODE (from) == ADDR_EXPR || TREE_REFERENCE_EXPR (from))
- return 1;
-
- /* If we are storing into a static variable, then what
- we store will be safe from the gc. */
- if (to && TREE_CODE (to) == VAR_DECL
- && TREE_STATIC (to))
- return 1;
-
- /* Now recurse on structure of FROM. */
- switch (TREE_CODE (from))
- {
- case COMPONENT_REF:
- /* These guys are special, and safe. */
- if (TREE_CODE (TREE_OPERAND (from, 1)) == FIELD_DECL
- && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))
- || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (from, 1)))))
- return 1;
- /* fall through... */
- case NOP_EXPR:
- case CONVERT_EXPR:
- case NON_LVALUE_EXPR:
- case WITH_CLEANUP_EXPR:
- case SAVE_EXPR:
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- if (value_safe_from_gc (to, TREE_OPERAND (from, 0)))
- return 1;
- break;
-
- case VAR_DECL:
- case PARM_DECL:
- /* We can safely pass these things as parameters to functions. */
- if (to == 0)
- return 1;
-
- case ARRAY_REF:
- case INDIRECT_REF:
- case RESULT_DECL:
- case OFFSET_REF:
- case CALL_EXPR:
- case METHOD_CALL_EXPR:
- break;
-
- case COMPOUND_EXPR:
- case TARGET_EXPR:
- if (value_safe_from_gc (to, TREE_OPERAND (from, 1)))
- return 1;
- break;
-
- case COND_EXPR:
- if (value_safe_from_gc (to, TREE_OPERAND (from, 1))
- && value_safe_from_gc (to, TREE_OPERAND (from, 2)))
- return 1;
- break;
-
- case PLUS_EXPR:
- case MINUS_EXPR:
- if ((type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 0)))
- || value_safe_from_gc (to, TREE_OPERAND (from, 0)))
- && (type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 1))) == 0
- || value_safe_from_gc (to, TREE_OPERAND (from, 1))))
- return 1;
- break;
-
- case RTL_EXPR:
- /* Every time we build an RTL_EXPR in the front-end, we must
- ensure that everything in it is safe from the garbage collector.
- ??? This has only been done for `build_new'. */
- return 1;
-
- default:
- my_friendly_abort (41);
- }
-
- if (to == 0)
- return 0;
-
- /* FROM wasn't safe. But other properties of TO might make it safe. */
- switch (TREE_CODE (to))
- {
- case VAR_DECL:
- case PARM_DECL:
- /* We already culled out static VAR_DECLs above. */
- return 0;
-
- case COMPONENT_REF:
- /* These guys are special, and safe. */
- if (TREE_CODE (TREE_OPERAND (to, 1)) == FIELD_DECL
- && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))
- || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (to, 1)))))
- return 1;
- /* fall through... */
-
- case NOP_EXPR:
- case NON_LVALUE_EXPR:
- case WITH_CLEANUP_EXPR:
- case SAVE_EXPR:
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- return value_safe_from_gc (TREE_OPERAND (to, 0), from);
-
- case COMPOUND_EXPR:
- case TARGET_EXPR:
- return value_safe_from_gc (TREE_OPERAND (to, 1), from);
-
- case COND_EXPR:
- return (value_safe_from_gc (TREE_OPERAND (to, 1), from)
- && value_safe_from_gc (TREE_OPERAND (to, 2), from));
-
- case INDIRECT_REF:
- case ARRAY_REF:
- /* This used to be 0, but our current restricted model
- allows this to be 1. We'll never get arrays this way. */
- return 1;
-
- default:
- my_friendly_abort (42);
- }
-
- /* Catch-all case is that TO/FROM is not safe. */
- return 0;
-}
-
-/* Function to build a static GC entry for DECL. TYPE is DECL's type.
-
- For objects of type `class *', this is just an entry in the
- static vector __PTR_LIST__.
-
- For objects of type `class[]', this requires building an entry
- in the static vector __ARR_LIST__.
-
- For aggregates, this records all fields of type `class *'
- and `class[]' in the respective lists above. */
-void
-build_static_gc_entry (decl, type)
- tree decl;
- tree type;
-{
- /* Now, figure out what sort of entry to build. */
- if (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- assemble_gc_entry (IDENTIFIER_POINTER (DECL_NAME (decl)));
- else if (TREE_CODE (type) == RECORD_TYPE)
- {
- tree ref = get_temp_name (build_reference_type (type), 1);
- DECL_INITIAL (ref) = build1 (ADDR_EXPR, TREE_TYPE (ref), decl);
- TREE_CONSTANT (DECL_INITIAL (ref)) = 1;
- finish_decl (ref, DECL_INITIAL (ref), 0, 0);
- }
- else
- {
- /* Not yet implemented.
-
- Cons up a static variable that holds address and length info
- and add that to ___ARR_LIST__. */
- my_friendly_abort (43);
- }
-}
-
-/* Protect FROM from the GC, assuming FROM is going to be
- stored into TO. We handle three cases for TO here:
-
- case 1: TO is a stack variable.
- case 2: TO is zero (which means it is a parameter).
- case 3: TO is a return value. */
-
-tree
-protect_value_from_gc (to, from)
- tree to, from;
-{
- if (to == 0)
- {
- tree cleanup;
-
- to = get_temp_regvar (TREE_TYPE (from), from);
-
- /* Convert from integer to list form since we'll use it twice. */
- DECL_GC_OFFSET (to) = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
- cleanup = build_function_call (gc_unprotect_fndecl,
- DECL_GC_OFFSET (to));
-
- if (! expand_decl_cleanup (to, cleanup))
- {
- compiler_error ("cannot unprotect parameter in this scope");
- return error_mark_node;
- }
- }
-
- /* Should never need to protect a value that's headed for static storage. */
- if (TREE_STATIC (to))
- my_friendly_abort (44);
-
- switch (TREE_CODE (to))
- {
- case COMPONENT_REF:
- case INDIRECT_REF:
- return protect_value_from_gc (TREE_OPERAND (to, 0), from);
-
- case VAR_DECL:
- case PARM_DECL:
- {
- tree rval;
- if (DECL_GC_OFFSET (to) == NULL_TREE)
- {
- /* Because of a cast or a conversion, we might stick
- a value into a variable that would not normally
- have a GC entry. */
- DECL_GC_OFFSET (to) = size_int (++current_function_obstack_index);
- }
-
- if (TREE_CODE (DECL_GC_OFFSET (to)) != TREE_LIST)
- {
- DECL_GC_OFFSET (to)
- = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to));
- }
-
- current_function_obstack_usage = 1;
- rval = build_function_call (gc_protect_fndecl,
- tree_cons (NULL_TREE, from,
- DECL_GC_OFFSET (to)));
- TREE_TYPE (rval) = TREE_TYPE (from);
- return rval;
- }
- }
-
- /* If we fall through the switch, assume we lost. */
- my_friendly_abort (45);
- /* NOTREACHED */
- return NULL_TREE;
-}
-
-/* Given the expression EXP of type `class *', return the head
- of the object pointed to by EXP. */
-tree
-build_headof (exp)
- tree exp;
-{
- tree type = TREE_TYPE (exp);
- tree vptr, offset;
-
- if (TREE_CODE (type) != POINTER_TYPE)
- {
- error ("`headof' applied to non-pointer type");
- return error_mark_node;
- }
-
- vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
- offset = build_component_ref (build_array_ref (vptr, integer_one_node),
- get_identifier (VTABLE_DELTA_NAME),
- NULL_TREE, 0);
- return build (PLUS_EXPR, class_star_type_node, exp,
- convert (integer_type_node, offset));
-}
-
-/* Given the expression EXP of type `class *', return the
- type descriptor for the object pointed to by EXP. */
-tree
-build_classof (exp)
- tree exp;
-{
- tree type = TREE_TYPE (exp);
- tree vptr;
- tree t_desc_entry;
-
- if (TREE_CODE (type) != POINTER_TYPE)
- {
- error ("`classof' applied to non-pointer type");
- return error_mark_node;
- }
-
- vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp);
- t_desc_entry = build_component_ref (build_array_ref (vptr, integer_one_node),
- get_identifier (VTABLE_PFN_NAME),
- NULL_TREE, 0);
- TREE_TYPE (t_desc_entry) = TYPE_POINTER_TO (__t_desc_type_node);
- return t_desc_entry;
-}
-
-/* Build and initialize various sorts of descriptors. Every descriptor
- node has a name associated with it (the name created by mangling).
- For this reason, we use the identifier as our access to the __*_desc
- nodes, instead of sticking them directly in the types. Otherwise we
- would burden all built-in types (and pointer types) with slots that
- we don't necessarily want to use.
-
- For each descriptor we build, we build a variable that contains
- the descriptor's information. When we need this info at runtime,
- all we need is access to these variables.
-
- Note: these constructors always return the address of the descriptor
- info, since that is simplest for their mutual interaction. */
-
-static tree
-build_generic_desc (decl, elems)
- tree decl;
- tree elems;
-{
- tree init = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, elems);
- TREE_CONSTANT (init) = 1;
- TREE_STATIC (init) = 1;
- TREE_READONLY (init) = 1;
-
- DECL_INITIAL (decl) = init;
- TREE_STATIC (decl) = 1;
- layout_decl (decl, 0);
- finish_decl (decl, init, 0, 0);
-
- return IDENTIFIER_AS_DESC (DECL_NAME (decl));
-}
-
-/* Build an initializer for a __t_desc node. So that we can take advantage
- of recursion, we accept NULL for TYPE.
- DEFINITION is greater than zero iff we must define the type descriptor
- (as opposed to merely referencing it). 1 means treat according to
- #pragma interface/#pragma implementation rules. 2 means define as
- global and public, no matter what. */
-tree
-build_t_desc (type, definition)
- tree type;
- int definition;
-{
- tree tdecl;
- tree tname, name_string;
- tree elems, fields;
- tree parents, vbases, offsets, ivars, methods, target_type;
- int method_count = 0, field_count = 0;
-
- if (type == NULL_TREE)
- return NULL_TREE;
-
- tname = build_t_desc_overload (type);
- if (IDENTIFIER_AS_DESC (tname)
- && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
- return IDENTIFIER_AS_DESC (tname);
-
- tdecl = lookup_name (tname, 0);
- if (tdecl == NULL_TREE)
- {
- tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
- DECL_EXTERNAL (tdecl) = 1;
- TREE_PUBLIC (tdecl) = 1;
- tdecl = pushdecl_top_level (tdecl);
- }
- /* If we previously defined it, return the defined result. */
- else if (definition && DECL_INITIAL (tdecl))
- return IDENTIFIER_AS_DESC (tname);
-
- if (definition)
- {
- tree taggr = type;
- /* Let T* and T& be written only when T is written (if T is an aggr).
- We do this for const, but not for volatile, since volatile
- is rare and const is not. */
- if (!TYPE_VOLATILE (taggr)
- && (TREE_CODE (taggr) == POINTER_TYPE
- || TREE_CODE (taggr) == REFERENCE_TYPE)
- && IS_AGGR_TYPE (TREE_TYPE (taggr)))
- taggr = TREE_TYPE (taggr);
-
- /* If we know that we don't need to write out this type's
- vtable, then don't write out it's dossier. Somebody
- else will take care of that. */
- if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
- {
- if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
- {
- TREE_PUBLIC (tdecl) = !(CLASSTYPE_INTERFACE_ONLY (taggr)
- || CLASSTYPE_INTERFACE_UNKNOWN (taggr));
- TREE_STATIC (tdecl) = 1;
- DECL_EXTERNAL (tdecl) = 0;
- }
- else
- {
- if (write_virtuals != 0)
- TREE_PUBLIC (tdecl) = 1;
- }
- }
- else
- {
- DECL_EXTERNAL (tdecl) = 0;
- TREE_STATIC (tdecl) = 1;
- TREE_PUBLIC (tdecl) = (definition > 1);
- }
- }
- SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
- if (!definition || DECL_EXTERNAL (tdecl))
- {
- /* That's it! */
- finish_decl (tdecl, 0, 0, 0);
- return IDENTIFIER_AS_DESC (tname);
- }
-
- /* Show that we are defining the t_desc for this type. */
- DECL_INITIAL (tdecl) = error_mark_node;
-
- parents = build_tree_list (NULL_TREE, integer_zero_node);
- vbases = build_tree_list (NULL_TREE, integer_zero_node);
- offsets = build_tree_list (NULL_TREE, integer_zero_node);
- methods = NULL_TREE;
- ivars = NULL_TREE;
-
- if (TYPE_LANG_SPECIFIC (type))
- {
- int i = CLASSTYPE_N_BASECLASSES (type);
- tree method_vec = CLASSTYPE_METHOD_VEC (type);
- tree *meth, *end;
- tree binfos = TYPE_BINFO_BASETYPES (type);
- tree vb = CLASSTYPE_VBASECLASSES (type);
-
- while (--i >= 0)
- parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
-
- while (vb)
- {
- vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
- offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
- vb = TREE_CHAIN (vb);
- }
-
- if (method_vec)
- for (meth = TREE_VEC_END (method_vec),
- end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
- if (*meth)
- {
- methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
- method_count++;
- }
- }
-
- if (IS_AGGR_TYPE (type))
- {
- for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- if (TREE_CODE (fields) == FIELD_DECL
- || TREE_CODE (fields) == VAR_DECL)
- {
- ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
- field_count++;
- }
- ivars = nreverse (ivars);
- }
-
- parents = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), parents, 0);
- vbases = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), vbases, 0);
- offsets = finish_table (0, integer_type_node, offsets, 0);
- methods = finish_table (0, __m_desc_type_node, methods, 0);
- ivars = finish_table (0, __i_desc_type_node, ivars, 0);
- if (TREE_TYPE (type))
- target_type = build_t_desc (TREE_TYPE (type), definition);
- else
- target_type = integer_zero_node;
-
- name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
-
- elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
- tree_cons (NULL_TREE,
- TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
- /* really should use bitfield initialization here. */
- tree_cons (NULL_TREE, integer_zero_node,
- tree_cons (NULL_TREE, target_type,
- tree_cons (NULL_TREE, build_int_2 (field_count, 2),
- tree_cons (NULL_TREE, build_int_2 (method_count, 2),
- tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, ivars, 0),
- tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, methods, 0),
- tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
- tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
- build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
- return build_generic_desc (tdecl, elems);
-}
-
-/* Build an initializer for a __i_desc node. */
-tree
-build_i_desc (decl)
- tree decl;
-{
- tree elems, name_string;
- tree taggr;
-
- name_string = DECL_NAME (decl);
- name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
-
- /* Now decide whether this ivar should cause it's type to get
- def'd or ref'd in this file. If the type we are looking at
- has a proxy definition, we look at the proxy (i.e., a
- `foo *' is equivalent to a `foo'). */
- taggr = TREE_TYPE (decl);
-
- if ((TREE_CODE (taggr) == POINTER_TYPE
- || TREE_CODE (taggr) == REFERENCE_TYPE)
- && TYPE_VOLATILE (taggr) == 0)
- taggr = TREE_TYPE (taggr);
-
- elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
- tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
- build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
- ! IS_AGGR_TYPE (taggr)))));
- taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
- TREE_CONSTANT (taggr) = 1;
- TREE_STATIC (taggr) = 1;
- TREE_READONLY (taggr) = 1;
- return taggr;
-}
-
-/* Build an initializer for a __m_desc node. */
-tree
-build_m_desc (decl)
- tree decl;
-{
- tree taggr, elems, name_string;
- tree parm_count, req_count, vindex, vcontext;
- tree parms;
- int p_count, r_count;
- tree parm_types = NULL_TREE;
-
- for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
- parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
- {
- taggr = TREE_VALUE (parms);
- if ((TREE_CODE (taggr) == POINTER_TYPE
- || TREE_CODE (taggr) == REFERENCE_TYPE)
- && TYPE_VOLATILE (taggr) == 0)
- taggr = TREE_TYPE (taggr);
-
- parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
- ! IS_AGGR_TYPE (taggr)),
- parm_types);
- if (TREE_PURPOSE (parms) == NULL_TREE)
- r_count++;
- }
-
- parm_types = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node),
- nreverse (parm_types), 0);
- parm_count = build_int_2 (p_count, 0);
- req_count = build_int_2 (r_count, 0);
-
- if (DECL_VINDEX (decl))
- vindex = DECL_VINDEX (decl);
- else
- vindex = integer_zero_node;
- if (DECL_CONTEXT (decl)
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
- vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
- else
- vcontext = integer_zero_node;
- name_string = DECL_NAME (decl);
- if (name_string == NULL)
- name_string = DECL_ASSEMBLER_NAME (decl);
- name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
-
- /* Now decide whether the return type of this mvar
- should cause it's type to get def'd or ref'd in this file.
- If the type we are looking at has a proxy definition,
- we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */
- taggr = TREE_TYPE (TREE_TYPE (decl));
-
- if ((TREE_CODE (taggr) == POINTER_TYPE
- || TREE_CODE (taggr) == REFERENCE_TYPE)
- && TYPE_VOLATILE (taggr) == 0)
- taggr = TREE_TYPE (taggr);
-
- elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
- tree_cons (NULL_TREE, vindex,
- tree_cons (NULL_TREE, vcontext,
- tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
- ! IS_AGGR_TYPE (taggr)),
- tree_cons (NULL_TREE, build_c_cast (TYPE_POINTER_TO (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
- tree_cons (NULL_TREE, parm_count,
- tree_cons (NULL_TREE, req_count,
- build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
-
- taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
- TREE_CONSTANT (taggr) = 1;
- TREE_STATIC (taggr) = 1;
- TREE_READONLY (taggr) = 1;
- return taggr;
-}
-
-/* Conditionally emit code to set up an unwind-protect for the
- garbage collector. If this function doesn't do anything that involves
- the garbage collector, then do nothing. Otherwise, call __gc_push
- at the beginning and __gc_pop at the end.
-
- NOTE! The __gc_pop function must operate transparently, since
- it comes where the logical return label lies. This means that
- at runtime *it* must preserve any return value registers. */
-
-void
-expand_gc_prologue_and_epilogue ()
-{
- extern tree maybe_gc_cleanup;
- struct rtx_def *last_parm_insn, *mark;
- extern struct rtx_def *get_last_insn ();
- extern struct rtx_def *get_first_nonparm_insn ();
- extern struct rtx_def *previous_insn ();
- tree action;
-
- /* If we didn't need the obstack, don't cons any space. */
- if (current_function_obstack_index == 0
- || current_function_obstack_usage == 0)
- return;
-
- mark = get_last_insn ();
- last_parm_insn = get_first_nonparm_insn ();
- if (last_parm_insn == 0) last_parm_insn = mark;
- else last_parm_insn = previous_insn (last_parm_insn);
-
- action = build_function_call (gc_push_fndecl,
- build_tree_list (NULL_TREE, size_int (++current_function_obstack_index)));
- expand_expr_stmt (action);
-
- reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
-
- /* This will be expanded as a cleanup. */
- TREE_VALUE (maybe_gc_cleanup)
- = build_function_call (gc_pop_fndecl, NULL_TREE);
-}
-
-/* Some day we'll use this function as a call-back and clean
- up all the unnecessary gc dribble that we otherwise create. */
-void
-lang_expand_end_bindings (first, last)
- struct rtx_def *first, *last;
-{
-}
-
-void
-init_gc_processing ()
-{
- tree parmtypes = hash_tree_chain (class_star_type_node,
- hash_tree_chain (integer_type_node, NULL_TREE));
- gc_protect_fndecl = define_function ("__gc_protect",
- build_function_type (class_star_type_node, parmtypes),
- NOT_BUILT_IN, 0, 0);
-
- parmtypes = hash_tree_chain (integer_type_node, NULL_TREE);
- gc_unprotect_fndecl = define_function ("__gc_unprotect",
- build_function_type (void_type_node, parmtypes),
- NOT_BUILT_IN, 0, 0);
-
- gc_push_fndecl = define_function ("__gc_push",
- TREE_TYPE (gc_unprotect_fndecl),
- NOT_BUILT_IN, 0, 0);
-
- gc_pop_fndecl = define_function ("__gc_pop",
- build_function_type (void_type_node,
- void_list_node),
- NOT_BUILT_IN, 0, 0);
- gc_nonobject = build_int_2 (0x80000000, 0);
- gc_visible = build_int_2 (0x40000000, 0);
- gc_white = integer_zero_node;
- gc_offwhite = build_int_2 (0x10000000, 0);
- gc_grey = build_int_2 (0x20000000, 0);
- gc_black = build_int_2 (0x30000000, 0);
-}
diff --git a/gnu/gcc2/cc1plus/cp-hash.h b/gnu/gcc2/cc1plus/cp-hash.h
deleted file mode 100644
index 04d03accb9d6..000000000000
--- a/gnu/gcc2/cc1plus/cp-hash.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* C code produced by gperf version 2.5 (GNU C++ version) */
-/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
-/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
-struct resword { char *name; short token; enum rid rid;};
-
-#define TOTAL_KEYWORDS 82
-#define MIN_WORD_LENGTH 2
-#define MAX_WORD_LENGTH 13
-#define MIN_HASH_VALUE 4
-#define MAX_HASH_VALUE 140
-/* maximum key range = 137, duplicates = 0 */
-
-#ifdef __GNUC__
-inline
-#endif
-static unsigned int
-hash (str, len)
- register char *str;
- register int unsigned len;
-{
- static unsigned char asso_values[] =
- {
- 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
- 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
- 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
- 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
- 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
- 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
- 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
- 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
- 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
- 141, 141, 141, 141, 141, 0, 141, 49, 3, 28,
- 28, 0, 5, 11, 32, 37, 141, 2, 24, 35,
- 51, 0, 19, 141, 23, 0, 8, 48, 0, 36,
- 0, 11, 141, 141, 141, 141, 141, 141,
- };
- register int hval = len;
-
- switch (hval)
- {
- default:
- case 7:
- hval += asso_values[str[6]];
- case 6:
- case 5:
- case 4:
- hval += asso_values[str[3]];
- case 3:
- case 2:
- case 1:
- hval += asso_values[str[0]];
- }
- return hval + asso_values[str[len - 1]];
-}
-
-#ifdef __GNUC__
-inline
-#endif
-struct resword *
-is_reserved_word (str, len)
- register char *str;
- register unsigned int len;
-{
- static struct resword wordlist[] =
- {
- {"",}, {"",}, {"",}, {"",},
- {"else", ELSE, NORID,},
- {"",}, {"",},
- {"__asm__", GCC_ASM_KEYWORD, NORID},
- {"",}, {"",},
- {"__headof__", HEADOF, NORID},
- {"sizeof", SIZEOF, NORID,},
- {"this", THIS, NORID,},
- {"__headof", HEADOF, NORID},
- {"except", EXCEPT, NORID /* Extension */,},
- {"goto", GOTO, NORID,},
- {"",},
- {"__const__", TYPE_QUAL, RID_CONST},
- {"__volatile", TYPE_QUAL, RID_VOLATILE},
- {"typeof", TYPEOF, NORID,},
- {"__volatile__", TYPE_QUAL, RID_VOLATILE},
- {"__typeof__", TYPEOF, NORID},
- {"try", TRY, NORID /* Extension */,},
- {"__const", TYPE_QUAL, RID_CONST},
- {"__typeof", TYPEOF, NORID},
- {"typedef", SCSPEC, RID_TYPEDEF,},
- {"private", VISSPEC, RID_PRIVATE,},
- {"",},
- {"raise", RAISE, NORID /* Extension */,},
- {"raises", RAISES, NORID /* Extension */,},
- {"do", DO, NORID,},
- {"for", FOR, NORID,},
- {"case", CASE, NORID,},
- {"class", AGGR, RID_CLASS,},
- {"delete", DELETE, NORID,},
- {"__classof__", CLASSOF, NORID},
- {"short", TYPESPEC, RID_SHORT,},
- {"double", TYPESPEC, RID_DOUBLE,},
- {"__classof", CLASSOF, NORID},
- {"friend", SCSPEC, RID_FRIEND,},
- {"__asm", GCC_ASM_KEYWORD, NORID},
- {"const", TYPE_QUAL, RID_CONST,},
- {"static", SCSPEC, RID_STATIC,},
- {"template", TEMPLATE, NORID,},
- {"if", IF, NORID,},
- {"classof", CLASSOF, NORID,},
- {"switch", SWITCH, NORID,},
- {"__signed__", TYPESPEC, RID_SIGNED},
- {"int", TYPESPEC, RID_INT,},
- {"throw", THROW, NORID /* Extension */,},
- {"long", TYPESPEC, RID_LONG,},
- {"",}, {"",},
- {"auto", SCSPEC, RID_AUTO,},
- {"operator", OPERATOR, NORID,},
- {"",},
- {"__attribute", ATTRIBUTE, NORID},
- {"extern", SCSPEC, RID_EXTERN,},
- {"__attribute__", ATTRIBUTE, NORID},
- {"break", BREAK, NORID,},
- {"void", TYPESPEC, RID_VOID,},
- {"",},
- {"struct", AGGR, RID_RECORD,},
- {"virtual", SCSPEC, RID_VIRTUAL,},
- {"__extension__", EXTENSION, NORID},
- {"while", WHILE, NORID,},
- {"",},
- {"float", TYPESPEC, RID_FLOAT,},
- {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,},
- {"",}, {"",},
- {"headof", HEADOF, NORID,},
- {"protected", VISSPEC, RID_PROTECTED,},
- {"__signed", TYPESPEC, RID_SIGNED},
- {"enum", ENUM, NORID,},
- {"",},
- {"all", ALL, NORID /* Extension */,},
- {"public", VISSPEC, RID_PUBLIC,},
- {"char", TYPESPEC, RID_CHAR,},
- {"reraise", RERAISE, NORID /* Extension */,},
- {"inline", SCSPEC, RID_INLINE,},
- {"volatile", TYPE_QUAL, RID_VOLATILE,},
- {"__label__", LABEL, NORID},
- {"",}, {"",},
- {"signed", TYPESPEC, RID_SIGNED,},
- {"__alignof__", ALIGNOF, NORID},
- {"asm", ASM_KEYWORD, NORID,},
- {"",},
- {"__alignof", ALIGNOF, NORID},
- {"new", NEW, NORID,},
- {"register", SCSPEC, RID_REGISTER,},
- {"continue", CONTINUE, NORID,},
- {"catch", CATCH, NORID,},
- {"",}, {"",}, {"",},
- {"exception", AGGR, RID_EXCEPTION /* Extension */,},
- {"",}, {"",},
- {"default", DEFAULT, NORID,},
- {"",}, {"",}, {"",},
- {"union", AGGR, RID_UNION,},
- {"",}, {"",}, {"",},
- {"overload", OVERLOAD, NORID,},
- {"",},
- {"__inline", SCSPEC, RID_INLINE},
- {"",},
- {"__inline__", SCSPEC, RID_INLINE},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"unsigned", TYPESPEC, RID_UNSIGNED,},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"return", RETURN, NORID,},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",},
- {"dynamic", DYNAMIC, NORID,},
- };
-
- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
- {
- register int key = hash (str, len);
-
- if (key <= MAX_HASH_VALUE && key >= 0)
- {
- register char *s = wordlist[key].name;
-
- if (*s == *str && !strcmp (str + 1, s + 1))
- return &wordlist[key];
- }
- }
- return 0;
-}
diff --git a/gnu/gcc2/cc1plus/cp-init.c b/gnu/gcc2/cc1plus/cp-init.c
deleted file mode 100644
index 38082e5689aa..000000000000
--- a/gnu/gcc2/cc1plus/cp-init.c
+++ /dev/null
@@ -1,4008 +0,0 @@
-/* Handle initialization things in C++.
- 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. */
-
-
-/* High-level class interface. */
-
-#include "config.h"
-#include "tree.h"
-#include "rtl.h"
-#include "cp-tree.h"
-#include "flags.h"
-
-#undef NULL
-#define NULL 0
-
-/* In C++, structures with well-defined constructors are initialized by
- those constructors, unasked. CURRENT_BASE_INIT_LIST
- holds a list of stmts for a BASE_INIT term in the grammar.
- This list has one element for each base class which must be
- initialized. The list elements are [basename, init], with
- type basetype. This allows the possibly anachronistic form
- (assuming d : a, b, c) "d (int a) : c(a+5), b (a-4), a (a+3)"
- where each successive term can be handed down the constructor
- line. Perhaps this was not intended. */
-tree current_base_init_list, current_member_init_list;
-
-void emit_base_init ();
-void check_base_init ();
-static void expand_aggr_vbase_init ();
-void expand_member_init ();
-void expand_aggr_init ();
-
-static void expand_aggr_init_1 ();
-static void expand_recursive_init_1 ();
-static void expand_recursive_init ();
-tree expand_vec_init ();
-tree build_vec_delete ();
-
-static void add_friend (), add_friends ();
-
-/* Cache _builtin_new and _builtin_delete exprs. */
-static tree BIN, BID;
-
-static tree minus_one;
-
-/* Set up local variable for this file. MUST BE CALLED AFTER
- INIT_DECL_PROCESSING. */
-
-tree BI_header_type, BI_header_size;
-
-void init_init_processing ()
-{
- tree op_id;
- tree fields[2];
-
- /* Define implicit `operator new' and `operator delete' functions. */
- BIN = default_conversion (TREE_VALUE (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) NEW_EXPR])));
- TREE_USED (TREE_OPERAND (BIN, 0)) = 0;
- BID = default_conversion (TREE_VALUE (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR])));
- TREE_USED (TREE_OPERAND (BID, 0)) = 0;
- minus_one = build_int_2 (-1, -1);
-
- op_id = ansi_opname[(int) NEW_EXPR];
- IDENTIFIER_GLOBAL_VALUE (op_id) = BIN;
- op_id = ansi_opname[(int) DELETE_EXPR];
- IDENTIFIER_GLOBAL_VALUE (op_id) = BID;
-
- /* Define the structure that holds header information for
- arrays allocated via operator new. */
- BI_header_type = make_lang_type (RECORD_TYPE);
- fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("nelts"),
- sizetype);
- fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("ptr_2comp"),
- ptr_type_node);
- finish_builtin_type (BI_header_type, "__new_cookie", fields, 1, double_type_node);
- BI_header_size = size_in_bytes (BI_header_type);
-}
-
-/* Recursive subroutine of emit_base_init. For main type T,
- recursively initialize the vfields of the base type PARENT.
- RECURSE is non-zero when this function is being called
- recursively. */
-
-static void
-init_vfields (t, parent, recurse)
- tree t, parent;
- int recurse;
-{
- tree vfields;
-
- /* Initialize all the virtual function table fields that
- do not come from virtual base classes. */
- vfields = CLASSTYPE_VFIELDS (parent);
- while (vfields)
- {
- tree basetype = VF_DERIVED_VALUE (vfields)
- ? TYPE_MAIN_VARIANT (VF_DERIVED_VALUE (vfields))
- : VF_BASETYPE_VALUE (vfields);
-
- /* If the vtable installed by the constructor was not
- the right one, fix that here. */
- if (TREE_ADDRESSABLE (vfields)
- && CLASSTYPE_NEEDS_VIRTUAL_REINIT (basetype)
- && (recurse > 0
- || TYPE_HAS_CONSTRUCTOR (basetype)
- /* BASE_INIT_LIST has already initialized the immediate basetypes. */
- || get_base_distance (basetype, t, 0, (tree *) 0) > 1))
- {
- tree binfo = binfo_value (basetype, t);
- if ((recurse != 0 && (binfo != binfo_value (basetype, parent)))
- || (recurse == 0
- && BINFO_VTABLE (binfo) != TYPE_BINFO_VTABLE (basetype)))
- {
- tree ptr = convert_pointer_to (binfo, current_class_decl);
- expand_expr_stmt (build_virtual_init (TYPE_BINFO (t), binfo, ptr));
- }
- init_vfields (t, basetype, recurse+1);
- }
- vfields = TREE_CHAIN (vfields);
- }
-}
-
-/* Perform whatever initialization have yet to be done on the
- base class of the class variable. These actions are in
- the global variable CURRENT_BASE_INIT_LIST. Such an
- action could be NULL_TREE, meaning that the user has explicitly
- called the base class constructor with no arguments.
-
- If there is a need for a call to a constructor, we
- must surround that call with a pushlevel/poplevel pair,
- since we are technically at the PARM level of scope.
-
- Argument IMMEDIATELY, if zero, forces a new sequence to be generated
- to contain these new insns, so it can be emitted later. This sequence
- is saved in the global variable BASE_INIT_INSNS. Otherwise, the insns
- are emitted into the current sequence.
-
- Note that emit_base_init does *not* initialize virtual
- base classes. That is done specially, elsewhere. */
-
-void
-emit_base_init (t, immediately)
- tree t;
- int immediately;
-{
- extern tree in_charge_identifier;
-
- tree member, decl, vbases;
- tree init_list;
- int pass, start;
- tree t_binfo = TYPE_BINFO (t);
- tree binfos = BINFO_BASETYPES (t_binfo);
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- tree fields_to_unmark = NULL_TREE;
-
- if (! immediately)
- {
- do_pending_stack_adjust ();
- start_sequence ();
- }
-
- if (write_symbols == NO_DEBUG)
- /* As a matter of principle, `start_sequence' should do this. */
- emit_note (0, -1);
- else
- /* Always emit a line number note so we can step into constructors. */
- emit_line_note_force (DECL_SOURCE_FILE (current_function_decl),
- DECL_SOURCE_LINE (current_function_decl));
-
- /* In this case, we always need IN_CHARGE_NODE, because we have
- to know whether to deallocate or not before exiting. */
- if (flag_handle_exceptions == 2
- && lookup_name (in_charge_identifier, 0) == NULL_TREE)
- {
- tree in_charge_node = pushdecl (build_decl (VAR_DECL, in_charge_identifier,
- integer_type_node));
- store_init_value (in_charge_node, build (EQ_EXPR, integer_type_node,
- current_class_decl,
- integer_zero_node));
- expand_decl (in_charge_node);
- expand_decl_init (in_charge_node);
- }
-
- start = ! TYPE_USES_VIRTUAL_BASECLASSES (t);
- for (pass = start; pass < 2; pass++)
- {
- tree vbase_init_list = NULL_TREE;
-
- for (init_list = current_base_init_list; init_list;
- init_list = TREE_CHAIN (init_list))
- {
- tree basename = TREE_PURPOSE (init_list);
- tree binfo;
- tree init = TREE_VALUE (init_list);
-
- if (basename == NULL_TREE)
- {
- /* Initializer for single base class. Must not
- use multiple inheritance or this is ambiguous. */
- switch (n_baseclasses)
- {
- case 0:
- error ("type `%s' does not have a base class to initialize",
- IDENTIFIER_POINTER (current_class_name));
- return;
- case 1:
- break;
- default:
- error ("unnamed initializer ambiguous for type `%s' which uses multiple inheritance", IDENTIFIER_POINTER (current_class_name));
- return;
- }
- binfo = TREE_VEC_ELT (binfos, 0);
- }
- else if (is_aggr_typedef (basename, 1))
- {
- binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t);
- if (binfo == NULL_TREE)
- continue;
-
- /* Virtual base classes are special cases. Their initializers
- are recorded with this constructor, and they are used when
- this constructor is the top-level constructor called. */
- if (! TREE_VIA_VIRTUAL (binfo))
- {
- /* Otherwise, if it is not an immediate base class, complain. */
- for (i = n_baseclasses-1; i >= 0; i--)
- if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
- break;
- if (i < 0)
- {
- error ("type `%s' is not an immediate base class of type `%s'",
- IDENTIFIER_POINTER (basename),
- IDENTIFIER_POINTER (current_class_name));
- continue;
- }
- }
- }
- else
- continue;
-
- /* The base initialization list goes up to the first
- base class which can actually use it. */
-
- if (pass == start)
- {
- char *msgp = (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))
- ? "cannot pass initialization up to class `%s'" : 0;
-
- while (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo))
- && BINFO_BASETYPES (binfo) != NULL_TREE
- && TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 1)
- {
- /* ?? This should be fixed in RENO by forcing
- default constructors to exist. */
- SET_BINFO_BASEINIT_MARKED (binfo);
- binfo = BINFO_BASETYPE (binfo, 0);
- }
-
- if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))
- {
- if (msgp)
- {
- if (pedantic)
- error_with_aggr_type (binfo, msgp);
- else
- msgp = 0;
- }
- }
- else
- {
- msgp = "no constructor found for initialization of `%s'";
- error (msgp, IDENTIFIER_POINTER (basename));
- }
-
- if (BINFO_BASEINIT_MARKED (binfo))
- {
- msgp = "class `%s' initializer already specified";
- error (msgp, IDENTIFIER_POINTER (basename));
- }
- if (msgp)
- continue;
-
- SET_BINFO_BASEINIT_MARKED (binfo);
- if (TREE_VIA_VIRTUAL (binfo))
- {
- vbase_init_list = tree_cons (init, BINFO_TYPE (binfo),
- vbase_init_list);
- continue;
- }
- if (pass == 0)
- continue;
- }
- else if (TREE_VIA_VIRTUAL (binfo))
- continue;
-
- member = convert_pointer_to (binfo, current_class_decl);
- expand_aggr_init_1 (t_binfo, 0,
- build_indirect_ref (member, 0), init,
- BINFO_OFFSET_ZEROP (binfo),
- LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN);
- if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
- {
- cplus_expand_start_try (1);
- push_exception_cleanup (member);
- }
- }
-
- if (pass == 0)
- {
- tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
- tree vbases;
-
- if (DECL_NAME (current_function_decl) == NULL_TREE
- && TREE_CHAIN (first_arg) != NULL_TREE)
- {
- /* If there are virtual baseclasses without initialization
- specified, and this is a default X(X&) constructor,
- build the initialization list so that each virtual baseclass
- of the new object is initialized from the virtual baseclass
- of the incoming arg. */
- tree init_arg = build_unary_op (ADDR_EXPR, TREE_CHAIN (first_arg), 0);
- for (vbases = CLASSTYPE_VBASECLASSES (t);
- vbases; vbases = TREE_CHAIN (vbases))
- {
- if (BINFO_BASEINIT_MARKED (vbases) == 0)
- {
- member = convert_pointer_to (vbases, init_arg);
- if (member == init_arg)
- member = TREE_CHAIN (first_arg);
- else
- TREE_TYPE (member) = build_reference_type (BINFO_TYPE (vbases));
- vbase_init_list = tree_cons (convert_from_reference (member),
- vbases, vbase_init_list);
- SET_BINFO_BASEINIT_MARKED (vbases);
- }
- }
- }
- expand_start_cond (first_arg, 0);
- expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,
- vbase_init_list);
- expand_expr_stmt (build_vbase_vtables_init (t_binfo, t_binfo,
- C_C_D, current_class_decl, 1));
- expand_end_cond ();
- }
- }
- current_base_init_list = NULL_TREE;
-
- /* Now, perform default initialization of all base classes which
- have not yet been initialized, and unmark baseclasses which
- have been initialized. */
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base = current_class_decl;
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
- {
- if (! TREE_VIA_VIRTUAL (base_binfo)
- && ! BINFO_BASEINIT_MARKED (base_binfo))
- {
- tree ref;
-
- if (BINFO_OFFSET_ZEROP (base_binfo))
- base = build1 (NOP_EXPR,
- TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
- current_class_decl);
- else
- base = build (PLUS_EXPR,
- TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
- current_class_decl, BINFO_OFFSET (base_binfo));
-
- ref = build_indirect_ref (base, 0);
- expand_aggr_init_1 (t_binfo, 0, ref, NULL_TREE,
- BINFO_OFFSET_ZEROP (base_binfo),
- LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN);
- if (flag_handle_exceptions == 2
- && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
- {
- cplus_expand_start_try (1);
- push_exception_cleanup (base);
- }
- }
- }
- CLEAR_BINFO_BASEINIT_MARKED (base_binfo);
- }
- for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
- CLEAR_BINFO_BASEINIT_MARKED (vbases);
-
- /* Initialize all the virtual function table fields that
- do not come from virtual base classes. */
- init_vfields (t, t, 0);
-
- if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (t))
- expand_expr_stmt (build_virtual_init (TYPE_BINFO (t), t,
- current_class_decl));
-
- /* Members we through expand_member_init. We initialize all the members
- needing initialization that did not get it so far. */
- for (; current_member_init_list;
- current_member_init_list = TREE_CHAIN (current_member_init_list))
- {
- tree name = TREE_PURPOSE (current_member_init_list);
- tree init = TREE_VALUE (current_member_init_list);
- tree field = (TREE_CODE (name) == COMPONENT_REF
- ? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name));
- tree type;
-
- /* If one member shadows another, get the outermost one. */
- if (TREE_CODE (field) == TREE_LIST)
- {
- field = TREE_VALUE (field);
- if (decl_type_context (field) != current_class_type)
- error ("field `%s' not in immediate context");
- }
-
- type = TREE_TYPE (field);
-
- if (TREE_STATIC (field))
- {
- error_with_aggr_type (DECL_FIELD_CONTEXT (field),
- "field `%s::%s' is static; only point of initialization is its declaration", IDENTIFIER_POINTER (name));
- continue;
- }
-
- if (DECL_NAME (field))
- {
- if (TREE_HAS_CONSTRUCTOR (field))
- error ("multiple initializations given for member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- }
-
- /* Mark this node as having been initialized. */
- TREE_HAS_CONSTRUCTOR (field) = 1;
- if (DECL_FIELD_CONTEXT (field) != t)
- fields_to_unmark = tree_cons (NULL_TREE, field, fields_to_unmark);
-
- if (TREE_CODE (name) == COMPONENT_REF)
- {
- /* Initialization of anonymous union. */
- expand_assignment (name, init, 0, 0);
- continue;
- }
- decl = build_component_ref (C_C_D, name, 0, 1);
-
- if (TYPE_NEEDS_CONSTRUCTING (type))
- {
- if (TREE_CODE (type) == ARRAY_TYPE
- && init != NULL_TREE
- && TREE_CHAIN (init) == NULL_TREE
- && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
- {
- /* Initialization of one array from another. */
- expand_vec_init (TREE_OPERAND (decl, 1), decl,
- array_type_nelts (type), TREE_VALUE (init), 1);
- }
- else
- expand_aggr_init (decl, init, 0);
- }
- else
- {
- if (init == NULL_TREE)
- {
- error ("types without constructors must have complete initializers");
- init = error_mark_node;
- }
- else if (TREE_CHAIN (init))
- {
- warning ("initializer list treated as compound expression");
- init = build_compound_expr (init);
- }
- else
- init = TREE_VALUE (init);
-
- expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
- }
- if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type))
- {
- cplus_expand_start_try (1);
- push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0));
- }
- }
-
- for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
- {
- /* All we care about is this unique member. It contains
- all the information we need to know, and that right early. */
- tree type = TREE_TYPE (member);
- tree init = TREE_HAS_CONSTRUCTOR (member)
- ? error_mark_node : DECL_INITIAL (member);
-
- /* Unmark this field. If it is from an anonymous union,
- then unmark the field recursively. */
- TREE_HAS_CONSTRUCTOR (member) = 0;
- if (TREE_ANON_UNION_ELEM (member))
- emit_base_init (TREE_TYPE (member), 1);
-
- /* Member had explicit initializer. */
- if (init == error_mark_node)
- continue;
-
- if (TREE_CODE (member) != FIELD_DECL)
- continue;
-
- if (type == error_mark_node)
- continue;
-
- if (TYPE_NEEDS_CONSTRUCTING (type))
- {
- if (init)
- init = build_tree_list (NULL_TREE, init);
- decl = build_component_ref (C_C_D, DECL_NAME (member), 0, 0);
- expand_aggr_init (decl, init, 0);
- }
- else
- {
- if (init)
- {
- decl = build_component_ref (C_C_D, DECL_NAME (member), 0, 0);
- expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
- }
- else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE)
- warning ("uninitialized reference member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (member)));
- }
- if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type))
- {
- cplus_expand_start_try (1);
- push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0));
- }
- }
- /* Unmark fields which are initialized for the base class. */
- while (fields_to_unmark)
- {
- TREE_HAS_CONSTRUCTOR (TREE_VALUE (fields_to_unmark)) = 0;
- fields_to_unmark = TREE_CHAIN (fields_to_unmark);
- }
-
- /* It is possible for the initializers to need cleanups.
- Expand those cleanups now that all the initialization
- has been done. */
- expand_cleanups_to (NULL_TREE);
-
- if (! immediately)
- {
- extern rtx base_init_insns;
-
- do_pending_stack_adjust ();
- my_friendly_assert (base_init_insns == 0, 207);
- base_init_insns = get_insns ();
- end_sequence ();
- }
-
- /* All the implicit try blocks we built up will be zapped
- when we come to a real binding contour boundary. */
-}
-
-/* Check that all fields are properly initialized after
- an assignment to `this'. */
-void
-check_base_init (t)
- tree t;
-{
- tree member;
- for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
- if (DECL_NAME (member) && TREE_USED (member))
- error ("field `%s' used before initialized (after assignment to `this')",
- IDENTIFIER_POINTER (DECL_NAME (member)));
-}
-
-/* This code sets up the virtual function tables appropriate for
- the pointer DECL. It is a one-ply initialization.
-
- BINFO is the exact type that DECL is supposed to be. In
- multiple inheritance, this might mean "C's A" if C : A, B. */
-tree
-build_virtual_init (main_binfo, binfo, decl)
- tree main_binfo, binfo;
- tree decl;
-{
- tree type;
- tree vtbl, vtbl_ptr;
- tree vtype;
-
- if (TREE_CODE (binfo) == TREE_VEC)
- type = BINFO_TYPE (binfo);
- else if (TREE_CODE (binfo) == RECORD_TYPE)
- {
- type = binfo;
- binfo = TYPE_BINFO (type);
- }
- else
- my_friendly_abort (46);
-
- vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));
-#if 0
- /* This code suggests that it's time to rewrite how we handle
- replicated baseclasses in G++. */
- if (get_base_distance (vtype, TREE_TYPE (TREE_TYPE (decl)),
- 0, (tree *) 0) == -2)
- {
- tree binfos = TYPE_BINFO_BASETYPES (TREE_TYPE (TREE_TYPE (decl)));
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- tree result = NULL_TREE;
-
- for (i = n_baselinks-1; i >= 0; i--)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree this_decl;
-
- if (get_base_distance (vtype, BINFO_TYPE (base_binfo), 0, 0) == -1)
- continue;
-
- if (TREE_VIA_VIRTUAL (base_binfo))
- this_decl = build_vbase_pointer (build_indirect_ref (decl), BINFO_TYPE (base_binfo));
- else if (BINFO_OFFSET_ZEROP (base_binfo))
- this_decl = build1 (NOP_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
- decl);
- else
- this_decl = build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
- decl, BINFO_OFFSET (base_binfo));
- result = tree_cons (NULL_TREE, build_virtual_init (main_binfo, base_binfo, this_decl), result);
- }
- return build_compound_expr (result);
- }
-#endif
-
- {
-#if 1
-#if 1
- vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
-#else
- /* The below does not work when we have to step through the
- vfield, on our way down to the most base class for the
- vfield. */
- vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)),
- BINFO_TYPE (main_binfo)));
-#endif
-#else
- my_friendly_assert (BINFO_TYPE (main_binfo) == BINFO_TYPE (binfo), 208);
- vtbl = BINFO_VTABLE (main_binfo);
-#endif /* 1 */
- assemble_external (vtbl);
- TREE_USED (vtbl) = 1;
- vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl);
- }
- decl = convert_pointer_to (vtype, decl);
- vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, 0), vtype);
- if (vtbl_ptr == error_mark_node)
- return error_mark_node;
-
- /* Have to convert VTBL since array sizes may be different. */
- return build_modify_expr (vtbl_ptr, NOP_EXPR,
- convert (TREE_TYPE (vtbl_ptr), vtbl));
-}
-
-/* Subroutine of `expand_aggr_vbase_init'.
- BINFO is the binfo of the type that is being initialized.
- INIT_LIST is the list of initializers for the virtual baseclass. */
-static void
-expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
- tree binfo, exp, addr, init_list;
-{
- tree init = value_member (BINFO_TYPE (binfo), init_list);
- tree ref = build_indirect_ref (addr, 0);
- if (init)
- init = TREE_PURPOSE (init);
- /* Call constructors, but don't set up vtables. */
- expand_aggr_init_1 (binfo, exp, ref, init, 0,
- LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY);
- CLEAR_BINFO_VBASE_INIT_MARKED (binfo);
-}
-
-/* Initialize this object's virtual base class pointers. This must be
- done only at the top-level of the object being constructed.
-
- INIT_LIST is list of initialization for constructor to perform. */
-static void
-expand_aggr_vbase_init (binfo, exp, addr, init_list)
- tree binfo;
- tree exp;
- tree addr;
- tree init_list;
-{
- tree type = BINFO_TYPE (binfo);
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- {
- tree result = init_vbase_pointers (type, addr);
- tree vbases;
-
- if (result)
- expand_expr_stmt (build_compound_expr (result));
-
- /* Mark everything as having an initializer
- (either explicit or default). */
- for (vbases = CLASSTYPE_VBASECLASSES (type);
- vbases; vbases = TREE_CHAIN (vbases))
- SET_BINFO_VBASE_INIT_MARKED (vbases);
-
- /* First, initialize baseclasses which could be baseclasses
- for other virtual baseclasses. */
- for (vbases = CLASSTYPE_VBASECLASSES (type);
- vbases; vbases = TREE_CHAIN (vbases))
- /* Don't initialize twice. */
- if (BINFO_VBASE_INIT_MARKED (vbases))
- {
- tree tmp = result;
-
- while (BINFO_TYPE (vbases) != BINFO_TYPE (TREE_PURPOSE (tmp)))
- tmp = TREE_CHAIN (tmp);
- expand_aggr_vbase_init_1 (vbases, exp,
- TREE_OPERAND (TREE_VALUE (tmp), 0),
- init_list);
- }
-
- /* Now initialize the baseclasses which don't have virtual baseclasses. */
- for (; result; result = TREE_CHAIN (result))
- /* Don't initialize twice. */
- if (BINFO_VBASE_INIT_MARKED (TREE_PURPOSE (result)))
- {
- my_friendly_abort (47);
- expand_aggr_vbase_init_1 (TREE_PURPOSE (result), exp,
- TREE_OPERAND (TREE_VALUE (result), 0),
- init_list);
- }
- }
-}
-
-/* Subroutine to perform parser actions for member initialization.
- S_ID is the scoped identifier.
- NAME is the name of the member.
- INIT is the initializer, or `void_type_node' if none. */
-void
-do_member_init (s_id, name, init)
- tree s_id, name, init;
-{
- tree binfo, base;
-
- if (current_class_type == NULL_TREE
- || ! is_aggr_typedef (s_id, 1))
- return;
- binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id),
- current_class_type, 1);
- if (binfo == error_mark_node)
- return;
- if (binfo == 0)
- {
- error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type);
- return;
- }
-
- base = convert_pointer_to (binfo, current_class_decl);
- expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
-}
-
-/* Function to give error message if member initialization specification
- is erroneous. FIELD is the member we decided to initialize.
- TYPE is the type for which the initialization is being performed.
- FIELD must be a member of TYPE, or the base type from which FIELD
- comes must not need a constructor.
-
- MEMBER_NAME is the name of the member. */
-
-static int
-member_init_ok_or_else (field, type, member_name)
- tree field;
- tree type;
- char *member_name;
-{
- if (field == error_mark_node) return 0;
- if (field == NULL_TREE)
- {
- error_with_aggr_type (type, "class `%s' does not have any field named `%s'",
- member_name);
- return 0;
- }
- if (DECL_CONTEXT (field) != type
- && TYPE_NEEDS_CONSTRUCTOR (DECL_CONTEXT (field)))
- {
- error ("member `%s' comes from base class needing constructor", member_name);
- return 0;
- }
- return 1;
-}
-
-/* If NAME is a viable field name for the aggregate DECL,
- and PARMS is a viable parameter list, then expand an _EXPR
- which describes this initialization.
-
- Note that we do not need to chase through the class's base classes
- to look for NAME, because if it's in that list, it will be handled
- by the constructor for that base class.
-
- We do not yet have a fixed-point finder to instantiate types
- being fed to overloaded constructors. If there is a unique
- constructor, then argument types can be got from that one.
-
- If INIT is non-NULL, then it the initialization should
- be placed in `current_base_init_list', where it will be processed
- by `emit_base_init'. */
-void
-expand_member_init (exp, name, init)
- tree exp, name, init;
-{
- extern tree ptr_type_node; /* should be in tree.h */
-
- tree basetype = NULL_TREE, field;
- tree parm;
- tree rval, type;
- tree actual_name;
-
- if (exp == NULL_TREE)
- return; /* complain about this later */
-
- type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
-
- if (name == NULL_TREE && IS_AGGR_TYPE (type))
- switch (CLASSTYPE_N_BASECLASSES (type))
- {
- case 0:
- error ("base class initializer specified, but no base class to initialize");
- return;
- case 1:
- basetype = TYPE_BINFO_BASETYPE (type, 0);
- break;
- default:
- error ("initializer for unnamed base class ambiguous");
- error_with_aggr_type (type, "(type `%s' uses multiple inheritance)");
- return;
- }
-
- if (init)
- {
- /* The grammar should not allow fields which have names
- that are TYPENAMEs. Therefore, if the field has
- a non-NULL TREE_TYPE, we may assume that this is an
- attempt to initialize a base class member of the current
- type. Otherwise, it is an attempt to initialize a
- member field. */
-
- if (init == void_type_node)
- init = NULL_TREE;
-
- if (name == NULL_TREE || IDENTIFIER_HAS_TYPE_VALUE (name))
- {
- tree base_init;
-
- if (name == NULL_TREE)
- if (basetype)
- name = TYPE_IDENTIFIER (basetype);
- else
- {
- error ("no base class to initialize");
- return;
- }
- else
- {
- basetype = IDENTIFIER_TYPE_VALUE (name);
- if (basetype != type
- && ! binfo_member (basetype, TYPE_BINFO (type))
- && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
- {
- if (IDENTIFIER_CLASS_VALUE (name))
- goto try_member;
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- error ("type `%s' is not an immediate or virtual basetype for `%s'",
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (type));
- else
- error ("type `%s' is not an immediate basetype for `%s'",
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (type));
- return;
- }
- }
-
- if (purpose_member (name, current_base_init_list))
- {
- error ("base class `%s' already initialized",
- IDENTIFIER_POINTER (name));
- return;
- }
-
- base_init = build_tree_list (name, init);
- TREE_TYPE (base_init) = basetype;
- current_base_init_list = chainon (current_base_init_list, base_init);
- }
- else
- {
- tree member_init;
-
- try_member:
- field = lookup_field (type, name, 1, 0);
-
- if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
- return;
-
- if (purpose_member (name, current_member_init_list))
- {
- error ("field `%s' already initialized", IDENTIFIER_POINTER (name));
- return;
- }
-
- member_init = build_tree_list (name, init);
- TREE_TYPE (member_init) = TREE_TYPE (field);
- current_member_init_list = chainon (current_member_init_list, member_init);
- }
- return;
- }
- else if (name == NULL_TREE)
- {
- compiler_error ("expand_member_init: name == NULL_TREE");
- return;
- }
-
- basetype = type;
- field = lookup_field (basetype, name, 0, 0);
-
- if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name)))
- return;
-
- /* now see if there is a constructor for this type
- which will take these args. */
-
- if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field)))
- {
- tree parmtypes, fndecl;
-
- if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
- {
- /* just know that we've seen something for this node */
- DECL_INITIAL (exp) = error_mark_node;
- TREE_USED (exp) = 1;
- }
- type = TYPE_MAIN_VARIANT (TREE_TYPE (field));
- actual_name = TYPE_IDENTIFIER (type);
- parm = build_component_ref (exp, name, 0, 0);
-
- /* Now get to the constructor. */
- fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
- /* Get past destructor, if any. */
- if (TYPE_HAS_DESTRUCTOR (type))
- fndecl = DECL_CHAIN (fndecl);
-
- if (fndecl)
- my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209);
-
- /* If the field is unique, we can use the parameter
- types to guide possible type instantiation. */
- if (DECL_CHAIN (fndecl) == NULL_TREE)
- {
- /* There was a confusion here between
- FIELD and FNDECL. The following code
- should be correct, but abort is here
- to make sure. */
- my_friendly_abort (48);
- parmtypes = FUNCTION_ARG_CHAIN (fndecl);
- }
- else
- {
- parmtypes = NULL_TREE;
- fndecl = NULL_TREE;
- }
-
- init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL);
- if (init == NULL_TREE || TREE_TYPE (init) != error_mark_node)
- rval = build_method_call (NULL_TREE, actual_name, init, NULL_TREE, LOOKUP_NORMAL);
- else
- return;
-
- if (rval != error_mark_node)
- {
- /* Now, fill in the first parm with our guy */
- TREE_VALUE (TREE_OPERAND (rval, 1))
- = build_unary_op (ADDR_EXPR, parm, 0);
- TREE_TYPE (rval) = ptr_type_node;
- TREE_SIDE_EFFECTS (rval) = 1;
- }
- }
- else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
- {
- parm = build_component_ref (exp, name, 0, 0);
- expand_aggr_init (parm, NULL_TREE, 0);
- rval = error_mark_node;
- }
-
- /* Now initialize the member. It does not have to
- be of aggregate type to receive initialization. */
- if (rval != error_mark_node)
- expand_expr_stmt (rval);
-}
-
-/* This is like `expand_member_init', only it stores one aggregate
- value into another.
-
- INIT comes in two flavors: it is either a value which
- is to be stored in EXP, or it is a parameter list
- to go to a constructor, which will operate on EXP.
- If `init' is a CONSTRUCTOR, then we emit a warning message,
- explaining that such initializations are illegal.
-
- ALIAS_THIS is nonzero iff we are initializing something which is
- essentially an alias for C_C_D. In this case, the base constructor
- may move it on us, and we must keep track of such deviations.
-
- If INIT resolves to a CALL_EXPR which happens to return
- something of the type we are looking for, then we know
- that we can safely use that call to perform the
- initialization.
-
- The virtual function table pointer cannot be set up here, because
- we do not really know its type.
-
- Virtual baseclass pointers are also set up here.
-
- This never calls operator=().
-
- When initializing, nothing is CONST.
-
- A default copy constructor may have to be used to perform the
- initialization.
-
- A constructor or a conversion operator may have to be used to
- perform the initialization, but not both, as it would be ambiguous.
- */
-
-void
-expand_aggr_init (exp, init, alias_this)
- tree exp, init;
- int alias_this;
-{
- tree type = TREE_TYPE (exp);
- int was_const = TREE_READONLY (exp);
-
- if (init == error_mark_node)
- return;
-
- TREE_READONLY (exp) = 0;
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- /* Must arrange to initialize each element of EXP
- from elements of INIT. */
- int was_const_elts = TYPE_READONLY (TREE_TYPE (type));
- tree itype = init ? TREE_TYPE (init) : NULL_TREE;
- if (was_const_elts)
- {
- tree atype = build_cplus_array_type (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
- TYPE_DOMAIN (type));
- if (init && (TREE_TYPE (exp) == TREE_TYPE (init)))
- TREE_TYPE (init) = atype;
- TREE_TYPE (exp) = atype;
- }
- expand_vec_init (exp, exp, array_type_nelts (type), init,
- init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1));
- TREE_READONLY (exp) = was_const;
- TREE_TYPE (exp) = type;
- if (init) TREE_TYPE (init) = itype;
- return;
- }
-
- if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
- /* just know that we've seen something for this node */
- TREE_USED (exp) = 1;
-
- /* If initializing from a GNU C CONSTRUCTOR, consider the elts in the
- constructor as parameters to an implicit GNU C++ constructor. */
- if (init && TREE_CODE (init) == CONSTRUCTOR
- && TYPE_HAS_CONSTRUCTOR (type)
- && TREE_TYPE (init) == type)
- init = CONSTRUCTOR_ELTS (init);
- expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
- init, alias_this, LOOKUP_NORMAL);
- TREE_READONLY (exp) = was_const;
-}
-
-static void
-expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
- tree binfo;
- tree true_exp, exp;
- tree type;
- tree init;
- int alias_this;
- int flags;
-{
- /* It fails because there may not be a constructor which takes
- its own type as the first (or only parameter), but which does
- take other types via a conversion. So, if the thing initializing
- the expression is a unit element of type X, first try X(X&),
- followed by initialization by X. If neither of these work
- out, then look hard. */
- tree rval;
- tree parms;
- int xxref_init_possible;
-
- if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
- {
- parms = init;
- if (parms) init = TREE_VALUE (parms);
- }
- else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init))
- {
- rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
- expand_expr_stmt (rval);
- return;
- }
- else parms = build_tree_list (NULL_TREE, init);
-
- if (TYPE_HAS_INIT_REF (type)
- || init == NULL_TREE
- || TREE_CHAIN (parms) != NULL_TREE)
- xxref_init_possible = 0;
- else
- {
- xxref_init_possible = LOOKUP_SPECULATIVELY;
- flags &= ~LOOKUP_COMPLAIN;
- }
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- {
- if (true_exp == exp)
- parms = tree_cons (NULL_TREE, integer_one_node, parms);
- else
- parms = tree_cons (NULL_TREE, integer_zero_node, parms);
- flags |= LOOKUP_HAS_IN_CHARGE;
- }
-
- rval = build_method_call (exp, constructor_name (type),
- parms, binfo, flags|xxref_init_possible);
- if (rval == NULL_TREE && xxref_init_possible)
- {
- /* It is an error to implement a default copy constructor if
- (see ARM 12.8 for details) ... one case being if another
- copy constructor already exists. */
- tree init_type = TREE_TYPE (init);
- if (TREE_CODE (init_type) == REFERENCE_TYPE)
- init_type = TREE_TYPE (init_type);
- if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type)
- || (IS_AGGR_TYPE (init_type)
- && UNIQUELY_DERIVED_FROM_P (type, init_type)))
- {
- if (type == BINFO_TYPE (binfo)
- && TYPE_USES_VIRTUAL_BASECLASSES (type))
- {
- tree addr = build_unary_op (ADDR_EXPR, exp, 0);
- expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE);
-
- expand_expr_stmt (build_vbase_vtables_init (binfo, binfo,
- exp, addr, 1));
- }
- expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
- return;
- }
- else
- rval = build_method_call (exp, constructor_name (type), parms,
- binfo, flags);
- }
-
- /* Private, protected, or otherwise unavailable. */
- if (rval == error_mark_node && (flags&LOOKUP_COMPLAIN))
- error_with_aggr_type (binfo, "in base initialization for class `%s'");
- /* A valid initialization using constructor. */
- else if (rval != error_mark_node && rval != NULL_TREE)
- {
- /* p. 222: if the base class assigns to `this', then that
- value is used in the derived class. */
- if ((flag_this_is_variable & 1) && alias_this)
- {
- TREE_TYPE (rval) = TREE_TYPE (current_class_decl);
- expand_assignment (current_class_decl, rval, 0, 0);
- }
- else
- expand_expr_stmt (rval);
- }
- else if (parms && TREE_CHAIN (parms) == NULL_TREE)
- {
- /* If we are initializing one aggregate value
- from another, and though there are constructors,
- and none accept the initializer, just do a bitwise
- copy.
-
- The above sounds wrong, ``If a class has any copy
- constructor defined, the default copy constructor will
- not be generated.'' 12.8 Copying Class Objects (mrs)
-
- @@ This should reject initializer which a constructor
- @@ rejected on visibility gounds, but there is
- @@ no way right now to recognize that case with
- @@ just `error_mark_node'. */
- tree itype;
- init = TREE_VALUE (parms);
- itype = TREE_TYPE (init);
- if (TREE_CODE (itype) == REFERENCE_TYPE)
- {
- init = convert_from_reference (init);
- itype = TREE_TYPE (init);
- }
- itype = TYPE_MAIN_VARIANT (itype);
-
- /* This is currently how the default X(X&) constructor
- is implemented. */
- if (comptypes (TYPE_MAIN_VARIANT (type), itype, 0))
- {
-#if 0
- warning ("bitwise copy in initialization of type `%s'",
- TYPE_NAME_STRING (type));
-#endif
- rval = build (INIT_EXPR, type, exp, init);
- expand_expr_stmt (rval);
- }
- else
- {
- error_with_aggr_type (binfo, "in base initialization for class `%s',");
- error_with_aggr_type (type, "invalid initializer to constructor for type `%s'");
- return;
- }
- }
- else
- {
- if (init == NULL_TREE)
- my_friendly_assert (parms == NULL_TREE, 210);
- if (parms == NULL_TREE && TREE_VIA_VIRTUAL (binfo))
- error_with_aggr_type (binfo, "virtual baseclass `%s' does not have default initializer");
- else
- {
- error_with_aggr_type (binfo, "in base initialization for class `%s',");
- /* This will make an error message for us. */
- build_method_call (exp, constructor_name (type), parms, binfo,
- (TYPE_USES_VIRTUAL_BASECLASSES (type)
- ? LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE
- : LOOKUP_NORMAL));
- }
- return;
- }
- /* Constructor has been called, but vtables may be for TYPE
- rather than for FOR_TYPE. */
-}
-
-/* This function is responsible for initializing EXP with INIT
- (if any).
-
- BINFO is the binfo of the type for who we are performing the
- initialization. For example, if W is a virtual base class of A and B,
- and C : A, B.
- If we are initializing B, then W must contain B's W vtable, whereas
- were we initializing C, W must contain C's W vtable.
-
- TRUE_EXP is nonzero if it is the true expression being initialized.
- In this case, it may be EXP, or may just contain EXP. The reason we
- need this is because if EXP is a base element of TRUE_EXP, we
- don't necessarily know by looking at EXP where its virtual
- baseclass fields should really be pointing. But we do know
- from TRUE_EXP. In constructors, we don't know anything about
- the value being initialized.
-
- ALIAS_THIS serves the same purpose it serves for expand_aggr_init.
-
- FLAGS is just passes to `build_method_call'. See that function for
- its description. */
-
-static void
-expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
- tree binfo;
- tree true_exp, exp;
- tree init;
- int alias_this;
- int flags;
-{
- tree type = TREE_TYPE (exp);
- tree init_type = NULL_TREE;
- tree rval;
-
- my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);
-
- /* Use a function returning the desired type to initialize EXP for us.
- If the function is a constructor, and its first argument is
- NULL_TREE, know that it was meant for us--just slide exp on
- in and expand the constructor. Constructors now come
- as TARGET_EXPRs. */
- if (init)
- {
- tree init_list = NULL_TREE;
-
- if (TREE_CODE (init) == TREE_LIST)
- {
- init_list = init;
- if (TREE_CHAIN (init) == NULL_TREE)
- init = TREE_VALUE (init);
- }
-
- init_type = TREE_TYPE (init);
-
- if (TREE_CODE (init) != TREE_LIST)
- {
- if (TREE_CODE (init_type) == ERROR_MARK)
- return;
-
-#if 0
- /* These lines are found troublesome 5/11/89. */
- if (TREE_CODE (init_type) == REFERENCE_TYPE)
- init_type = TREE_TYPE (init_type);
-#endif
-
- /* This happens when we use C++'s functional cast notation.
- If the types match, then just use the TARGET_EXPR
- directly. Otherwise, we need to create the initializer
- separately from the object being initialized. */
- if (TREE_CODE (init) == TARGET_EXPR)
- {
- if (init_type == type)
- {
- if (TREE_CODE (exp) == VAR_DECL
- || TREE_CODE (exp) == RESULT_DECL)
- /* Unify the initialization targets. */
- DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp);
- else
- DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, 0, 0);
-
- expand_expr_stmt (init);
- return;
- }
- else
- {
- init = TREE_OPERAND (init, 1);
- init = build (CALL_EXPR, init_type,
- TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
- TREE_SIDE_EFFECTS (init) = 1;
-#if 0
- TREE_RAISES (init) = ??
-#endif
- if (init_list)
- TREE_VALUE (init_list) = init;
- }
- }
-
- if (init_type == type && TREE_CODE (init) == CALL_EXPR
-#if 0
- /* It is legal to directly initialize from a CALL_EXPR
- without going through X(X&), apparently. */
- && ! TYPE_GETS_INIT_REF (type)
-#endif
- )
- {
- /* A CALL_EXPR is a legitimate form of initialization, so
- we should not print this warning message. */
-#if 0
- /* Should have gone away due to 5/11/89 change. */
- if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
- init = convert_from_reference (init);
-#endif
- expand_assignment (exp, init, 0, 0);
- if (exp == DECL_RESULT (current_function_decl))
- {
- /* Failing this assertion means that the return value
- from receives multiple initializations. */
- my_friendly_assert (DECL_INITIAL (exp) == NULL_TREE
- || DECL_INITIAL (exp) == error_mark_node,
- 212);
- DECL_INITIAL (exp) = init;
- }
- return;
- }
- else if (init_type == type
- && TREE_CODE (init) == COND_EXPR)
- {
- /* Push value to be initialized into the cond, where possible.
- Avoid spurious warning messages when initializing the
- result of this function. */
- TREE_OPERAND (init, 1)
- = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1));
- if (exp == DECL_RESULT (current_function_decl))
- DECL_INITIAL (exp) = NULL_TREE;
- TREE_OPERAND (init, 2)
- = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2));
- if (exp == DECL_RESULT (current_function_decl))
- DECL_INITIAL (exp) = init;
- expand_expr (init, const0_rtx, VOIDmode, 0);
- free_temp_slots ();
- return;
- }
- }
-
- /* We did not know what we were initializing before. Now we do. */
- if (TREE_CODE (init) == TARGET_EXPR)
- {
- tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1);
-
- if (TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR
- && TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node)
- {
- /* In order for this to work for RESULT_DECLs, if their
- type has a constructor, then they must be BLKmode
- so that they will be meaningfully addressable. */
- tree arg = build_unary_op (ADDR_EXPR, exp, 0);
- init = TREE_OPERAND (init, 1);
- init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)),
- TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
- TREE_SIDE_EFFECTS (init) = 1;
-#if 0
- TREE_RAISES (init) = ??
-#endif
- TREE_VALUE (TREE_OPERAND (init, 1))
- = convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);
-
- if (alias_this)
- {
- expand_assignment (current_function_decl, init, 0, 0);
- return;
- }
- if (exp == DECL_RESULT (current_function_decl))
- {
- if (DECL_INITIAL (DECL_RESULT (current_function_decl)))
- fatal ("return value from function receives multiple initializations");
- DECL_INITIAL (exp) = init;
- }
- expand_expr_stmt (init);
- return;
- }
- }
-
- /* Handle this case: when calling a constructor: xyzzy foo(bar);
- which really means: xyzzy foo = bar; Ugh!
-
- We can also be called with an initializer for an object
- which has virtual functions, but no constructors. In that
- case, we perform the assignment first, then initialize
- the virtual function table pointer fields. */
-
- if (! TYPE_NEEDS_CONSTRUCTING (type))
- {
- if (init_list && TREE_CHAIN (init_list))
- {
- warning ("initializer list being treated as compound expression");
- init = convert (TREE_TYPE (exp), build_compound_expr (init_list));
- if (init == error_mark_node)
- return;
- }
- if (TREE_CODE (exp) == VAR_DECL
- && TREE_CODE (init) == CONSTRUCTOR
- && TREE_HAS_CONSTRUCTOR (init)
- && flag_pic == 0)
- store_init_value (exp, init);
- else
- expand_assignment (exp, init, 0, 0);
-
- if (TYPE_VIRTUAL_P (type))
- expand_recursive_init (binfo, true_exp, exp, init, CLASSTYPE_BASE_INIT_LIST (type), alias_this);
- return;
- }
-
- /* See whether we can go through a type conversion operator.
- This wins over going through a non-existent constructor. If
- there is a constructor, it is ambiguous. */
- if (TREE_CODE (init) != TREE_LIST)
- {
- tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE
- ? TREE_TYPE (init_type) : init_type;
-
- if (ttype != type && IS_AGGR_TYPE (ttype))
- {
- tree rval = build_type_conversion (CONVERT_EXPR, type, init, 0);
-
- if (rval)
- {
- /* See if there is a constructor for``type'' that takes a
- ``ttype''-typed object. */
- tree parms = build_tree_list (NULL_TREE, init);
- tree as_cons = NULL_TREE;
- if (TYPE_HAS_CONSTRUCTOR (type))
- as_cons = build_method_call (exp, constructor_name (type),
- parms, binfo,
- LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION);
- if (as_cons != NULL_TREE && as_cons != error_mark_node)
- {
- tree name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
- error ("ambiguity between conversion to `%s' and constructor",
- IDENTIFIER_POINTER (name));
- }
- else
- expand_assignment (exp, rval, 0, 0);
- return;
- }
- }
- }
- }
-
- /* Handle default copy constructors here, does not matter if there is
- a constructor or not. */
- if (type == init_type && IS_AGGR_TYPE (type)
- && init && TREE_CODE (init) != TREE_LIST)
- expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags);
- /* Not sure why this is here... */
- else if (TYPE_HAS_CONSTRUCTOR (type))
- expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags);
- else if (TREE_CODE (type) == ARRAY_TYPE)
- {
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
- expand_vec_init (exp, exp, array_type_nelts (type), init, 0);
- else if (TYPE_VIRTUAL_P (TREE_TYPE (type)))
- sorry ("arrays of objects with virtual functions but no constructors");
- }
- else
- expand_recursive_init (binfo, true_exp, exp, init,
- CLASSTYPE_BASE_INIT_LIST (type), alias_this);
-}
-
-/* A pointer which holds the initializer. First call to
- expand_aggr_init gets this value pointed to, and sets it to init_null. */
-static tree *init_ptr, init_null;
-
-/* Subroutine of expand_recursive_init:
-
- ADDR is the address of the expression being initialized.
- INIT_LIST is the cons-list of initializations to be performed.
- ALIAS_THIS is its same, lovable self. */
-static void
-expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
- tree binfo, true_exp, addr;
- tree init_list;
- int alias_this;
-{
- while (init_list)
- {
- if (TREE_PURPOSE (init_list))
- {
- if (TREE_CODE (TREE_PURPOSE (init_list)) == FIELD_DECL)
- {
- tree member = TREE_PURPOSE (init_list);
- tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), 0);
- tree member_base = build (COMPONENT_REF, TREE_TYPE (member), subexp, member);
- if (IS_AGGR_TYPE (TREE_TYPE (member)))
- expand_aggr_init (member_base, DECL_INITIAL (member), 0);
- else if (TREE_CODE (TREE_TYPE (member)) == ARRAY_TYPE
- && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (member)))
- {
- member_base = save_expr (default_conversion (member_base));
- expand_vec_init (member, member_base,
- array_type_nelts (TREE_TYPE (member)),
- DECL_INITIAL (member), 0);
- }
- else expand_expr_stmt (build_modify_expr (member_base, INIT_EXPR, DECL_INITIAL (member)));
- }
- else if (TREE_CODE (TREE_PURPOSE (init_list)) == TREE_LIST)
- {
- expand_recursive_init_1 (binfo, true_exp, addr, TREE_PURPOSE (init_list), alias_this);
- expand_recursive_init_1 (binfo, true_exp, addr, TREE_VALUE (init_list), alias_this);
- }
- else if (TREE_CODE (TREE_PURPOSE (init_list)) == ERROR_MARK)
- {
- /* Only initialize the virtual function tables if we
- are initializing the ultimate users of those vtables. */
- if (TREE_VALUE (init_list))
- {
- /* We have to ensure that the second argment to
- build_virtual_init is in binfo's hierarchy. */
- expand_expr_stmt (build_virtual_init (binfo,
- get_binfo (TREE_VALUE (init_list), binfo, 0),
- addr));
- if (TREE_VALUE (init_list) == binfo
- && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
- expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));
- }
- }
- else my_friendly_abort (49);
- }
- else if (TREE_VALUE (init_list)
- && TREE_CODE (TREE_VALUE (init_list)) == TREE_VEC)
- {
- tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), 0);
- expand_aggr_init_1 (binfo, true_exp, subexp, *init_ptr,
- alias_this && BINFO_OFFSET_ZEROP (TREE_VALUE (init_list)),
- LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN);
-
- /* INIT_PTR is used up. */
- init_ptr = &init_null;
- }
- else
- my_friendly_abort (50);
- init_list = TREE_CHAIN (init_list);
- }
-}
-
-/* Initialize EXP with INIT. Type EXP does not have a constructor,
- but it has a baseclass with a constructor or a virtual function
- table which needs initializing.
-
- INIT_LIST is a cons-list describing what parts of EXP actually
- need to be initialized. INIT is given to the *unique*, first
- constructor within INIT_LIST. If there are multiple first
- constructors, such as with multiple inheritance, INIT must
- be zero or an ambiguity error is reported.
-
- ALIAS_THIS is passed from `expand_aggr_init'. See comments
- there. */
-
-static void
-expand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this)
- tree binfo, true_exp, exp, init;
- tree init_list;
- int alias_this;
-{
- tree *old_init_ptr = init_ptr;
- tree addr = build_unary_op (ADDR_EXPR, exp, 0);
- init_ptr = &init;
-
- if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
- {
- expand_aggr_vbase_init (binfo, exp, addr, init_list);
- expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));
- }
- expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);
-
- if (*init_ptr)
- {
- tree type = TREE_TYPE (exp);
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
- if (IS_AGGR_TYPE (type))
- error_with_aggr_type (type, "unexpected argument to constructor `%s'");
- else
- error ("unexpected argument to constructor");
- }
- init_ptr = old_init_ptr;
-}
-
-/* Report an error if NAME is not the name of a user-defined,
- aggregate type. If OR_ELSE is nonzero, give an error message. */
-int
-is_aggr_typedef (name, or_else)
- tree name;
- int or_else;
-{
- tree type;
-
- if (name == error_mark_node)
- return 0;
-
- if (! IDENTIFIER_HAS_TYPE_VALUE (name))
- {
- if (or_else)
- error ("`%s' fails to be an aggregate typedef",
- IDENTIFIER_POINTER (name));
- return 0;
- }
- type = IDENTIFIER_TYPE_VALUE (name);
- if (! IS_AGGR_TYPE (type))
- {
- if (or_else)
- error ("type `%s' is of non-aggregate type",
- IDENTIFIER_POINTER (name));
- return 0;
- }
- return 1;
-}
-
-/* This code could just as well go in `cp-class.c', but is placed here for
- modularity. */
-
-/* For an expression of the form CNAME :: NAME (PARMLIST), build
- the appropriate function call. */
-tree
-build_member_call (cname, name, parmlist)
- tree cname, name, parmlist;
-{
- tree type, t;
- tree method_name = name;
- int dtor = 0;
- int dont_use_this = 0;
- tree basetype_path, decl;
-
- if (TREE_CODE (method_name) == BIT_NOT_EXPR)
- {
- method_name = TREE_OPERAND (method_name, 0);
- dtor = 1;
- }
-
- if (TREE_CODE (cname) == SCOPE_REF)
- cname = resolve_scope_to_name (NULL_TREE, cname);
-
- if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1))
- return error_mark_node;
-
- /* An operator we did not like. */
- if (name == NULL_TREE)
- return error_mark_node;
-
- if (dtor)
- {
- if (! TYPE_HAS_DESTRUCTOR (IDENTIFIER_TYPE_VALUE (cname)))
- error ("type `%s' does not have a destructor",
- IDENTIFIER_POINTER (cname));
- else
- error ("destructor specification error");
- return error_mark_node;
- }
-
- type = IDENTIFIER_TYPE_VALUE (cname);
-
- /* No object? Then just fake one up, and let build_method_call
- figure out what to do. */
- if (current_class_type == 0
- || get_base_distance (type, current_class_type, 0, &basetype_path) == -1)
- dont_use_this = 1;
-
- if (dont_use_this)
- {
- basetype_path = NULL_TREE;
- decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node);
- }
- else if (current_class_decl == 0)
- {
- dont_use_this = 1;
- decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node);
- }
- else
- {
- decl = current_class_decl;
- if (TREE_TYPE (decl) != type)
- decl = convert (TYPE_POINTER_TO (type), decl);
- }
-
- if (t = lookup_fnfields (TYPE_BINFO (type), method_name, 0))
- return build_method_call (decl, method_name, parmlist, basetype_path,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
- if (TREE_CODE (name) == IDENTIFIER_NODE
- && (t = lookup_field (TYPE_BINFO (type), name, 1, 0)))
- {
- if (t == error_mark_node)
- return error_mark_node;
- if (TREE_CODE (t) == FIELD_DECL)
- {
- if (dont_use_this)
- {
- error ("invalid use of non-static field `%s'",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t);
- }
- else if (TREE_CODE (t) == VAR_DECL)
- decl = t;
- else
- {
- error ("invalid use of member `%s::%s'",
- IDENTIFIER_POINTER (cname), name);
- return error_mark_node;
- }
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl))
- && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (decl)))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, parmlist, NULL_TREE);
- return build_function_call (decl, parmlist);
- }
- else
- {
- char *err_name;
- if (TREE_CODE (name) == IDENTIFIER_NODE)
- {
- if (IDENTIFIER_OPNAME_P (name))
- {
- char *op_name = operator_name_string (method_name);
- err_name = (char *)alloca (13 + strlen (op_name));
- sprintf (err_name, "operator %s", op_name);
- }
- else
- err_name = IDENTIFIER_POINTER (name);
- }
- else
- my_friendly_abort (51);
-
- error ("no method `%s::%s'", IDENTIFIER_POINTER (cname), err_name);
- return error_mark_node;
- }
-}
-
-/* Build a reference to a member of an aggregate. This is not a
- C++ `&', but really something which can have its address taken,
- and then act as a pointer to member, for example CNAME :: FIELD
- can have its address taken by saying & CNAME :: FIELD.
-
- @@ Prints out lousy diagnostics for operator <typename>
- @@ fields.
-
- @@ This function should be rewritten and placed in cp-search.c. */
-tree
-build_offset_ref (cname, name)
- tree cname, name;
-{
- tree decl, type, fnfields, fields, t = error_mark_node;
- tree basetypes = NULL_TREE;
- int dtor = 0;
-
- if (TREE_CODE (cname) == SCOPE_REF)
- cname = resolve_scope_to_name (NULL_TREE, cname);
-
- if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1))
- return error_mark_node;
-
- type = IDENTIFIER_TYPE_VALUE (cname);
-
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- dtor = 1;
- name = TREE_OPERAND (name, 0);
- }
-
- if (TYPE_SIZE (type) == 0)
- {
- t = IDENTIFIER_CLASS_VALUE (name);
- if (t == 0)
- {
- error_with_aggr_type (type, "incomplete type `%s' does not have member `%s'", IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- if (TREE_CODE (t) == TYPE_DECL)
- {
- error_with_decl (t, "member `%s' is just a type declaration");
- return error_mark_node;
- }
- if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)
- {
- TREE_USED (t) = 1;
- return t;
- }
- if (TREE_CODE (t) == FIELD_DECL)
- sorry ("use of member in incomplete aggregate type");
- else if (TREE_CODE (t) == FUNCTION_DECL)
- sorry ("use of member function in incomplete aggregate type");
- else
- my_friendly_abort (52);
- return error_mark_node;
- }
-
- if (TREE_CODE (name) == TYPE_EXPR)
- /* Pass a TYPE_DECL to build_component_type_expr. */
- return build_component_type_expr (TYPE_NAME (TREE_TYPE (cname)),
- name, NULL_TREE, 1);
-
- fnfields = lookup_fnfields (TYPE_BINFO (type), name, 1);
- fields = lookup_field (type, name, 0, 0);
-
- if (fields == error_mark_node || fnfields == error_mark_node)
- return error_mark_node;
-
- if (current_class_type == 0
- || get_base_distance (type, current_class_type, 0, &basetypes) == -1)
- {
- basetypes = TYPE_BINFO (type);
- decl = build1 (NOP_EXPR,
- IDENTIFIER_TYPE_VALUE (cname),
- error_mark_node);
- }
- else if (current_class_decl == 0)
- decl = build1 (NOP_EXPR, IDENTIFIER_TYPE_VALUE (cname),
- error_mark_node);
- else decl = C_C_D;
-
- /* A lot of this logic is now handled in lookup_field and
- lookup_fnfield. */
- if (fnfields)
- {
- basetypes = TREE_PURPOSE (fnfields);
-
- /* Go from the TREE_BASELINK to the member function info. */
- t = TREE_VALUE (fnfields);
-
- if (fields)
- {
- if (DECL_FIELD_CONTEXT (fields) == DECL_FIELD_CONTEXT (t))
- {
- error ("ambiguous member reference: member `%s' defined as both field and function",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (fields), DECL_FIELD_CONTEXT (t)))
- ;
- else if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (t), DECL_FIELD_CONTEXT (fields)))
- t = fields;
- else
- {
- error ("ambiguous member reference: member `%s' derives from distinct classes in multiple inheritance lattice");
- return error_mark_node;
- }
- }
-
- if (t == TREE_VALUE (fnfields))
- {
- extern int flag_save_memoized_contexts;
-
- /* This does not handle visibility checking yet. */
- if (DECL_CHAIN (t) == NULL_TREE || dtor)
- {
- enum visibility_type visibility;
-
- /* unique functions are handled easily. */
- unique:
- visibility = compute_visibility (basetypes, t);
- if (visibility == visibility_protected)
- {
- error_with_decl (t, "member function `%s' is protected");
- error ("in this context");
- return error_mark_node;
- }
- if (visibility == visibility_private)
- {
- error_with_decl (t, "member function `%s' is private");
- error ("in this context");
- return error_mark_node;
- }
- assemble_external (t);
- return build (OFFSET_REF, TREE_TYPE (t), decl, t);
- }
-
- /* overloaded functions may need more work. */
- if (cname == name)
- {
- if (TYPE_HAS_DESTRUCTOR (type)
- && DECL_CHAIN (DECL_CHAIN (t)) == NULL_TREE)
- {
- t = DECL_CHAIN (t);
- goto unique;
- }
- }
- /* FNFIELDS is most likely allocated on the search_obstack,
- which will go away after this class scope. If we need
- to save this value for later (either for memoization
- or for use as an initializer for a static variable), then
- do so here.
-
- ??? The smart thing to do for the case of saving initializers
- is to resolve them before we're done with this scope. */
- if (!TREE_PERMANENT (fnfields)
- && ((flag_save_memoized_contexts && global_bindings_p ())
- || ! allocation_temporary_p ()))
- fnfields = copy_list (fnfields);
- t = build_tree_list (error_mark_node, fnfields);
- TREE_TYPE (t) = build_offset_type (type, unknown_type_node);
- return t;
- }
- }
-
- /* Now that we know we are looking for a field, see if we
- have access to that field. Lookup_field will give us the
- error message. */
-
- t = lookup_field (basetypes, name, 1, 0);
-
- if (t == error_mark_node)
- return error_mark_node;
-
- if (t == NULL_TREE)
- {
- char *print_name, *non_operator = "<";
-
- if (name == ansi_opname[(int) TYPE_EXPR])
- {
- error ("type conversion operator not a member of type `%s'",
- IDENTIFIER_POINTER (cname));
- return error_mark_node;
- }
-
- if ((IDENTIFIER_POINTER (name))[0] == '_'
- && (IDENTIFIER_POINTER (name))[1] == '_')
- print_name = operator_name_string (name);
- else
- print_name = non_operator;
-
- /* First character of "<invalid operator>". */
- if (print_name[0] == '<')
- error ("field `%s' is not a member of type `%s'",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (cname));
- else
- error ("operator `%s' is not a member of type `%s'",
- print_name, IDENTIFIER_POINTER (cname));
- return error_mark_node;
- }
-
- if (TREE_CODE (t) == TYPE_DECL)
- {
- error_with_decl (t, "member `%s' is just a type declaration");
- return error_mark_node;
- }
- /* static class members and class-specific enum
- values can be returned without further ado. */
- if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)
- {
- assemble_external (t);
- TREE_USED (t) = 1;
- return t;
- }
-
- /* static class functions too. */
- if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
- my_friendly_abort (53);
-
- /* In member functions, the form `cname::name' is no longer
- equivalent to `this->cname::name'. */
- return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t);
-}
-
-/* Given an object EXP and a member function reference MEMBER,
- return the address of the actual member function. */
-tree
-get_member_function (exp_addr_ptr, exp, member)
- tree *exp_addr_ptr;
- tree exp, member;
-{
- tree ctype = TREE_TYPE (exp);
- tree function = save_expr (build_unary_op (ADDR_EXPR, member, 0));
-
- if (TYPE_VIRTUAL_P (ctype)
- || (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (ctype)))
- {
- tree e0, e1, e3;
- tree exp_addr;
-
- /* Save away the unadulterated `this' pointer. */
- exp_addr = save_expr (*exp_addr_ptr);
-
- /* Cast function to signed integer. */
- e0 = build1 (NOP_EXPR, integer_type_node, function);
-
-#ifdef VTABLE_USES_MASK
- /* If we are willing to limit the number of
- virtual functions a class may have to some
- *small* number, then if, for a function address,
- we are passed some small number, we know that
- it is a virtual function index, and work from there. */
- e1 = build (BIT_AND_EXPR, integer_type_node, e0, vtbl_mask);
-#else
- /* There is a hack here that takes advantage of
- twos complement arithmetic, and the fact that
- there are more than one UNITS to the WORD.
- If the high bit is set for the `function',
- then we pretend it is a virtual function,
- and the array indexing will knock this bit
- out the top, leaving a valid index. */
- if (UNITS_PER_WORD <= 1)
- my_friendly_abort (54);
-
- e1 = build (GT_EXPR, integer_type_node, e0, integer_zero_node);
- e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,
- build_tree_list (NULL_TREE, e1)));
- e1 = save_expr (e1);
-#endif
-
- if (TREE_SIDE_EFFECTS (*exp_addr_ptr))
- {
- exp = build_indirect_ref (exp_addr, 0);
- *exp_addr_ptr = exp_addr;
- }
-
- /* This is really hairy: if the function pointer is a pointer
- to a non-virtual member function, then we can't go mucking
- with the `this' pointer (any more than we already have to
- this point). If it is a pointer to a virtual member function,
- then we have to adjust the `this' pointer according to
- what the virtual function table tells us. */
-
- e3 = build_vfn_ref (exp_addr_ptr, exp, e0);
- my_friendly_assert (e3 != error_mark_node, 213);
-
- /* Change this pointer type from `void *' to the
- type it is really supposed to be. */
- TREE_TYPE (e3) = TREE_TYPE (function);
-
- /* If non-virtual, use what we had originally. Otherwise,
- use the value we get from the virtual function table. */
- *exp_addr_ptr = build_conditional_expr (e1, exp_addr, *exp_addr_ptr);
-
- function = build_conditional_expr (e1, function, e3);
- }
- return build_indirect_ref (function, 0);
-}
-
-/* If a OFFSET_REF made it through to here, then it did
- not have its address taken. */
-
-tree
-resolve_offset_ref (exp)
- tree exp;
-{
- tree type = TREE_TYPE (exp);
- tree base = NULL_TREE;
- tree member;
- tree basetype, addr;
-
- if (TREE_CODE (exp) == TREE_LIST)
- return build_unary_op (ADDR_EXPR, exp, 0);
-
- if (TREE_CODE (exp) != OFFSET_REF)
- {
- my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214);
- if (TYPE_OFFSET_BASETYPE (type) != current_class_type)
- {
- error ("object missing in use of pointer-to-member construct");
- return error_mark_node;
- }
- member = exp;
- type = TREE_TYPE (type);
- base = C_C_D;
- }
- else
- {
- member = TREE_OPERAND (exp, 1);
- base = TREE_OPERAND (exp, 0);
- }
-
- if (TREE_CODE (member) == VAR_DECL
- || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
- {
- /* These were static members. */
- if (mark_addressable (member) == 0)
- return error_mark_node;
- return member;
- }
-
- /* Syntax error can cause a member which should
- have been seen as static to be grok'd as non-static. */
- if (TREE_CODE (member) == FIELD_DECL && C_C_D == NULL_TREE)
- {
- if (TREE_ADDRESSABLE (member) == 0)
- {
- error_with_decl (member, "member `%s' is non-static in static member function context");
- error ("at this point in file");
- TREE_ADDRESSABLE (member) = 1;
- }
- return error_mark_node;
- }
-
- /* The first case is really just a reference to a member of `this'. */
- if (TREE_CODE (member) == FIELD_DECL
- && (base == C_C_D
- || (TREE_CODE (base) == NOP_EXPR
- && TREE_OPERAND (base, 0) == error_mark_node)))
- {
- tree basetype_path;
- enum visibility_type visibility;
-
- basetype = DECL_CONTEXT (member);
- if (get_base_distance (basetype, current_class_type, 0, &basetype_path) < 0)
- {
- error_not_base_type (basetype, current_class_type);
- return error_mark_node;
- }
- addr = convert_pointer_to (basetype, current_class_decl);
- visibility = compute_visibility (basetype_path, member);
- if (visibility == visibility_public)
- return build (COMPONENT_REF, TREE_TYPE (member),
- build_indirect_ref (addr, 0), member);
- if (visibility == visibility_protected)
- {
- error_with_decl (member, "member `%s' is protected");
- error ("in this context");
- return error_mark_node;
- }
- if (visibility == visibility_private)
- {
- error_with_decl (member, "member `%s' is private");
- error ("in this context");
- return error_mark_node;
- }
- my_friendly_abort (55);
- }
-
- /* If this is a reference to a member function, then return
- the address of the member function (which may involve going
- through the object's vtable), otherwise, return an expression
- for the dereferenced pointer-to-member construct. */
- addr = build_unary_op (ADDR_EXPR, base, 0);
-
- if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
- {
- basetype = DECL_CLASS_CONTEXT (member);
- addr = convert_pointer_to (basetype, addr);
- return build_unary_op (ADDR_EXPR, get_member_function (&addr, build_indirect_ref (addr, 0), member), 0);
- }
- else if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
- {
- basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member));
- addr = convert_pointer_to (basetype, addr);
- member = convert (ptr_type_node, build_unary_op (ADDR_EXPR, member, 0));
- return build1 (INDIRECT_REF, type,
- build (PLUS_EXPR, ptr_type_node, addr, member));
- }
- my_friendly_abort (56);
- /* NOTREACHED */
- return NULL_TREE;
-}
-
-/* Return either DECL or its known constant value (if it has one). */
-
-tree
-decl_constant_value (decl)
- tree decl;
-{
- if (! TREE_THIS_VOLATILE (decl)
-#if 0
- /* These may be necessary for C, but they break C++. */
- ! TREE_PUBLIC (decl)
- /* Don't change a variable array bound or initial value to a constant
- in a place where a variable is invalid. */
- && ! pedantic
-#endif /* 0 */
- && DECL_INITIAL (decl) != 0
- && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
- /* This is invalid if initial value is not constant.
- If it has either a function call, a memory reference,
- or a variable, then re-evaluating it could give different results. */
- && TREE_CONSTANT (DECL_INITIAL (decl))
- /* Check for cases where this is sub-optimal, even though valid. */
- && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
-#if 0
- /* We must allow this to work outside of functions so that
- static constants can be used for array sizes. */
- && current_function_decl != 0
- && DECL_MODE (decl) != BLKmode
-#endif
- )
- return DECL_INITIAL (decl);
- return decl;
-}
-
-/* Friend handling routines. */
-/* Friend data structures:
-
- Friend lists come from TYPE_DECL nodes. Since all aggregate
- types are automatically typedef'd, these node are guaranteed
- to exist.
-
- The TREE_PURPOSE of a friend list is the name of the friend,
- and its TREE_VALUE is another list.
-
- The TREE_PURPOSE of that list is a type, which allows
- all functions of a given type to be friends.
- The TREE_VALUE of that list is an individual function
- which is a friend.
-
- Non-member friends will match only by their DECL. Their
- member type is NULL_TREE, while the type of the inner
- list will either be of aggregate type or error_mark_node. */
-
-/* Tell if this function specified by DECL
- can be a friend of type TYPE.
- Return nonzero if friend, zero otherwise.
-
- DECL can be zero if we are calling a constructor or accessing a
- member in global scope. */
-int
-is_friend (type, decl)
- tree type, decl;
-{
- tree typedecl = TYPE_NAME (type);
- tree ctype;
- tree list;
- tree name;
-
- if (decl == NULL_TREE)
- return 0;
-
- ctype = DECL_CLASS_CONTEXT (decl);
- if (ctype)
- {
- list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (typedecl));
- while (list)
- {
- if (ctype == TREE_VALUE (list))
- return 1;
- list = TREE_CHAIN (list);
- }
- }
-
- list = DECL_FRIENDLIST (typedecl);
- name = DECL_NAME (decl);
- while (list)
- {
- if (name == TREE_PURPOSE (list))
- {
- tree friends = TREE_VALUE (list);
- name = DECL_ASSEMBLER_NAME (decl);
- while (friends)
- {
- if (ctype == TREE_PURPOSE (friends))
- return 1;
- if (name == DECL_ASSEMBLER_NAME (TREE_VALUE (friends)))
- return 1;
- friends = TREE_CHAIN (friends);
- }
- return 0;
- }
- list = TREE_CHAIN (list);
- }
- return 0;
-}
-
-/* Add a new friend to the friends of the aggregate type TYPE.
- DECL is the FUNCTION_DECL of the friend being added. */
-static void
-add_friend (type, decl)
- tree type, decl;
-{
- tree typedecl = TYPE_NAME (type);
- tree list = DECL_FRIENDLIST (typedecl);
- tree name = DECL_NAME (decl);
- tree ctype = TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
- ? DECL_CLASS_CONTEXT (decl) : error_mark_node;
-
- while (list)
- {
- if (name == TREE_PURPOSE (list))
- {
- tree friends = TREE_VALUE (list);
- while (friends)
- {
- if (decl == TREE_VALUE (friends))
- {
- warning_with_decl (decl, "`%s' is already a friend of class `%s'", IDENTIFIER_POINTER (DECL_NAME (typedecl)));
- return;
- }
- friends = TREE_CHAIN (friends);
- }
- TREE_VALUE (list) = tree_cons (ctype, decl, TREE_VALUE (list));
- return;
- }
- list = TREE_CHAIN (list);
- }
- DECL_FRIENDLIST (typedecl)
- = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
- DECL_FRIENDLIST (typedecl));
- if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
- {
- tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
- TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
- TYPE_GETS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
- if (parmtypes && TREE_CHAIN (parmtypes))
- {
- tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes));
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl))
- {
- TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
- TYPE_GETS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
- }
- }
- }
-}
-
-/* Declare that every member function NAME in FRIEND_TYPE
- (which may be NULL_TREE) is a friend of type TYPE. */
-static void
-add_friends (type, name, friend_type)
- tree type, name, friend_type;
-{
- tree typedecl = TYPE_NAME (type);
- tree list = DECL_FRIENDLIST (typedecl);
-
- while (list)
- {
- if (name == TREE_PURPOSE (list))
- {
- tree friends = TREE_VALUE (list);
- while (friends && TREE_PURPOSE (friends) != friend_type)
- friends = TREE_CHAIN (friends);
- if (friends)
- if (friend_type)
- warning ("method `%s::%s' is already a friend of class",
- TYPE_NAME_STRING (friend_type),
- IDENTIFIER_POINTER (name));
- else
- warning ("function `%s' is already a friend of class `%s'",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (DECL_NAME (typedecl)));
- else
- TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE,
- TREE_VALUE (list));
- return;
- }
- list = TREE_CHAIN (list);
- }
- DECL_FRIENDLIST (typedecl) =
- tree_cons (name,
- build_tree_list (friend_type, NULL_TREE),
- DECL_FRIENDLIST (typedecl));
- if (! strncmp (IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]),
- strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]))))
- {
- TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
- TYPE_GETS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
- sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists");
- }
-}
-
-/* Set up a cross reference so that type TYPE will
- make member function CTYPE::DECL a friend when CTYPE
- is finally defined. */
-void
-xref_friend (type, decl, ctype)
- tree type, decl, ctype;
-{
- tree typedecl = TYPE_NAME (type);
- tree friend_decl = TYPE_NAME (ctype);
- tree t = tree_cons (NULL_TREE, ctype, DECL_UNDEFINED_FRIENDS (typedecl));
-
- DECL_UNDEFINED_FRIENDS (typedecl) = t;
- SET_DECL_WAITING_FRIENDS (friend_decl, tree_cons (type, t, DECL_WAITING_FRIENDS (friend_decl)));
- TREE_TYPE (DECL_WAITING_FRIENDS (friend_decl)) = decl;
-}
-
-/* Set up a cross reference so that functions with name NAME and
- type CTYPE know that they are friends of TYPE. */
-void
-xref_friends (type, name, ctype)
- tree type, name, ctype;
-{
- tree typedecl = TYPE_NAME (type);
- tree friend_decl = TYPE_NAME (ctype);
- tree t = tree_cons (NULL_TREE, ctype,
- DECL_UNDEFINED_FRIENDS (typedecl));
-
- DECL_UNDEFINED_FRIENDS (typedecl) = t;
- SET_DECL_WAITING_FRIENDS (friend_decl, tree_cons (type, t, DECL_WAITING_FRIENDS (friend_decl)));
- TREE_TYPE (DECL_WAITING_FRIENDS (friend_decl)) = name;
-}
-
-/* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already
- been defined, we make all of its member functions friends of
- TYPE. If not, we make it a pending friend, which can later be added
- when its definition is seen. If a type is defined, then its TYPE_DECL's
- DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend
- classes that are not defined. If a type has not yet been defined,
- then the DECL_WAITING_FRIENDS contains a list of types
- waiting to make it their friend. Note that these two can both
- be in use at the same time! */
-void
-make_friend_class (type, friend_type)
- tree type, friend_type;
-{
- tree classes;
-
- if (type == friend_type)
- {
- warning ("class `%s' is implicitly friends with itself",
- TYPE_NAME_STRING (type));
- return;
- }
-
- GNU_xref_hier (TYPE_NAME_STRING (type),
- TYPE_NAME_STRING (friend_type), 0, 0, 1);
-
- classes = CLASSTYPE_FRIEND_CLASSES (type);
- while (classes && TREE_VALUE (classes) != friend_type)
- classes = TREE_CHAIN (classes);
- if (classes)
- warning ("class `%s' is already friends with class `%s'",
- TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type));
- else
- {
- CLASSTYPE_FRIEND_CLASSES (type)
- = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
- }
-}
-
-/* Main friend processor. This is large, and for modularity purposes,
- has been removed from grokdeclarator. It returns `void_type_node'
- to indicate that something happened, though a FIELD_DECL is
- not returned.
-
- CTYPE is the class this friend belongs to.
-
- DECLARATOR is the name of the friend.
-
- DECL is the FUNCTION_DECL that the friend is.
-
- In case we are parsing a friend which is part of an inline
- definition, we will need to store PARM_DECL chain that comes
- with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL.
-
- FLAGS is just used for `grokclassfn'.
-
- QUALS say what special qualifies should apply to the object
- pointed to by `this'. */
-tree
-do_friend (ctype, declarator, decl, parmdecls, flags, quals)
- tree ctype, declarator, decl, parmdecls;
- enum overload_flags flags;
- tree quals;
-{
- /* first, lets find out if what we are making a friend needs overloading */
- tree previous_decl;
- int was_c_linkage = 0;
- /* if we find something in scope, let see if it has extern "C" linkage */
- /* This code is pretty general and should be ripped out and reused
- as a separate function. */
- if (DECL_NAME (decl))
- {
- previous_decl=lookup_name (DECL_NAME (decl), 0);
- if (previous_decl && TREE_CODE (previous_decl) == TREE_LIST)
- {
- do
- {
- if (TREE_TYPE (TREE_VALUE (previous_decl)) == TREE_TYPE (decl))
- {
- previous_decl = TREE_VALUE (previous_decl);
- break;
- }
- previous_decl = TREE_CHAIN (previous_decl);
- }
- while (previous_decl);
- }
- if (previous_decl && TREE_CODE (previous_decl) == FUNCTION_DECL)
- if (TREE_TYPE (decl) == TREE_TYPE (previous_decl))
- if (DECL_LANGUAGE (previous_decl) == lang_c)
- {
- /* it did, so lets not overload this */
- was_c_linkage = 1;
- }
- }
-
- if (ctype)
- {
- tree cname = TYPE_NAME (ctype);
- if (TREE_CODE (cname) == TYPE_DECL)
- cname = DECL_NAME (cname);
-
- /* A method friend. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- if (flags == NO_SPECIAL && ctype && declarator == cname)
- DECL_CONSTRUCTOR_P (decl) = 1;
-
- /* This will set up DECL_ARGUMENTS for us. */
- grokclassfn (ctype, cname, decl, flags, quals);
- if (TYPE_SIZE (ctype) != 0)
- check_classfn (ctype, cname, decl);
-
- if (TREE_TYPE (decl) != error_mark_node)
- {
- if (TYPE_SIZE (ctype))
- {
- /* We don't call pushdecl here yet, or ever on this
- actual FUNCTION_DECL. We must preserve its TREE_CHAIN
- until the end. */
- make_decl_rtl (decl, NULL_PTR, 1);
- add_friend (current_class_type, decl);
- }
- else
- xref_friend (current_class_type, decl, ctype);
- DECL_FRIEND_P (decl) = 1;
- }
- }
- else
- {
- /* Possibly a bunch of method friends. */
-
- /* Get the class they belong to. */
- tree ctype = IDENTIFIER_TYPE_VALUE (cname);
-
- /* This class is defined, use its methods now. */
- if (TYPE_SIZE (ctype))
- {
- tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0);
- if (fields)
- add_friends (current_class_type, declarator, ctype);
- else
- error ("method `%s' is not a member of class `%s'",
- IDENTIFIER_POINTER (declarator),
- IDENTIFIER_POINTER (cname));
- }
- else
- xref_friends (current_class_type, declarator, ctype);
- decl = void_type_node;
- }
- }
- /* never overload C functions */
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && ((IDENTIFIER_LENGTH (declarator) == 4
- && IDENTIFIER_POINTER (declarator)[0] == 'm'
- && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
- || (IDENTIFIER_LENGTH (declarator) > 10
- && IDENTIFIER_POINTER (declarator)[0] == '_'
- && IDENTIFIER_POINTER (declarator)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (declarator)+2,
- "builtin_", 8) == 0)
- || was_c_linkage))
- {
- /* raw "main", and builtin functions never gets overloaded,
- but they can become friends. */
- TREE_PUBLIC (decl) = 1;
- add_friend (current_class_type, decl);
- DECL_FRIEND_P (decl) = 1;
- if (IDENTIFIER_POINTER (declarator)[0] == '_')
- {
- if (! strcmp (IDENTIFIER_POINTER (declarator)+10, "new"))
- TREE_GETS_NEW (current_class_type) = 0;
- else if (! strcmp (IDENTIFIER_POINTER (declarator)+10, "delete"))
- TREE_GETS_DELETE (current_class_type) = 0;
- }
- decl = void_type_node;
- }
- /* A global friend.
- @@ or possibly a friend from a base class ?!? */
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- /* Friends must all go through the overload machinery,
- even though they may not technically be overloaded.
-
- Note that because classes all wind up being top-level
- in their scope, their friend wind up in top-level scope as well. */
- DECL_ASSEMBLER_NAME (decl)
- = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
- TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
- DECL_ARGUMENTS (decl) = parmdecls;
-
- /* We can call pushdecl here, because the TREE_CHAIN of this
- FUNCTION_DECL is not needed for other purposes. */
- decl = pushdecl_top_level (decl);
-
- make_decl_rtl (decl, NULL_PTR, 1);
- add_friend (current_class_type, decl);
-
- if (! TREE_OVERLOADED (declarator)
- && IDENTIFIER_GLOBAL_VALUE (declarator)
- && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (declarator)) == FUNCTION_DECL)
- {
- error ("friend `%s' implicitly overloaded",
- IDENTIFIER_POINTER (declarator));
- error_with_decl (IDENTIFIER_GLOBAL_VALUE (declarator),
- "after declaration of non-overloaded `%s'");
- }
- DECL_FRIEND_P (decl) = 1;
- DECL_OVERLOADED (decl) = 1;
- TREE_OVERLOADED (declarator) = 1;
- decl = push_overloaded_decl (decl, 1);
- }
- else
- {
- /* @@ Should be able to ingest later definitions of this function
- before use. */
- tree decl = IDENTIFIER_GLOBAL_VALUE (declarator);
- if (decl == NULL_TREE)
- {
- warning ("implicitly declaring `%s' as struct",
- IDENTIFIER_POINTER (declarator));
- decl = xref_tag (record_type_node, declarator, NULL_TREE);
- decl = TYPE_NAME (decl);
- }
-
- /* Allow abbreviated declarations of overloaded functions,
- but not if those functions are really class names. */
- if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl)))
- {
- warning ("`friend %s' archaic, use `friend class %s' instead",
- IDENTIFIER_POINTER (declarator),
- IDENTIFIER_POINTER (declarator));
- decl = TREE_TYPE (TREE_PURPOSE (decl));
- }
-
- if (TREE_CODE (decl) == TREE_LIST)
- add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE);
- else
- make_friend_class (current_class_type, TREE_TYPE (decl));
- decl = void_type_node;
- }
- return decl;
-}
-
-/* TYPE has now been defined. It may, however, have a number of things
- waiting make make it their friend. We resolve these references
- here. */
-void
-embrace_waiting_friends (type)
- tree type;
-{
- tree decl = TYPE_NAME (type);
- tree waiters;
-
- if (TREE_CODE (decl) != TYPE_DECL)
- return;
-
- for (waiters = DECL_WAITING_FRIENDS (decl); waiters;
- waiters = TREE_CHAIN (waiters))
- {
- tree waiter = TREE_PURPOSE (waiters);
- tree waiter_prev = TREE_VALUE (waiters);
- tree decl = TREE_TYPE (waiters);
- tree name = decl ? (TREE_CODE (decl) == IDENTIFIER_NODE
- ? decl : DECL_NAME (decl)) : NULL_TREE;
- if (name)
- {
- /* @@ There may be work to be done since we have not verified
- @@ consistency between original and friend declarations
- @@ of the functions waiting to become friends. */
- tree field = lookup_fnfields (TYPE_BINFO (type), name, 0);
- if (field)
- if (decl == name)
- add_friends (waiter, name, type);
- else
- add_friend (waiter, decl);
- else
- error_with_file_and_line (DECL_SOURCE_FILE (TYPE_NAME (waiter)),
- DECL_SOURCE_LINE (TYPE_NAME (waiter)),
- "no method `%s' defined in class `%s' to be friend",
- IDENTIFIER_POINTER (DECL_NAME (TREE_TYPE (waiters))),
- TYPE_NAME_STRING (type));
- }
- else
- make_friend_class (type, waiter);
-
- if (TREE_CHAIN (waiter_prev))
- TREE_CHAIN (waiter_prev) = TREE_CHAIN (TREE_CHAIN (waiter_prev));
- else
- DECL_UNDEFINED_FRIENDS (TYPE_NAME (waiter)) = NULL_TREE;
- }
-}
-
-/* Common subroutines of build_new and build_vec_delete. */
-
-/* Common interface for calling "builtin" functions that are not
- really builtin. */
-
-tree
-build_builtin_call (type, node, arglist)
- tree type;
- tree node;
- tree arglist;
-{
- tree rval = build (CALL_EXPR, type, node, arglist, 0);
- TREE_SIDE_EFFECTS (rval) = 1;
- assemble_external (TREE_OPERAND (node, 0));
- TREE_USED (TREE_OPERAND (node, 0)) = 1;
- return rval;
-}
-
-/* Generate a C++ "new" expression. DECL is either a TREE_LIST
- (which needs to go through some sort of groktypename) or it
- is the name of the class we are newing. INIT is an initialization value.
- It is either an EXPRLIST, an EXPR_NO_COMMAS, or something in braces.
- If INIT is void_type_node, it means do *not* call a constructor
- for this instance.
-
- For types with constructors, the data returned is initialized
- by the appropriate constructor.
-
- Whether the type has a constructor or not, if it has a pointer
- to a virtual function table, then that pointer is set up
- here.
-
- Unless I am mistaken, a call to new () will return initialized
- data regardless of whether the constructor itself is private or
- not.
-
- Note that build_new does nothing to assure that any special
- alignment requirements of the type are met. Rather, it leaves
- it up to malloc to do the right thing. Otherwise, folding to
- the right alignment cal cause problems if the user tries to later
- free the memory returned by `new'.
-
- PLACEMENT is the `placement' list for user-defined operator new (). */
-
-tree
-build_new (placement, decl, init, use_global_new)
- tree placement;
- tree decl, init;
- int use_global_new;
-{
- tree type, true_type, size, rval;
- tree init1 = NULL_TREE, nelts;
- int has_call = 0, has_array = 0;
-
- tree pending_sizes = NULL_TREE;
-
- if (decl == error_mark_node)
- return error_mark_node;
-
- if (TREE_CODE (decl) == TREE_LIST)
- {
- tree absdcl = TREE_VALUE (decl);
- tree last_absdcl = NULL_TREE;
- int old_immediate_size_expand;
-
- if (current_function_decl
- && DECL_CONSTRUCTOR_P (current_function_decl))
- {
- old_immediate_size_expand = immediate_size_expand;
- immediate_size_expand = 0;
- }
-
- nelts = integer_one_node;
-
- if (absdcl && TREE_CODE (absdcl) == CALL_EXPR)
- {
- /* probably meant to be a call */
- has_call = 1;
- init1 = TREE_OPERAND (absdcl, 1);
- absdcl = TREE_OPERAND (absdcl, 0);
- TREE_VALUE (decl) = absdcl;
- }
- while (absdcl && TREE_CODE (absdcl) == INDIRECT_REF)
- {
- last_absdcl = absdcl;
- absdcl = TREE_OPERAND (absdcl, 0);
- }
-
- if (absdcl && TREE_CODE (absdcl) == ARRAY_REF)
- {
- /* probably meant to be a vec new */
- tree this_nelts;
-
- has_array = 1;
- this_nelts = TREE_OPERAND (absdcl, 1);
- if (this_nelts != error_mark_node)
- {
- if (this_nelts == NULL_TREE)
- error ("new of array type fails to specify size");
- else
- {
- this_nelts = save_expr (this_nelts);
- absdcl = TREE_OPERAND (absdcl, 0);
- if (this_nelts == integer_zero_node)
- {
- warning ("zero size array reserves no space");
- nelts = integer_zero_node;
- }
- else
- nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
- }
- }
- else
- nelts = integer_zero_node;
- }
-
- if (last_absdcl)
- TREE_OPERAND (last_absdcl, 0) = absdcl;
- else
- TREE_VALUE (decl) = absdcl;
-
- type = true_type = groktypename (decl);
- if (! type || type == error_mark_node
- || true_type == error_mark_node)
- return error_mark_node;
-
- /* ``A reference cannot be created by the new operator. A reference
- is not an object (8.2.2, 8.4.3), so a pointer to it could not be
- returned by new.'' ARM 5.3.3 */
- if (TREE_CODE (type) == REFERENCE_TYPE)
- error ("new cannot be applied to a reference type");
-
- type = TYPE_MAIN_VARIANT (type);
- if (type == void_type_node)
- {
- error ("invalid type: `void []'");
- return error_mark_node;
- }
- if (current_function_decl
- && DECL_CONSTRUCTOR_P (current_function_decl))
- {
- pending_sizes = get_pending_sizes ();
- immediate_size_expand = old_immediate_size_expand;
- }
- }
- else if (TREE_CODE (decl) == IDENTIFIER_NODE)
- {
- if (IDENTIFIER_HAS_TYPE_VALUE (decl))
- {
- /* An aggregate type. */
- type = IDENTIFIER_TYPE_VALUE (decl);
- decl = TYPE_NAME (type);
- }
- else
- {
- /* A builtin type. */
- decl = lookup_name (decl, 1);
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 215);
- type = TREE_TYPE (decl);
- }
- true_type = type;
- }
- else if (TREE_CODE (decl) == TYPE_DECL)
- {
- type = TREE_TYPE (decl);
- true_type = type;
- }
- else
- {
- type = decl;
- true_type = type;
- decl = TYPE_NAME (type);
- }
-
- if (TYPE_SIZE (type) == 0)
- {
- if (type == void_type_node)
- error ("invalid type for new: `void'");
- else
- incomplete_type_error (0, type);
- return error_mark_node;
- }
-
- if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
- {
- abstract_virtuals_error (NULL_TREE, type);
- return error_mark_node;
- }
-
- /* If our base type is an array, then make sure we know how many elements
- it has. */
- while (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree this_nelts = array_type_nelts_top (type);
- if (nelts == integer_one_node)
- {
- has_array = 1;
- nelts = this_nelts;
- }
- else
- {
- my_friendly_assert (has_array != 0, 216);
- nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
- }
- type = TREE_TYPE (type);
- }
- if (has_array)
- size = fold (build_binary_op (MULT_EXPR, size_in_bytes (type), nelts, 1));
- else
- size = size_in_bytes (type);
-
- if (has_call)
- init = init1;
-
- /* Get to the target type of TRUE_TYPE, so we can decide whether
- any constructors need to be called or not. */
- type = true_type;
- while (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
-
- /* Get a little extra space to store a couple of things before the new'ed
- array. */
- if (has_array && TYPE_NEEDS_DESTRUCTOR (true_type))
- {
- tree extra = BI_header_size;
-
- size = size_binop (PLUS_EXPR, size, extra);
- }
-
- /* Allocate the object. */
- if (TYPE_LANG_SPECIFIC (true_type)
- && (TREE_GETS_NEW (true_type) && !use_global_new))
- rval = build_opfncall (NEW_EXPR, LOOKUP_NORMAL,
- TYPE_POINTER_TO (true_type), size, placement);
- else if (placement)
- {
- rval = build_opfncall (NEW_EXPR, LOOKUP_GLOBAL|LOOKUP_COMPLAIN,
- ptr_type_node, size, placement);
- rval = convert (TYPE_POINTER_TO (true_type), rval);
- }
- else if (flag_this_is_variable > 0
- && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
- {
- if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
- rval = NULL_TREE;
- else
- {
- error ("constructors take parameter lists");
- return error_mark_node;
- }
- }
- else
- {
- rval = build_builtin_call (build_pointer_type (true_type),
- BIN, build_tree_list (NULL_TREE, size));
-#if 0
- /* See comment above as to why this is disabled. */
- if (alignment)
- {
- rval = build (PLUS_EXPR, TYPE_POINTER_TO (true_type), rval,
- alignment);
- rval = build (BIT_AND_EXPR, TYPE_POINTER_TO (true_type),
- rval, build1 (BIT_NOT_EXPR, integer_type_node,
- alignment));
- }
-#endif
- TREE_CALLS_NEW (rval) = 1;
- TREE_SIDE_EFFECTS (rval) = 1;
- }
-
- /* if rval is NULL_TREE I don't have to allocate it, but are we totally
- sure we have some extra bytes in that case for the BI_header_size
- cookies? And how does that interact with the code below? (mrs) */
- /* Finish up some magic for new'ed arrays */
- if (has_array && TYPE_NEEDS_DESTRUCTOR (true_type) && rval != NULL_TREE)
- {
- tree extra = BI_header_size;
- tree cookie, exp1, exp2;
- rval = convert (ptr_type_node, rval); /* convert to void * first */
- rval = convert (string_type_node, rval); /* lets not add void* and ints */
- rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra, 1));
- /* Store header info. */
- cookie = build_indirect_ref (build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type),
- rval, extra), 0);
- exp1 = build (MODIFY_EXPR, void_type_node,
- build_component_ref (cookie, get_identifier ("nelts"), 0, 0),
- nelts);
- TREE_SIDE_EFFECTS (exp1) = 1;
- exp2 = build (MODIFY_EXPR, void_type_node,
- build_component_ref (cookie, get_identifier ("ptr_2comp"), 0, 0),
- build (MINUS_EXPR, ptr_type_node, integer_zero_node, rval));
- TREE_SIDE_EFFECTS (exp2) = 1;
- rval = convert (build_pointer_type (true_type), rval);
- TREE_CALLS_NEW (rval) = 1;
- TREE_SIDE_EFFECTS (rval) = 1;
- rval = build_compound_expr (tree_cons (NULL_TREE, exp1,
- tree_cons (NULL_TREE, exp2,
- build_tree_list (NULL_TREE, rval))));
- }
-
- /* We've figured out where the allocation is to go.
- If we're not eliding constructors, then if a constructor
- is defined, we must go through it. */
- if (!has_array && (rval == NULL_TREE || !flag_elide_constructors)
- && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
- {
- tree newrval;
- /* Constructors are never virtual. */
- int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL;
- /* If a copy constructor might work, set things up so that we can
- try that after this. */
- if (rval != NULL_TREE)
- flags = ~LOOKUP_COMPLAIN & (flags|LOOKUP_SPECULATIVELY);
-
- if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
- {
- init = tree_cons (NULL_TREE, integer_one_node, init);
- flags |= LOOKUP_HAS_IN_CHARGE;
- }
- newrval = build_method_call (rval, constructor_name (true_type),
- init, NULL_TREE, flags);
- if (newrval)
- {
- rval = newrval;
- TREE_HAS_CONSTRUCTOR (rval) = 1;
- goto done;
- }
- /* Didn't find the constructor, maybe it is a call to a copy constructor
- that we should implement. */
- }
-
- if (rval == error_mark_node)
- return error_mark_node;
- rval = save_expr (rval);
- TREE_HAS_CONSTRUCTOR (rval) = 1;
-
- /* Don't call any constructors or do any initialization. */
- if (init == void_type_node)
- goto done;
-
- if (TYPE_NEEDS_CONSTRUCTING (type)
- || (has_call || init))
- {
- extern tree static_aggregates;
-
- if (current_function_decl == NULL_TREE)
- {
- /* In case of static initialization, SAVE_EXPR is good enough. */
- init = copy_to_permanent (init);
- rval = copy_to_permanent (rval);
- static_aggregates = perm_tree_cons (init, rval, static_aggregates);
- }
- else
- {
- /* Have to wrap this in RTL_EXPR for two cases:
- in base or member initialization and if we
- are a branch of a ?: operator. Since we
- can't easily know the latter, just do it always. */
- tree xval = make_node (RTL_EXPR);
-
- TREE_TYPE (xval) = TREE_TYPE (rval);
- do_pending_stack_adjust ();
- start_sequence ();
-
- /* As a matter of principle, `start_sequence' should do this. */
- emit_note (0, -1);
-
- if (has_array)
- rval = expand_vec_init (decl, rval,
- build_binary_op (MINUS_EXPR, nelts, integer_one_node, 1),
- init, 0);
- else
- expand_aggr_init (build_indirect_ref (rval, 0), init, 0);
-
- do_pending_stack_adjust ();
-
- TREE_SIDE_EFFECTS (xval) = 1;
- TREE_CALLS_NEW (xval) = 1;
- RTL_EXPR_SEQUENCE (xval) = get_insns ();
- end_sequence ();
-
- if (TREE_CODE (rval) == SAVE_EXPR)
- {
- /* Errors may cause this to not get evaluated. */
- if (SAVE_EXPR_RTL (rval) == 0)
- SAVE_EXPR_RTL (rval) = const0_rtx;
- RTL_EXPR_RTL (xval) = SAVE_EXPR_RTL (rval);
- }
- else
- {
- my_friendly_assert (TREE_CODE (rval) == VAR_DECL, 217);
- RTL_EXPR_RTL (xval) = DECL_RTL (rval);
- }
- rval = xval;
- }
- }
-#if 0
- /* It would seem that the above code handles this better than the code
- below. (mrs) */
- else if (has_call || init)
- {
- if (IS_AGGR_TYPE (type))
- {
- /* default copy constructor may be missing from the below. (mrs) */
- error_with_aggr_type (type, "no constructor for type `%s'");
- rval = error_mark_node;
- }
- else
- {
- /* New 2.0 interpretation: `new int (10)' means
- allocate an int, and initialize it with 10. */
-
- init = build_c_cast (type, init);
- rval = build (COMPOUND_EXPR, TREE_TYPE (rval),
- build_modify_expr (build_indirect_ref (rval, 0),
- NOP_EXPR, init),
- rval);
- TREE_SIDE_EFFECTS (rval) = 1;
- }
- }
-#endif
- done:
- if (pending_sizes)
- rval = build_compound_expr (chainon (pending_sizes,
- build_tree_list (NULL_TREE, rval)));
-
- if (flag_gc)
- {
- extern tree gc_visible;
- tree objbits;
- tree update_expr;
-
- rval = save_expr (rval);
- /* We don't need a `headof' operation to do this because
- we know where the object starts. */
- objbits = build1 (INDIRECT_REF, unsigned_type_node,
- build (MINUS_EXPR, ptr_type_node,
- rval, c_sizeof_nowarn (unsigned_type_node)));
- update_expr = build_modify_expr (objbits, BIT_IOR_EXPR, gc_visible);
- rval = build_compound_expr (tree_cons (NULL_TREE, rval,
- tree_cons (NULL_TREE, update_expr,
- build_tree_list (NULL_TREE, rval))));
- }
-
- return save_expr (rval);
-}
-
-/* `expand_vec_init' performs initialization of a vector of aggregate
- types.
-
- DECL is passed only for error reporting, and provides line number
- and source file name information.
- BASE is the space where the vector will be.
- MAXINDEX is the maximum index of the array (one less than the
- number of elements).
- INIT is the (possibly NULL) initializer.
-
- FROM_ARRAY is 0 if we should init everything with INIT
- (i.e., every element initialized from INIT).
- FROM_ARRAY is 1 if we should index into INIT in parallel
- with initialization of DECL.
- FROM_ARRAY is 2 if we should index into INIT in parallel,
- but use assignment instead of initialization. */
-
-tree
-expand_vec_init (decl, base, maxindex, init, from_array)
- tree decl, base, maxindex, init;
- int from_array;
-{
- tree rval;
- tree iterator, base2 = NULL_TREE;
- tree type = TREE_TYPE (TREE_TYPE (base));
- tree size;
-
- maxindex = convert (integer_type_node, maxindex);
- if (maxindex == error_mark_node)
- return error_mark_node;
-
- if (current_function_decl == NULL_TREE)
- {
- rval = make_tree_vec (3);
- TREE_VEC_ELT (rval, 0) = base;
- TREE_VEC_ELT (rval, 1) = maxindex;
- TREE_VEC_ELT (rval, 2) = init;
- return rval;
- }
-
- size = size_in_bytes (type);
-
- /* Set to zero in case size is <= 0. Optimizer will delete this if
- it is not needed. */
- rval = get_temp_regvar (TYPE_POINTER_TO (type), convert (TYPE_POINTER_TO (type),
- null_pointer_node));
- base = default_conversion (base);
- base = convert (TYPE_POINTER_TO (type), base);
- expand_assignment (rval, base, 0, 0);
- base = get_temp_regvar (TYPE_POINTER_TO (type), base);
-
- if (init != NULL_TREE
- && TREE_CODE (init) == CONSTRUCTOR
- && TREE_TYPE (init) == TREE_TYPE (decl))
- {
- /* Initialization of array from {...}. */
- tree elts = CONSTRUCTOR_ELTS (init);
- tree baseref = build1 (INDIRECT_REF, type, base);
- tree baseinc = build (PLUS_EXPR, TYPE_POINTER_TO (type), base, size);
- int host_i = TREE_INT_CST_LOW (maxindex);
-
- if (IS_AGGR_TYPE (type))
- {
- while (elts)
- {
- host_i -= 1;
- expand_aggr_init (baseref, TREE_VALUE (elts), 0);
-
- expand_assignment (base, baseinc, 0, 0);
- elts = TREE_CHAIN (elts);
- }
- /* Initialize any elements by default if possible. */
- if (host_i >= 0)
- {
- if (TYPE_NEEDS_CONSTRUCTING (type) == 0)
- {
- if (obey_regdecls)
- use_variable (DECL_RTL (base));
- goto done_init;
- }
-
- iterator = get_temp_regvar (integer_type_node,
- build_int_2 (host_i, 0));
- init = NULL_TREE;
- goto init_by_default;
- }
- }
- else
- while (elts)
- {
- expand_assignment (baseref, TREE_VALUE (elts), 0, 0);
-
- expand_assignment (base, baseinc, 0, 0);
- elts = TREE_CHAIN (elts);
- }
-
- if (obey_regdecls)
- use_variable (DECL_RTL (base));
- }
- else
- {
- iterator = get_temp_regvar (integer_type_node, maxindex);
-
- init_by_default:
-
- /* If initializing one array from another,
- initialize element by element. */
- if (from_array)
- {
- if (decl == NULL_TREE
- || (init && !comptypes (TREE_TYPE (init), TREE_TYPE (decl), 1)))
- {
- sorry ("initialization of array from dissimilar array type");
- return error_mark_node;
- }
- if (init)
- {
- base2 = default_conversion (init);
- base2 = get_temp_regvar (TYPE_POINTER_TO (type), base2);
- }
- else if (TYPE_LANG_SPECIFIC (type)
- && TYPE_NEEDS_CONSTRUCTING (type)
- && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
- {
- error ("initializer ends prematurely");
- return error_mark_node;
- }
- }
-
- expand_start_cond (build (GE_EXPR, integer_type_node,
- iterator, integer_zero_node), 0);
- expand_start_loop_continue_elsewhere (1);
-
- if (from_array)
- {
- tree to = build1 (INDIRECT_REF, type, base);
- tree from;
-
- if (base2)
- from = build1 (INDIRECT_REF, type, base2);
- else
- from = NULL_TREE;
-
- if (from_array == 2)
- expand_expr_stmt (build_modify_expr (to, NOP_EXPR, from));
- else if (TYPE_NEEDS_CONSTRUCTING (type))
- expand_aggr_init (to, from, 0);
- else if (from)
- expand_assignment (to, from, 0, 0);
- else my_friendly_abort (57);
- }
- else if (TREE_CODE (type) == ARRAY_TYPE)
- {
- if (init != 0)
- sorry ("cannot initialize multi-dimensional array with initializer");
- expand_vec_init (decl, build1 (NOP_EXPR, TYPE_POINTER_TO (TREE_TYPE (type)), base),
- array_type_nelts (type), 0, 0);
- }
- else
- expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0);
-
- expand_assignment (base,
- build (PLUS_EXPR, TYPE_POINTER_TO (type), base, size),
- 0, 0);
- if (base2)
- expand_assignment (base2,
- build (PLUS_EXPR, TYPE_POINTER_TO (type), base2, size), 0, 0);
- expand_loop_continue_here ();
- expand_exit_loop_if_false (0, build (NE_EXPR, integer_type_node,
- build (PREDECREMENT_EXPR, integer_type_node, iterator, integer_one_node), minus_one));
-
- if (obey_regdecls)
- {
- use_variable (DECL_RTL (base));
- if (base2)
- use_variable (DECL_RTL (base2));
- }
- expand_end_loop ();
- expand_end_cond ();
- if (obey_regdecls)
- use_variable (DECL_RTL (iterator));
- }
- done_init:
-
- if (obey_regdecls)
- use_variable (DECL_RTL (rval));
- return rval;
-}
-
-/* Free up storage of type TYPE, at address ADDR.
-
- TYPE is a POINTER_TYPE and can be ptr_type_node for no special type
- of pointer.
-
- VIRTUAL_SIZE is the ammount of storage that was allocated, and is
- used as the second argument to operator delete. It can include
- things like padding and magic size cookies. It has virtual in it,
- because if you have a base pointer and you delete through a virtual
- destructor, it should be the size of the dynamic object, not the
- static object, see Free Store 12.5 ANSI C++ WP.
-
- This does not call any destructors. */
-tree
-build_x_delete (type, addr, use_global_delete, virtual_size)
- tree type, addr;
- int use_global_delete;
- tree virtual_size;
-{
- tree rval;
-
- if (!use_global_delete
- && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
- && TREE_GETS_DELETE (TREE_TYPE (type)))
- rval = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE);
- else
- rval = build_builtin_call (void_type_node, BID,
- tree_cons (NULL_TREE, addr,
- build_tree_list (NULL_TREE,
- virtual_size)));
- return rval;
-}
-
-/* Objects returned by `build_new' may point to just what the user
- requested (in the case of `new X'), or they may have a cookie
- consisting of a special value (the two's complement of the pointer
- address) and the number of elements allocated (in the case of
- `new X[N]'. In the latter case, we need to adjust the pointer
- that's passed back to the storage allocator. */
-
-static tree
-maybe_adjust_addr_for_delete (addr)
- tree addr;
-{
- tree cookie_addr;
- tree cookie;
- tree adjusted_addr, ptr_2comp;
-
- if (TREE_SIDE_EFFECTS (addr))
- addr = save_expr (addr);
-
- cookie_addr = build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type),
- addr, BI_header_size);
- cookie = build_indirect_ref (cookie_addr, 0);
-
- ptr_2comp = build_component_ref (cookie, get_identifier ("ptr_2comp"), 0, 0);
- adjusted_addr = save_expr (build (MINUS_EXPR, TREE_TYPE (addr), addr, BI_header_size));
-
- /* We must zero out the storage here because if the memory is freed,
- then later reallocated, we might get a false positive when the
- address is reused. */
- adjusted_addr = build_compound_expr (tree_cons (NULL_TREE,
- build_modify_expr (ptr_2comp, NOP_EXPR, null_pointer_node),
- build_tree_list (NULL_TREE, adjusted_addr)));
-
- addr = build (COND_EXPR, TREE_TYPE (addr),
- build (TRUTH_ORIF_EXPR, integer_type_node,
- build (EQ_EXPR, integer_type_node,
- addr, integer_zero_node),
- build (PLUS_EXPR, integer_type_node,
- convert (ptr_type_node, addr), ptr_2comp)),
- addr,
- adjusted_addr);
- return addr;
-}
-
-/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
- ADDR is an expression which yields the store to be destroyed.
- AUTO_DELETE is nonzero if a call to DELETE should be made or not.
- If in the program, (AUTO_DELETE & 2) is non-zero, we tear down the
- virtual baseclasses.
- If in the program, (AUTO_DELETE & 1) is non-zero, then we deallocate.
-
- FLAGS is the logical disjunction of zero or more LOOKUP_
- flags. See cp-tree.h for more info.
-
- MAYBE_ADJUST is nonzero iff we may need to adjust the address
- of the object being deleted before calling `operator delete'.
- This can happen when a user allocates an array with `operator new'
- and simply calls delete. Ideally this is unnecessary, but there
- is much code that does `p = new char[n]; ... delete p;' and this code
- would crash otherwise.
-
- This function does not delete an object's virtual base classes. */
-tree
-build_delete (type, addr, auto_delete, flags, use_global_delete, maybe_adjust)
- tree type, addr;
- tree auto_delete;
- int flags;
- int use_global_delete;
- int maybe_adjust;
-{
- tree function, parms;
- tree member;
- tree expr;
- tree ref;
- int ptr;
-
- if (addr == error_mark_node)
- return error_mark_node;
-
- /* Can happen when CURRENT_EXCEPTION_OBJECT gets its type
- set to `error_mark_node' before it gets properly cleaned up. */
- if (type == error_mark_node)
- return error_mark_node;
-
- type = TYPE_MAIN_VARIANT (type);
-
- if (TREE_CODE (type) == POINTER_TYPE)
- {
- type = TREE_TYPE (type);
- if (TYPE_SIZE (type) == 0)
- {
- incomplete_type_error (0, type);
- return error_mark_node;
- }
- if (TREE_CODE (type) == ARRAY_TYPE)
- goto handle_array;
- if (! IS_AGGR_TYPE (type))
- {
- tree virtual_size;
-
- /* This is probably wrong. It should be the size of the virtual
- object being deleted. */
- virtual_size = c_sizeof_nowarn (type);
-
- if (maybe_adjust)
- addr = maybe_adjust_addr_for_delete (addr);
- return build_builtin_call (void_type_node, BID,
- tree_cons (NULL_TREE, addr,
- build_tree_list (NULL_TREE, virtual_size)));
- }
- if (TREE_SIDE_EFFECTS (addr))
- addr = save_expr (addr);
- ref = build_indirect_ref (addr, 0);
- ptr = 1;
- }
- else if (TREE_CODE (type) == ARRAY_TYPE)
- {
- handle_array:
- if (TREE_SIDE_EFFECTS (addr))
- addr = save_expr (addr);
- return build_vec_delete (addr, array_type_nelts (type),
- c_sizeof_nowarn (TREE_TYPE (type)),
- NULL_TREE, auto_delete, integer_two_node);
- }
- else
- {
- /* Don't check PROTECT here; leave that decision to the
- destructor. If the destructor is visible, call it,
- else report error. */
- addr = build_unary_op (ADDR_EXPR, addr, 0);
- if (TREE_SIDE_EFFECTS (addr))
- addr = save_expr (addr);
-
- if (TREE_CONSTANT (addr))
- addr = convert_pointer_to (type, addr);
- else
- addr = convert_force (build_pointer_type (type), addr);
-
- if (TREE_CODE (addr) == NOP_EXPR
- && TREE_OPERAND (addr, 0) == current_class_decl)
- ref = C_C_D;
- else
- ref = build_indirect_ref (addr, 0);
- ptr = 0;
- }
-
- my_friendly_assert (IS_AGGR_TYPE (type), 220);
-
- if (! TYPE_NEEDS_DESTRUCTOR (type))
- {
- tree virtual_size;
-
- /* This is probably wrong. It should be the size of the virtual object
- being deleted. */
- virtual_size = c_sizeof_nowarn (type);
-
- if (auto_delete == integer_zero_node)
- return void_zero_node;
- if (maybe_adjust && addr != current_class_decl)
- addr = maybe_adjust_addr_for_delete (addr);
- if (TREE_GETS_DELETE (type) && !use_global_delete)
- return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE);
- return build_builtin_call (void_type_node, BID,
- tree_cons (NULL_TREE, addr,
- build_tree_list (NULL_TREE, virtual_size)));
- }
- parms = build_tree_list (NULL_TREE, addr);
-
- /* Below, we will reverse the order in which these calls are made.
- If we have a destructor, then that destructor will take care
- of the base classes; otherwise, we must do that here. */
- if (TYPE_HAS_DESTRUCTOR (type))
- {
- tree dtor = DECL_MAIN_VARIANT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0));
- tree basetypes = TYPE_BINFO (type);
-
- if (flags & LOOKUP_PROTECT)
- {
- enum visibility_type visibility = compute_visibility (basetypes, dtor);
-
- if (visibility == visibility_private)
- {
- if (flags & LOOKUP_COMPLAIN)
- error_with_aggr_type (type, "destructor for type `%s' is private in this scope");
- return error_mark_node;
- }
- else if (visibility == visibility_protected
- && (flags & LOOKUP_PROTECTED_OK) == 0)
- {
- if (flags & LOOKUP_COMPLAIN)
- error_with_aggr_type (type, "destructor for type `%s' is protected in this scope");
- return error_mark_node;
- }
- }
-
- /* Once we are in a destructor, try not going through
- the virtual function table to find the next destructor. */
- if (DECL_VINDEX (dtor)
- && ! (flags & LOOKUP_NONVIRTUAL)
- && TREE_CODE (auto_delete) != PARM_DECL
- && (ptr == 1 || ! resolves_to_fixed_type_p (ref, 0)))
- {
- /* This destructor must be called via virtual function table. */
- dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (DECL_CONTEXT (dtor)), 0);
- expr = convert_pointer_to (DECL_CLASS_CONTEXT (dtor), TREE_VALUE (parms));
- if (expr != TREE_VALUE (parms))
- {
- expr = fold (expr);
- ref = build_indirect_ref (expr, 0);
- TREE_VALUE (parms) = expr;
- }
- function = build_vfn_ref (&TREE_VALUE (parms), ref, DECL_VINDEX (dtor));
- if (function == error_mark_node)
- return error_mark_node;
- TREE_TYPE (function) = build_pointer_type (TREE_TYPE (dtor));
- TREE_CHAIN (parms) = build_tree_list (NULL_TREE, auto_delete);
- expr = build_function_call (function, parms);
- if (ptr && (flags & LOOKUP_DESTRUCTOR) == 0)
- {
- /* Handle the case where a virtual destructor is
- being called on an item that is 0.
-
- @@ Does this really need to be done? */
- tree ifexp = build_binary_op(NE_EXPR, addr, integer_zero_node,1);
-#if 0
- if (TREE_CODE (ref) == VAR_DECL
- || TREE_CODE (ref) == COMPONENT_REF)
- warning ("losing in build_delete");
-#endif
- expr = build (COND_EXPR, void_type_node,
- ifexp, expr, void_zero_node);
- }
- }
- else
- {
- tree ifexp;
-
- if ((flags & LOOKUP_DESTRUCTOR)
- || TREE_CODE (ref) == VAR_DECL
- || TREE_CODE (ref) == PARM_DECL
- || TREE_CODE (ref) == COMPONENT_REF
- || TREE_CODE (ref) == ARRAY_REF)
- /* These can't be 0. */
- ifexp = integer_one_node;
- else
- /* Handle the case where a non-virtual destructor is
- being called on an item that is 0. */
- ifexp = build_binary_op (NE_EXPR, addr, integer_zero_node, 1);
-
- /* Used to mean that this destructor was known to be empty,
- but that's now obsolete. */
- my_friendly_assert (DECL_INITIAL (dtor) != void_type_node, 221);
-
- TREE_CHAIN (parms) = build_tree_list (NULL_TREE, auto_delete);
- expr = build_function_call (dtor, parms);
-
- if (ifexp != integer_one_node)
- expr = build (COND_EXPR, void_type_node,
- ifexp, expr, void_zero_node);
- }
- return expr;
- }
- else
- {
- /* This can get visibilities wrong. */
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE;
- tree exprstmt = NULL_TREE;
- tree parent_auto_delete = auto_delete;
- tree cond;
-
- /* If this type does not have a destructor, but does have
- operator delete, call the parent parent destructor (if any),
- but let this node do the deleting. Otherwise, it is ok
- to let the parent destructor do the deleting. */
- if (TREE_GETS_DELETE (type) && !use_global_delete)
- {
- parent_auto_delete = integer_zero_node;
- if (auto_delete == integer_zero_node)
- cond = NULL_TREE;
- else
- {
- tree virtual_size;
-
- /* This is probably wrong. It should be the size of the
- virtual object being deleted. */
- virtual_size = c_sizeof_nowarn (type);
-
- expr = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
- virtual_size, NULL_TREE);
- if (expr == error_mark_node)
- return error_mark_node;
- if (auto_delete != integer_one_node)
- cond = build (COND_EXPR, void_type_node,
- build (BIT_AND_EXPR, integer_type_node,
- auto_delete, integer_one_node),
- expr, void_zero_node);
- else cond = expr;
- }
- }
- else if (base_binfo == NULL_TREE
- || (TREE_VIA_VIRTUAL (base_binfo) == 0
- && ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))))
- {
- tree virtual_size;
-
- /* This is probably wrong. It should be the size of the virtual
- object being deleted. */
- virtual_size = c_sizeof_nowarn (type);
-
- cond = build (COND_EXPR, void_type_node,
- build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node),
- build_builtin_call (void_type_node, BID,
- tree_cons (NULL_TREE, addr,
- build_tree_list (NULL_TREE, virtual_size))),
- void_zero_node);
- }
- else cond = NULL_TREE;
-
- if (cond)
- exprstmt = build_tree_list (NULL_TREE, cond);
-
- if (base_binfo
- && ! TREE_VIA_VIRTUAL (base_binfo)
- && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
- {
- tree this_auto_delete;
-
- if (BINFO_OFFSET_ZEROP (base_binfo))
- this_auto_delete = parent_auto_delete;
- else
- this_auto_delete = integer_zero_node;
-
- expr = build_delete (TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), addr,
- this_auto_delete, flags|LOOKUP_PROTECTED_OK, 0, 0);
- exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
- }
-
- /* Take care of the remaining baseclasses. */
- for (i = 1; i < n_baseclasses; i++)
- {
- base_binfo = TREE_VEC_ELT (binfos, i);
- if (! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))
- || TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- /* May be zero offset if other baseclasses are virtual. */
- expr = fold (build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
- addr, BINFO_OFFSET (base_binfo)));
-
- expr = build_delete (TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), expr,
- integer_zero_node,
- flags|LOOKUP_PROTECTED_OK, 0, 0);
-
- exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
- }
-
- for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
- {
- if (TREE_CODE (member) != FIELD_DECL)
- continue;
- if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (member)))
- {
- tree this_member = build_component_ref (ref, DECL_NAME (member), 0, 0);
- tree this_type = TREE_TYPE (member);
- expr = build_delete (this_type, this_member, integer_two_node, flags, 0, 0);
- exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
- }
- }
-
- if (exprstmt)
- return build_compound_expr (exprstmt);
- /* Virtual base classes make this function do nothing. */
- return void_zero_node;
- }
-}
-
-/* For type TYPE, delete the virtual baseclass objects of DECL. */
-
-tree
-build_vbase_delete (type, decl)
- tree type, decl;
-{
- tree vbases = CLASSTYPE_VBASECLASSES (type);
- tree result = NULL_TREE;
- tree addr = build_unary_op (ADDR_EXPR, decl, 0);
- my_friendly_assert (addr != error_mark_node, 222);
- while (vbases)
- {
- tree this_addr = convert_force (TYPE_POINTER_TO (BINFO_TYPE (vbases)), addr);
- result = tree_cons (NULL_TREE,
- build_delete (TREE_TYPE (this_addr), this_addr,
- integer_zero_node,
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0),
- result);
- vbases = TREE_CHAIN (vbases);
- }
- return build_compound_expr (nreverse (result));
-}
-
-/* Build a C++ vector delete expression.
- MAXINDEX is the number of elements to be deleted.
- ELT_SIZE is the nominal size of each element in the vector.
- BASE is the expression that should yield the store to be deleted.
- DTOR_DUMMY is a placeholder for a destructor. The library function
- __builtin_vec_delete has a pointer to function in this position.
- This function expands (or synthesizes) these calls itself.
- AUTO_DELETE_VEC says whether the container (vector) should be deallocated.
- AUTO_DELETE say whether each item in the container should be deallocated.
-
- This also calls delete for virtual baseclasses of elements of the vector.
-
- Update: MAXINDEX is no longer needed. The size can be extracted from the
- start of the vector for pointers, and from the type for arrays. We still
- use MAXINDEX for arrays because it happens to already have one of the
- values we'd have to extract. (We could use MAXINDEX with pointers to
- confirm the size, and trap if the numbers differ; not clear that it'd
- be worth bothering.) */
-tree
-build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_delete)
- tree base, maxindex, elt_size;
- tree dtor_dummy;
- tree auto_delete_vec, auto_delete;
-{
- tree ptype = TREE_TYPE (base);
- tree type;
- tree virtual_size;
- /* Temporary variables used by the loop. */
- tree tbase, size_exp, tbase_init;
-
- /* This is the body of the loop that implements the deletion of a
- single element, and moves temp variables to next elements. */
- tree body;
-
- /* This is the LOOP_EXPR that governs the deletion of the elements. */
- tree loop;
-
- /* This is the thing that governs what to do after the loop has run. */
- tree deallocate_expr = 0;
-
- /* This is the BIND_EXPR which holds the outermost iterator of the
- loop. It is convenient to set this variable up and test it before
- executing any other code in the loop.
- This is also the containing expression returned by this function. */
- tree controller = NULL_TREE;
-
- /* This is the BLOCK to record the symbol binding for debugging. */
- tree block;
-
- base = stabilize_reference (base);
-
- /* Since we can use base many times, save_epr it. */
- if (TREE_SIDE_EFFECTS (base))
- base = save_expr (base);
-
- if (TREE_CODE (ptype) == POINTER_TYPE)
- {
- /* Step back one from start of vector, and read dimension. */
- tree cookie_addr = build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type),
- base, BI_header_size);
- tree cookie = build_indirect_ref (cookie_addr, 0);
- maxindex = build_component_ref (cookie, get_identifier ("nelts"), 0, 0);
- do
- ptype = TREE_TYPE (ptype);
- while (TREE_CODE (ptype) == ARRAY_TYPE);
- }
- else if (TREE_CODE (ptype) == ARRAY_TYPE)
- {
- /* get the total number of things in the array, maxindex is a bad name */
- maxindex = array_type_nelts_total (ptype);
- while (TREE_CODE (ptype) == ARRAY_TYPE)
- ptype = TREE_TYPE (ptype);
- base = build_unary_op (ADDR_EXPR, base, 1);
- }
- else
- {
- error ("type to vector delete is neither pointer or array type");
- return error_mark_node;
- }
- type = ptype;
- ptype = TYPE_POINTER_TO (type);
-
- size_exp = size_in_bytes (type);
-
- if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type))
- {
- loop = integer_zero_node;
- goto no_destructor;
- }
-
- /* The below is short by BI_header_size */
- virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
-
- tbase = build_decl (VAR_DECL, NULL_TREE, ptype);
- tbase_init = build_modify_expr (tbase, NOP_EXPR,
- fold (build (PLUS_EXPR, ptype,
- base,
- virtual_size)));
- DECL_REGISTER (tbase) = 1;
- controller = build (BIND_EXPR, void_type_node, tbase, 0, 0);
- TREE_SIDE_EFFECTS (controller) = 1;
- block = build_block (tbase, 0, 0, 0, 0);
- add_block_current_level (block);
-
- if (auto_delete != integer_zero_node
- && auto_delete != integer_two_node)
- {
- tree base_tbd = convert (ptype,
- build_binary_op (MINUS_EXPR,
- convert (ptr_type_node, base),
- BI_header_size,
- 1));
- /* This is the real size */
- virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
- body = build_tree_list (NULL_TREE,
- build_x_delete (ptr_type_node, base_tbd, 0,
- virtual_size));
- body = build (COND_EXPR, void_type_node,
- build (BIT_AND_EXPR, integer_type_node,
- auto_delete, integer_one_node),
- body, integer_zero_node);
- }
- else
- body = NULL_TREE;
-
- body = tree_cons (NULL_TREE,
- build_delete (ptype, tbase, auto_delete,
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0),
- body);
-
- body = tree_cons (NULL_TREE,
- build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
- body);
-
- body = tree_cons (NULL_TREE,
- build (EXIT_EXPR, void_type_node,
- build (EQ_EXPR, integer_type_node, base, tbase)),
- body);
-
- loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
-
- loop = tree_cons (NULL_TREE, tbase_init,
- tree_cons (NULL_TREE, loop, NULL_TREE));
- loop = build_compound_expr (loop);
-
- no_destructor:
- /* If the delete flag is one, or anything else with the low bit set,
- delete the storage. */
- if (auto_delete_vec == integer_zero_node
- || auto_delete_vec == integer_two_node)
- deallocate_expr = integer_zero_node;
- else
- {
- tree base_tbd;
-
- /* The below is short by BI_header_size */
- virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
-
- if (loop == integer_zero_node)
- /* no header */
- base_tbd = base;
- else
- {
- base_tbd = convert (ptype,
- build_binary_op (MINUS_EXPR,
- convert (string_type_node, base),
- BI_header_size,
- 1));
- /* True size with header. */
- virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
- }
- deallocate_expr = build_x_delete (ptr_type_node, base_tbd, 1,
- virtual_size);
- if (auto_delete_vec != integer_one_node)
- deallocate_expr = build (COND_EXPR, void_type_node,
- build (BIT_AND_EXPR, integer_type_node,
- auto_delete_vec, integer_one_node),
- deallocate_expr, integer_zero_node);
- }
-
- if (loop && deallocate_expr != integer_zero_node)
- {
- body = tree_cons (NULL_TREE, loop,
- tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
- body = build_compound_expr (body);
- }
- else
- body = loop;
-
- /* Outermost wrapper: If pointer is null, punt. */
- body = build (COND_EXPR, void_type_node,
- build (NE_EXPR, integer_type_node, base, integer_zero_node),
- body, integer_zero_node);
-
- if (controller)
- {
- TREE_OPERAND (controller, 1) = body;
- return controller;
- }
- else
- return convert (void_type_node, body);
-}
diff --git a/gnu/gcc2/cc1plus/cp-input.c b/gnu/gcc2/cc1plus/cp-input.c
deleted file mode 100644
index 1252aed187a8..000000000000
--- a/gnu/gcc2/cc1plus/cp-input.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Input handling for G++.
- Copyright (C) 1992, 1993 Free Software Foundation, Inc.
- Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
-
-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. */
-
-/* G++ needs to do enough saving and re-parsing of text that it is
- necessary to abandon the simple FILE* model and use a mechanism where
- we can pre-empt one input stream with another derived from saved text;
- we may need to do this arbitrarily often, and cannot depend on having
- the GNU library available, so FILE objects just don't cut it.
-
- This file is written as a separate module, but can be included by
- cp-lex.c for very minor efficiency gains (primarily in function
- inlining). */
-
-#include <stdio.h>
-#include "obstack.h"
-
-extern FILE *finput;
-
-struct pending_input *save_pending_input ();
-void restore_pending_input ();
-
-struct input_source {
- /* saved string */
- char *str;
- int length;
- /* current position, when reading as input */
- int offset;
- /* obstack to free this input string from when finished, if any */
- struct obstack *obstack;
- /* linked list maintenance */
- struct input_source *next;
- /* values to restore after reading all of current string */
- char *filename;
- int lineno;
- struct pending_input *input;
- int putback_char;
-};
-
-static struct input_source *input, *free_inputs;
-
-extern char *input_filename;
-extern int lineno;
-
-#ifdef __GNUC__
-#define inline __inline__
-#else
-#define inline
-#endif
-
-static inline struct input_source *
-allocate_input ()
-{
- struct input_source *inp;
- if (free_inputs)
- {
- inp = free_inputs;
- free_inputs = inp->next;
- inp->next = 0;
- return inp;
- }
- inp = (struct input_source *) xmalloc (sizeof (struct input_source));
- inp->next = 0;
- inp->obstack = 0;
- return inp;
-}
-
-static inline void
-free_input (inp)
- struct input_source *inp;
-{
- if (inp->obstack)
- obstack_free (inp->obstack, inp->str);
- inp->obstack = 0;
- inp->str = 0;
- inp->length = 0;
- inp->next = free_inputs;
- free_inputs = inp;
-}
-
-static int putback_char = -1;
-
-/* Some of these external functions are declared inline in case this file
- is included in cp-lex.c. */
-
-inline
-void
-feed_input (str, len, delete)
- char *str;
- int len;
- struct obstack *delete;
-{
- struct input_source *inp = allocate_input ();
-
- /* This shouldn't be necessary. */
- while (len && !str[len-1])
- len--;
-
- inp->str = str;
- inp->length = len;
- inp->obstack = delete;
- inp->offset = 0;
- inp->next = input;
- inp->filename = input_filename;
- inp->lineno = lineno;
- inp->input = save_pending_input ();
- inp->putback_char = putback_char;
- putback_char = -1;
- input = inp;
-}
-
-struct pending_input *to_be_restored; /* XXX */
-extern int end_of_file;
-
-int
-getch ()
-{
- if (putback_char != -1)
- {
- int ch = putback_char;
- putback_char = -1;
- return ch;
- }
- if (input)
- {
- if (input->offset == input->length)
- {
- struct input_source *inp = input;
- my_friendly_assert (putback_char == -1, 223);
- to_be_restored = inp->input;
- input->offset++;
- return EOF;
- }
- else if (input->offset > input->length)
- {
- struct input_source *inp = input;
-
- end_of_file = 0;
- input = inp->next;
- input_filename = inp->filename;
- lineno = inp->lineno;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- putback_char = inp->putback_char;
- free_input (inp);
- return getch ();
- }
- if (input)
- return input->str[input->offset++];
- }
- return getc (finput);
-}
-
-inline
-void
-put_back (ch)
- int ch;
-{
- my_friendly_assert (putback_char == -1, 224);
- putback_char = ch;
-}
-
-inline
-int
-input_redirected ()
-{
- return input != 0;
-}
diff --git a/gnu/gcc2/cc1plus/cp-lex.c b/gnu/gcc2/cc1plus/cp-lex.c
deleted file mode 100644
index 81e9047d0150..000000000000
--- a/gnu/gcc2/cc1plus/cp-lex.c
+++ /dev/null
@@ -1,4232 +0,0 @@
-/* Separate lexical analyzer for GNU C++.
- Copyright (C) 1987, 1989, 1992, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-
-/* This file is the lexical analyzer for GNU C++. */
-
-#if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG)
-#undef YYDEBUG
-#define YYDEBUG 1
-#endif
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <errno.h>
-#include <setjmp.h>
-#include "config.h"
-#include "input.h"
-#include "tree.h"
-#include "cp-lex.h"
-#include "cp-parse.h"
-#include "cp-tree.h"
-#include "flags.h"
-#include "obstack.h"
-
-#ifdef MULTIBYTE_CHARS
-#include <stdlib.h>
-#include <locale.h>
-#endif
-
-#ifndef errno
-extern int errno; /* needed for VAX. */
-#endif
-extern jmp_buf toplevel;
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-extern struct obstack *expression_obstack, permanent_obstack;
-extern struct obstack *current_obstack, *saveable_obstack;
-
-extern double atof ();
-
-extern char *get_directive_line (); /* In c-common.c */
-
-/* Given a file name X, return the nondirectory portion.
- Keep in mind that X can be computed more than once. */
-#ifndef FILE_NAME_NONDIRECTORY
-#define FILE_NAME_NONDIRECTORY(X) \
- (rindex (X, '/') != 0 ? rindex (X, '/') + 1 : X)
-#endif
-
-extern char *index ();
-extern char *rindex ();
-
-void extract_interface_info ();
-void yyerror ();
-
-/* This obstack is needed to hold text. It is not safe to use
- TOKEN_BUFFER because `check_newline' calls `yylex'. */
-static struct obstack inline_text_obstack;
-static char *inline_text_firstobj;
-
-int end_of_file;
-
-extern int first_token;
-extern struct obstack token_obstack;
-
-/* ??? Don't really know where this goes yet. */
-#if 1
-#include "cp-input.c"
-#else
-extern void put_back (/* int */);
-extern int input_redirected ();
-extern void feed_input (/* char *, int, struct obstack * */);
-#endif
-
-/* Holds translations from TREE_CODEs to operator name strings,
- i.e., opname_tab[PLUS_EXPR] == "+". */
-char **opname_tab;
-char **assignop_tab;
-
-extern int yychar; /* the lookahead symbol */
-extern YYSTYPE yylval; /* the semantic value of the */
- /* lookahead symbol */
-
-#if 0
-YYLTYPE yylloc; /* location data for the lookahead */
- /* symbol */
-#endif
-
-
-/* the declaration found for the last IDENTIFIER token read in.
- yylex must look this up to detect typedefs, which get token type TYPENAME,
- so it is left around in case the identifier is not a typedef but is
- used in a context which makes it a reference to a variable. */
-tree lastiddecl;
-
-/* The elements of `ridpointers' are identifier nodes
- for the reserved type names and storage classes.
- It is indexed by a RID_... value. */
-tree ridpointers[(int) RID_MAX];
-
-/* We may keep statistics about how long which files took to compile. */
-static int header_time, body_time;
-static tree get_time_identifier ();
-static tree filename_times;
-static tree this_filename_time;
-
-/* For implementing #pragma unit. */
-tree current_unit_name;
-tree current_unit_language;
-
-/* Array for holding counts of the numbers of tokens seen. */
-extern int *token_count;
-
-/* Textual definition used for default functions. */
-static char default_def[] = "{}";
-
-/* Return something to represent absolute declarators containing a *.
- TARGET is the absolute declarator that the * contains.
- TYPE_QUALS is a list of modifiers such as const or volatile
- to apply to the pointer type, represented as identifiers.
-
- We return an INDIRECT_REF whose "contents" are TARGET
- and whose type is the modifier list. */
-
-tree
-make_pointer_declarator (type_quals, target)
- tree type_quals, target;
-{
- if (target && TREE_CODE (target) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (target))
- error ("type name expected before `*'");
- target = build_parse_node (INDIRECT_REF, target);
- TREE_TYPE (target) = type_quals;
- return target;
-}
-
-/* Return something to represent absolute declarators containing a &.
- TARGET is the absolute declarator that the & contains.
- TYPE_QUALS is a list of modifiers such as const or volatile
- to apply to the reference type, represented as identifiers.
-
- We return an ADDR_EXPR whose "contents" are TARGET
- and whose type is the modifier list. */
-
-tree
-make_reference_declarator (type_quals, target)
- tree type_quals, target;
-{
- if (target)
- {
- if (TREE_CODE (target) == ADDR_EXPR)
- {
- error ("cannot declare references to references");
- return target;
- }
- if (TREE_CODE (target) == INDIRECT_REF)
- {
- error ("cannot declare pointers to references");
- return target;
- }
- if (TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target))
- error ("type name expected before `&'");
- }
- target = build_parse_node (ADDR_EXPR, target);
- TREE_TYPE (target) = type_quals;
- return target;
-}
-
-/* Build names and nodes for overloaded operators. */
-
-tree ansi_opname[LAST_CPLUS_TREE_CODE];
-tree ansi_assopname[LAST_CPLUS_TREE_CODE];
-
-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 += 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];
-}
-
-int interface_only; /* whether or not current file is only for
- interface definitions. */
-int interface_unknown; /* whether or not we know this class
- to behave according to #pragma interface. */
-
-/* lexical analyzer */
-
-/* File used for outputting assembler code. */
-extern FILE *asm_out_file;
-
-#ifndef WCHAR_TYPE_SIZE
-#ifdef INT_TYPE_SIZE
-#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
-#else
-#define WCHAR_TYPE_SIZE BITS_PER_WORD
-#endif
-#endif
-
-/* Number of bytes in a wide character. */
-#define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)
-
-static int maxtoken; /* Current nominal length of token buffer. */
-char *token_buffer; /* Pointer to token buffer.
- Actual allocated length is maxtoken + 2. */
-
-#include "cp-hash.h"
-
-int check_newline ();
-
-/* Nonzero tells yylex to ignore \ in string constants. */
-static int ignore_escape_flag = 0;
-
-static int skip_white_space ();
-
-static tree
-get_time_identifier (name)
- char *name;
-{
- tree time_identifier;
- int len = strlen (name);
- char *buf = (char *)alloca (len + 6);
- strcpy (buf, "file ");
- bcopy (name, buf+5, len);
- buf[len+5] = '\0';
- time_identifier = get_identifier (buf);
- if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
- IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
- IDENTIFIER_GLOBAL_VALUE (time_identifier) = filename_times;
- filename_times = time_identifier;
- pop_obstacks ();
- }
- return time_identifier;
-}
-
-#ifdef __GNUC__
-__inline
-#endif
-static int
-my_get_run_time ()
-{
- int old_quiet_flag = quiet_flag;
- int this_time;
- quiet_flag = 0;
- this_time = get_run_time ();
- quiet_flag = old_quiet_flag;
- return this_time;
-}
-
-/* Table indexed by tree code giving a string containing a character
- classifying the tree code. Possibilities are
- t, d, s, c, r, <, 1 and 2. See cp-tree.def for details. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
-
-char *cplus_tree_code_type[] = {
- "x",
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
-
-/* Table indexed by tree code giving number of expression
- operands beyond the fixed part of the node structure.
- Not used for types or decls. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
-
-int cplus_tree_code_length[] = {
- 0,
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
-
-/* Names of tree components.
- Used for printing out the tree and error messages. */
-#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-
-char *cplus_tree_code_name[] = {
- "@@dummy",
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
-
-/* toplev.c needs to call these. */
-
-void
-lang_init ()
-{
- /* the beginning of the file is a new line; check for # */
- /* With luck, we discover the real source file's name from that
- and put it in input_filename. */
- put_back (check_newline ());
-
- if (flag_cadillac)
- cadillac_start ();
- if (flag_gnu_xref) GNU_xref_begin (input_filename);
-}
-
-void
-lang_finish ()
-{
- extern int errorcount, sorrycount;
- if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount);
-}
-
-char *
-lang_identify ()
-{
- return "cplusplus";
-}
-
-void
-init_filename_times ()
-{
- this_filename_time = get_time_identifier ("<top level>");
- if (flag_detailed_statistics)
- {
- header_time = 0;
- body_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
- }
-}
-
-/* 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_lex if we are an unexec'd binary. */
-void
-reinit_lang_specific ()
-{
- init_filename_times ();
- reinit_search_statistics ();
-}
-
-void
-init_lex ()
-{
- extern char *(*decl_printable_name) ();
-
- int i;
-
- /* Initialize the lookahead machinery. */
- init_spew ();
-
- /* Make identifier nodes long enough for the language-specific slots. */
- set_identifier_size (sizeof (struct lang_identifier));
- decl_printable_name = lang_printable_name;
-
- init_cplus_expand ();
-
- tree_code_type
- = (char **) realloc (tree_code_type,
- sizeof (char *) * LAST_CPLUS_TREE_CODE);
- tree_code_length
- = (int *) realloc (tree_code_length,
- sizeof (int) * LAST_CPLUS_TREE_CODE);
- tree_code_name
- = (char **) realloc (tree_code_name,
- sizeof (char *) * LAST_CPLUS_TREE_CODE);
- bcopy ((char *)cplus_tree_code_type,
- (char *)(tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE),
- (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
- bcopy ((char *)cplus_tree_code_length,
- (char *)(tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE),
- (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
- bcopy ((char *)cplus_tree_code_name,
- (char *)(tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE),
- (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
-
- opname_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
- bzero ((char *)opname_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
- assignop_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
- bzero ((char *)assignop_tab, (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) TYPE_EXPR] = get_identifier ("__op");
- 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) METHOD_CALL_EXPR] = get_identifier ("__wr");
- IDENTIFIER_OPNAME_P (ansi_opname[(int) METHOD_CALL_EXPR]) = 1;
-
- init_method ();
- gcc_obstack_init (&inline_text_obstack);
- inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
-
- /* Start it at 0, because check_newline is called at the very beginning
- and will increment it to 1. */
- lineno = 0;
- current_function_decl = NULL;
-
- maxtoken = 40;
- token_buffer = (char *) xmalloc (maxtoken + 2);
-
- ridpointers[(int) RID_INT] = get_identifier ("int");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]));
- ridpointers[(int) RID_CHAR] = get_identifier ("char");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]));
- ridpointers[(int) RID_VOID] = get_identifier ("void");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOID],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]));
- ridpointers[(int) RID_FLOAT] = get_identifier ("float");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FLOAT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_FLOAT]));
- ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_DOUBLE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_DOUBLE]));
- ridpointers[(int) RID_SHORT] = get_identifier ("short");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SHORT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_SHORT]));
- ridpointers[(int) RID_LONG] = get_identifier ("long");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_LONG],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]));
- ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_UNSIGNED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]));
- ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SIGNED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_SIGNED]));
- ridpointers[(int) RID_INLINE] = get_identifier ("inline");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INLINE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_INLINE]));
- ridpointers[(int) RID_CONST] = get_identifier ("const");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CONST],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_CONST]));
- ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
- ridpointers[(int) RID_AUTO] = get_identifier ("auto");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
- ridpointers[(int) RID_STATIC] = get_identifier ("static");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_STATIC],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]));
- ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXTERN],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]));
- ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TYPEDEF],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_TYPEDEF]));
- ridpointers[(int) RID_REGISTER] = get_identifier ("register");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
-
- /* C++ extensions. These are probably not correctly named. */
- ridpointers[(int) RID_WCHAR] = get_identifier ("__wchar_t");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_WCHAR],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_WCHAR]));
- class_type_node = build_int_2 (class_type, 0);
- TREE_TYPE (class_type_node) = class_type_node;
- ridpointers[(int) RID_CLASS] = class_type_node;
-
- record_type_node = build_int_2 (record_type, 0);
- TREE_TYPE (record_type_node) = record_type_node;
- ridpointers[(int) RID_RECORD] = record_type_node;
-
- union_type_node = build_int_2 (union_type, 0);
- TREE_TYPE (union_type_node) = union_type_node;
- ridpointers[(int) RID_UNION] = union_type_node;
-
- enum_type_node = build_int_2 (enum_type, 0);
- TREE_TYPE (enum_type_node) = enum_type_node;
- ridpointers[(int) RID_ENUM] = enum_type_node;
-
- ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
- ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
-
- ridpointers[(int) RID_PUBLIC] = get_identifier ("public");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PUBLIC],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PUBLIC]));
- ridpointers[(int) RID_PRIVATE] = get_identifier ("private");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PRIVATE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PRIVATE]));
- ridpointers[(int) RID_PROTECTED] = get_identifier ("protected");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PROTECTED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PROTECTED]));
-
- /* Exception handling extensions. */
- exception_type_node = build_int_2 (exception_type, 0);
- TREE_TYPE (exception_type_node) = exception_type_node;
- ridpointers[(int) RID_EXCEPTION] = exception_type_node;
-
- opname_tab[(int) COMPONENT_REF] = "->";
- opname_tab[(int) MEMBER_REF] = "->*";
- opname_tab[(int) METHOD_CALL_EXPR] = "->()";
- opname_tab[(int) INDIRECT_REF] = "(unary *)";
- opname_tab[(int) ARRAY_REF] = "[]";
- opname_tab[(int) MODIFY_EXPR] = "=";
- opname_tab[(int) NEW_EXPR] = "new";
- opname_tab[(int) 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) 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] = "(unary +)";
- opname_tab[(int) ADDR_EXPR] = "(unary &)";
- 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.
- Clear those words out of the hash table so they won't be recognized. */
-#define UNSET_RESERVED_WORD(STRING) \
- do { struct resword *s = is_reserved_word (STRING, sizeof (STRING) - 1); \
- if (s) s->name = ""; } while (0)
-
- if (flag_ansi_exceptions)
- flag_handle_exceptions = 2;
-
- if (!flag_ansi_exceptions)
- {
- UNSET_RESERVED_WORD ("catch");
- }
-
- if (! flag_handle_exceptions)
- {
- /* Easiest way to not recognize exception
- handling extensions... */
- UNSET_RESERVED_WORD ("all");
- UNSET_RESERVED_WORD ("except");
- UNSET_RESERVED_WORD ("exception");
- UNSET_RESERVED_WORD ("raise");
- UNSET_RESERVED_WORD ("raises");
- UNSET_RESERVED_WORD ("reraise");
- UNSET_RESERVED_WORD ("try");
- UNSET_RESERVED_WORD ("throw");
- }
- else if (flag_ansi_exceptions)
- {
- /* Easiest way to not recognize exception
- handling extensions... */
- UNSET_RESERVED_WORD ("exception");
- UNSET_RESERVED_WORD ("all");
- UNSET_RESERVED_WORD ("except");
- UNSET_RESERVED_WORD ("raise");
- UNSET_RESERVED_WORD ("raises");
- UNSET_RESERVED_WORD ("reraise");
- is_reserved_word ("try", sizeof ("try") - 1)->token = ANSI_TRY;
- is_reserved_word ("throw", sizeof ("throw") - 1)->token = ANSI_THROW;
- }
- if (! (flag_gc || flag_dossier))
- {
- UNSET_RESERVED_WORD ("classof");
- UNSET_RESERVED_WORD ("headof");
- }
- if (flag_no_asm)
- UNSET_RESERVED_WORD ("asm");
- if (flag_no_asm || flag_traditional)
- UNSET_RESERVED_WORD ("typeof");
- UNSET_RESERVED_WORD ("dynamic");
-
- token_count = init_parse ();
- interface_unknown = 1;
-}
-
-void
-reinit_parse_for_function ()
-{
- current_base_init_list = NULL_TREE;
- current_member_init_list = NULL_TREE;
-}
-
-#ifdef __GNUC__
-__inline
-#endif
-void
-yyprint (file, yychar, yylval)
- FILE *file;
- int yychar;
- YYSTYPE yylval;
-{
- tree t;
- switch (yychar)
- {
- case IDENTIFIER:
- case TYPENAME:
- case TYPESPEC:
- case PTYPENAME:
- case IDENTIFIER_DEFN:
- case TYPENAME_DEFN:
- case PTYPENAME_DEFN:
- case TYPENAME_COLON:
- case TYPENAME_ELLIPSIS:
- case SCOPED_TYPENAME:
- case SCSPEC:
- t = yylval.ttype;
- print_id:
- my_friendly_assert (TREE_CODE (t) == IDENTIFIER_NODE, 224);
- if (IDENTIFIER_POINTER (t))
- fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
- break;
- case AGGR:
- if (yylval.ttype == class_type_node)
- fprintf (file, " `class'");
- else if (yylval.ttype == record_type_node)
- fprintf (file, " `struct'");
- else if (yylval.ttype == union_type_node)
- fprintf (file, " `union'");
- else if (yylval.ttype == enum_type_node)
- fprintf (file, " `enum'");
- else
- my_friendly_abort (80);
- break;
- case PRE_PARSED_CLASS_DECL:
- t = yylval.ttype;
- my_friendly_assert (TREE_CODE (t) == TREE_LIST, 225);
- t = TREE_VALUE (t);
- goto print_id;
- }
-}
-
-static int *reduce_count;
-int *token_count;
-
-#define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
-#define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
-
-int *
-init_parse ()
-{
-#ifdef GATHER_STATISTICS
- reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1));
- bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1));
- reduce_count += 1;
- token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1));
- bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1));
- token_count += 1;
-#endif
- return token_count;
-}
-
-#ifdef GATHER_STATISTICS
-void
-yyhook (yyn)
- int yyn;
-{
- reduce_count[yyn] += 1;
-}
-#endif
-
-static int
-reduce_cmp (p, q)
- int *p, *q;
-{
- return reduce_count[*q] - reduce_count[*p];
-}
-
-static int
-token_cmp (p, q)
- int *p, *q;
-{
- return token_count[*q] - token_count[*p];
-}
-
-void
-print_parse_statistics ()
-{
-#ifdef GATHER_STATISTICS
-#if YYDEBUG != 0
- int i;
- int maxlen = REDUCE_LENGTH;
- unsigned *sorted;
-
- if (reduce_count[-1] == 0)
- return;
-
- if (TOKEN_LENGTH > REDUCE_LENGTH)
- maxlen = TOKEN_LENGTH;
- sorted = (unsigned *) alloca (sizeof (int) * maxlen);
-
- for (i = 0; i < TOKEN_LENGTH; i++)
- sorted[i] = i;
- qsort (sorted, TOKEN_LENGTH, sizeof (int), token_cmp);
- for (i = 0; i < TOKEN_LENGTH; i++)
- {
- int index = sorted[i];
- if (token_count[index] == 0)
- break;
- if (token_count[index] < token_count[-1])
- break;
- fprintf (stderr, "token %d, `%s', count = %d\n",
- index, yytname[YYTRANSLATE (index)], token_count[index]);
- }
- fprintf (stderr, "\n");
- for (i = 0; i < REDUCE_LENGTH; i++)
- sorted[i] = i;
- qsort (sorted, REDUCE_LENGTH, sizeof (int), reduce_cmp);
- for (i = 0; i < REDUCE_LENGTH; i++)
- {
- int index = sorted[i];
- if (reduce_count[index] == 0)
- break;
- if (reduce_count[index] < reduce_count[-1])
- break;
- fprintf (stderr, "rule %d, line %d, count = %d\n",
- index, yyrline[index], reduce_count[index]);
- }
- fprintf (stderr, "\n");
-#endif
-#endif
-}
-
-/* Sets the value of the 'yydebug' variable to VALUE.
- This is a function so we don't have to have YYDEBUG defined
- in order to build the compiler. */
-void
-set_yydebug (value)
- int value;
-{
-#if YYDEBUG != 0
- extern int yydebug;
- yydebug = value;
-#else
- warning ("YYDEBUG not defined.");
-#endif
-}
-
-#ifdef SPEW_DEBUG
-const char *
-debug_yytranslate (value)
- int value;
-{
- return yytname[YYTRANSLATE (value)];
-}
-
-#endif
-
-/* Functions and data structures for #pragma interface.
-
- `#pragma implementation' means that the main file being compiled
- is considered to implement (provide) the classes that appear in
- its main body. I.e., if this is file "foo.cc", and class `bar'
- is defined in "foo.cc", then we say that "foo.cc implements bar".
-
- All main input files "implement" themselves automagically.
-
- `#pragma interface' means that unless this file (of the form "foo.h"
- is not presently being included by file "foo.cc", the
- CLASSTYPE_INTERFACE_ONLY bit gets set. The effect is that none
- of the vtables nor any of the inline functions defined in foo.h
- will ever be output.
-
- There are cases when we want to link files such as "defs.h" and
- "main.cc". In this case, we give "defs.h" a `#pragma interface',
- and "main.cc" has `#pragma implementation "defs.h"'. */
-
-struct impl_files
-{
- char *filename;
- struct impl_files *next;
-};
-
-static struct impl_files *impl_file_chain;
-
-/* Helper function to load global variables with interface
- information. */
-void
-extract_interface_info ()
-{
- tree fileinfo = get_time_identifier (input_filename);
- fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
- interface_only = TREE_INT_CST_LOW (fileinfo);
- interface_unknown = TREE_INT_CST_HIGH (fileinfo);
-}
-
-/* Return nonzero if S and T are not considered part of an
- INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */
-static int
-interface_strcmp (s)
- char *s;
-{
- /* Set the interface/implementation bits for this scope. */
- struct impl_files *ifiles;
- char *s1;
-
- s = FILE_NAME_NONDIRECTORY (s);
-
- for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
- {
- char *t1 = ifiles->filename;
- s1 = s;
-
- if (*s1 != *t1 || *s1 == 0)
- continue;
-
- while (*s1 == *t1 && *s1 != 0)
- s1++, t1++;
-
- /* A match. */
- if (*s1 == *t1)
- return 0;
-
- /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc. */
- if (index (s1, '.') || index (t1, '.'))
- continue;
-
- if (*s1 == '\0' || s1[-1] != '.' || t1[-1] != '.')
- continue;
-
- /* A match. */
- return 0;
- }
-
- /* No matches. */
- return 1;
-}
-
-void
-set_typedecl_interface_info (prev, vars)
- tree prev, vars;
-{
- tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
- tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
- tree type = TREE_TYPE (vars);
-
- CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
- = interface_strcmp (DECL_SOURCE_FILE (vars));
-}
-
-void
-set_vardecl_interface_info (prev, vars)
- tree prev, vars;
-{
- tree type = DECL_CONTEXT (vars);
-
- if (CLASSTYPE_INTERFACE_UNKNOWN (type) == 0)
- {
- if (CLASSTYPE_INTERFACE_ONLY (type))
- set_typedecl_interface_info (prev, TYPE_NAME (type));
- else
- CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
- DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
- TREE_PUBLIC (vars) = 1;
- }
-}
-
-/* Called from the top level: if there are any pending inlines to
- do, set up to process them now. */
-void
-do_pending_inlines ()
-{
- struct pending_inline *prev = 0, *tail;
- struct pending_inline *t;
-
- /* Reverse the pending inline functions, since
- they were cons'd instead of appended. */
-
- for (t = pending_inlines; t; t = tail)
- {
- t->deja_vu = 1;
- tail = t->next;
- t->next = prev;
- prev = t;
- }
- /* Reset to zero so that if the inline functions we are currently
- processing define inline functions of their own, that is handled
- correctly. ??? This hasn't been checked in a while. */
- pending_inlines = 0;
-
- /* Now start processing the first inline function. */
- t = prev;
- my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE),
- 226);
- if (t->parm_vec)
- push_template_decls (t->parm_vec, t->bindings, 0);
- if (t->len > 0)
- {
- feed_input (t->buf, t->len, t->can_free ? &inline_text_obstack : 0);
- lineno = t->lineno;
-#if 0
- if (input_filename != t->filename)
- {
- input_filename = t->filename;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- }
-#else
- input_filename = t->filename;
- interface_unknown = t->interface == 1;
- interface_only = t->interface == 0;
-#endif
- yychar = PRE_PARSED_FUNCTION_DECL;
- }
- /* Pass back a handle on the rest of the inline functions, so that they
- can be processed later. */
- yylval.ttype = build_tree_list ((tree) t, t->fndecl);
- if (flag_default_inline && t->fndecl
- /* If we're working from a template, don't change
- the `inline' state. */
- && t->parm_vec == NULL_TREE)
- DECL_INLINE (t->fndecl) = 1;
- DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
-}
-
-extern struct pending_input *to_be_restored;
-static int nextchar = -1;
-
-void
-process_next_inline (t)
- tree t;
-{
- struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
- my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
- 227);
- if (i->parm_vec)
- pop_template_decls (i->parm_vec, i->bindings, 0);
- i = i->next;
- if (yychar == YYEMPTY)
- yychar = yylex ();
- if (yychar != END_OF_SAVED_INPUT)
- {
- error ("parse error at end of saved function text");
- /* restore_pending_input will abort unless yychar is either
- * END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
- * hosed, feed back YYEMPTY.
- * We also need to discard nextchar, since that may have gotten
- * set as well.
- */
- nextchar = -1;
- }
- yychar = YYEMPTY;
- if (to_be_restored == 0)
- my_friendly_abort (123);
- restore_pending_input (to_be_restored);
- to_be_restored = 0;
- if (i && i->fndecl != NULL_TREE)
- {
- my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
- 228);
- if (i->parm_vec)
- push_template_decls (i->parm_vec, i->bindings, 0);
- feed_input (i->buf, i->len, i->can_free ? &inline_text_obstack : 0);
- lineno = i->lineno;
- input_filename = i->filename;
- yychar = PRE_PARSED_FUNCTION_DECL;
- yylval.ttype = build_tree_list ((tree) i, i->fndecl);
- if (flag_default_inline
- /* If we're working from a template, don't change
- the `inline' state. */
- && i->parm_vec == NULL_TREE)
- DECL_INLINE (i->fndecl) = 1;
- DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
- }
- if (i)
- {
- interface_unknown = i->interface == 1;
- interface_only = i->interface == 0;
- }
- else
- extract_interface_info ();
-}
-
-/* Since inline methods can refer to text which has not yet been seen,
- we store the text of the method in a structure which is placed in the
- DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL.
- After parsing the body of the class definition, the FUNCTION_DECL's are
- scanned to see which ones have this field set. Those are then digested
- one at a time.
-
- This function's FUNCTION_DECL will have a bit set in its common so
- that we know to watch out for it. */
-
-void
-consume_string (this_obstack)
- register struct obstack *this_obstack;
-{
- register char c;
- do
- {
- c = getch ();
- if (c == '\\')
- {
- obstack_1grow (this_obstack, c);
- c = getch ();
- obstack_1grow (this_obstack, c);
- continue;
- }
- if (c == '\n')
- {
- if (pedantic)
- pedwarn ("ANSI C++ forbids newline in string constant");
- lineno++;
- }
- obstack_1grow (this_obstack, c);
- }
- while (c != '\"');
-}
-
-static int nextyychar = YYEMPTY;
-static YYSTYPE nextyylval;
-
-struct pending_input {
- int nextchar, yychar, nextyychar, eof;
- YYSTYPE yylval, nextyylval;
- struct obstack token_obstack;
- int first_token;
-};
-
-struct pending_input *
-save_pending_input ()
-{
- struct pending_input *p;
- p = (struct pending_input *) xmalloc (sizeof (struct pending_input));
- p->nextchar = nextchar;
- p->yychar = yychar;
- p->nextyychar = nextyychar;
- p->yylval = yylval;
- p->nextyylval = nextyylval;
- p->eof = end_of_file;
- yychar = nextyychar = YYEMPTY;
- nextchar = -1;
- p->first_token = first_token;
- p->token_obstack = token_obstack;
-
- first_token = 0;
- gcc_obstack_init (&token_obstack);
- end_of_file = 0;
- return p;
-}
-
-void
-restore_pending_input (p)
- struct pending_input *p;
-{
- my_friendly_assert (nextchar == -1, 229);
- nextchar = p->nextchar;
- my_friendly_assert (yychar == YYEMPTY || yychar == END_OF_SAVED_INPUT, 230);
- yychar = p->yychar;
- my_friendly_assert (nextyychar == YYEMPTY, 231);
- nextyychar = p->nextyychar;
- yylval = p->yylval;
- nextyylval = p->nextyylval;
- first_token = p->first_token;
- obstack_free (&token_obstack, (char *) 0);
- token_obstack = p->token_obstack;
- end_of_file = p->eof;
- free (p);
-}
-
-/* Return next non-whitespace input character, which may come
- from `finput', or from `nextchar'. */
-static int
-yynextch ()
-{
- int c;
-
- if (nextchar >= 0)
- {
- c = nextchar;
- nextchar = -1;
- }
- else c = getch ();
- return skip_white_space (c);
-}
-
-/* Unget character CH from the input stream.
- If RESCAN is non-zero, then we want to `see' this
- character as the next input token. */
-void
-yyungetc (ch, rescan)
- int ch;
- int rescan;
-{
- /* Unget a character from the input stream. */
- if (yychar == YYEMPTY || rescan == 0)
- {
- if (nextchar >= 0)
- put_back (nextchar);
- nextchar = ch;
- }
- else
- {
- my_friendly_assert (nextyychar == YYEMPTY, 232);
- nextyychar = yychar;
- nextyylval = yylval;
- yychar = ch;
- }
-}
-
-/* This function stores away the text for an inline function that should
- be processed later. It decides how much later, and may need to move
- the info between obstacks; therefore, the caller should not refer to
- the T parameter after calling this function.
-
- This function also stores the list of template-parameter bindings that
- will be needed for expanding the template, if any. */
-
-static void
-store_pending_inline (decl, t)
- tree decl;
- struct pending_inline *t;
-{
- extern int processing_template_defn;
- int delay_to_eof = 0;
- struct pending_inline **inlines;
-
- t->fndecl = decl;
- /* Default: compile right away, and no extra bindings are needed. */
- t->parm_vec = t->bindings = 0;
- if (processing_template_defn)
- {
- tree type = current_class_type;
- /* Assumption: In this (possibly) nested class sequence, only
- one name will have template parms. */
- while (type && TREE_CODE_CLASS (TREE_CODE (type)) == 't')
- {
- tree decl = TYPE_NAME (type);
- tree tmpl = IDENTIFIER_TEMPLATE (DECL_NAME (decl));
- if (tmpl)
- {
- t->parm_vec = DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl))->parm_vec;
- t->bindings = TREE_VALUE (tmpl);
- }
- type = DECL_CONTEXT (decl);
- }
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
- || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
- {
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- my_friendly_assert (TYPE_MAX_VALUE (TREE_TYPE (decl)) == current_class_type,
- 233);
-
- /* Inline functions can be compiled immediately. Other functions
- will be output separately, so if we're in interface-only mode,
- punt them now, or output them now if we're doing implementations
- and we know no overrides will exist. Otherwise, we delay until
- end-of-file, to see if the definition is really required. */
- if (DECL_INLINE (decl))
- /* delay_to_eof == 0 */;
- else if (current_class_type && !interface_unknown)
- {
- if (interface_only)
- {
-#if 0
- print_node_brief (stderr, "\ndiscarding text for ", decl, 0);
-#endif
- if (t->can_free)
- obstack_free (&inline_text_obstack, t->buf);
- DECL_PENDING_INLINE_INFO (decl) = 0;
- return;
- }
- }
- /* Don't delay the processing of virtual functions. */
- else if (DECL_VINDEX (decl) == NULL_TREE)
- delay_to_eof = 1;
- }
- else
- my_friendly_abort (58);
- }
-
- if (delay_to_eof)
- {
- extern struct pending_inline *pending_template_expansions;
-
- if (t->can_free)
- {
- char *free_to = t->buf;
- t->buf = (char *) obstack_copy (&permanent_obstack, t->buf,
- t->len + 1);
- t = (struct pending_inline *) obstack_copy (&permanent_obstack,
- (char *)t, sizeof (*t));
- obstack_free (&inline_text_obstack, free_to);
- }
- inlines = &pending_template_expansions;
- t->can_free = 0;
- }
- else
- {
- inlines = &pending_inlines;
- DECL_PENDING_INLINE_INFO (decl) = t;
- }
-
- /* Because we use obstacks, we must process these in precise order. */
- t->next = *inlines;
- *inlines = t;
-}
-
-void reinit_parse_for_block ();
-
-void
-reinit_parse_for_method (yychar, decl)
- int yychar;
- tree decl;
-{
- int len;
- int starting_lineno = lineno;
- char *starting_filename = input_filename;
-
- reinit_parse_for_block (yychar, &inline_text_obstack, 0);
-
- len = obstack_object_size (&inline_text_obstack);
- current_base_init_list = NULL_TREE;
- current_member_init_list = NULL_TREE;
- if (decl == void_type_node
- || (current_class_type && TYPE_REDEFINED (current_class_type)))
- {
- /* Happens when we get two declarations of the same
- function in the same scope. */
- char *buf = obstack_finish (&inline_text_obstack);
- obstack_free (&inline_text_obstack, buf);
- return;
- }
- else
- {
- struct pending_inline *t;
- char *buf = obstack_finish (&inline_text_obstack);
-
- t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
- sizeof (struct pending_inline));
- t->buf = buf;
- t->len = len;
- t->lineno = starting_lineno;
- t->filename = starting_filename;
- t->token = YYEMPTY;
- t->can_free = 1;
- t->deja_vu = 0;
- t->interface = ((interface_unknown || processing_template_defn)
- ? 1
- : (interface_only ? 0 : 2));
- store_pending_inline (decl, t);
- }
-}
-
-/* Consume a block -- actually, a method or template definition beginning
- with `:' or `{' -- and save it away on the specified obstack.
-
- Argument IS_TEMPLATE indicates which set of error messages should be
- output if something goes wrong. This should really be cleaned up somehow,
- without loss of clarity. */
-void
-reinit_parse_for_block (yychar, obstackp, is_template)
- int yychar;
- struct obstack *obstackp;
- int is_template;
-{
- register int c = 0;
- int blev = 1;
- int starting_lineno = lineno;
- char *starting_filename = input_filename;
- int len;
- int look_for_semicolon = 0;
-
- if (yychar == '{')
- obstack_1grow (obstackp, '{');
- else if (yychar == '=')
- {
- look_for_semicolon = 1;
- }
- else
- {
- if (yychar != ':' && (yychar != RETURN || is_template))
- {
- yyerror (is_template
- ? "parse error in template specification"
- : "parse error in method specification");
- yychar = '{';
- }
- obstack_1grow (obstackp, yychar);
- while (c >= 0)
- {
- int this_lineno = lineno;
-
- c = yynextch ();
-
- /* Don't lose our cool if there are lots of comments. */
- if (lineno == this_lineno)
- ;
- else if (lineno - this_lineno < 10 /* + strlen (input_filename) */)
- {
- int i;
- for (i = lineno - this_lineno; i > 0; i--)
- obstack_1grow (obstackp, '\n');
- }
- else
- {
- char buf[16];
- sprintf (buf, "\n# %d \"", lineno);
- len = strlen (buf);
- obstack_grow (obstackp, buf, len);
-
- len = strlen (input_filename);
- obstack_grow (obstackp, input_filename, len);
- obstack_1grow (obstackp, '\"');
- obstack_1grow (obstackp, '\n');
- }
-
- /* strings must be read differently than text. */
- if (c == '\"')
- {
- obstack_1grow (obstackp, c);
- consume_string (obstackp);
- c = yynextch ();
- }
- while (c > ' ') /* ASCII dependent! */
- {
- obstack_1grow (obstackp, c);
- if (c == '{')
- goto main_loop;
- if (c == '\"')
- consume_string (obstackp);
- if (c == ';')
- {
- error (is_template
- ? "template body missing"
- : "function body for constructor missing");
- obstack_1grow (obstackp, '{');
- obstack_1grow (obstackp, '}');
- len += 2;
- goto done;
- }
- c = getch ();
- }
- if (c == '\n')
- lineno++;
- obstack_1grow (obstackp, c);
- }
- if (c == EOF)
- error_with_file_and_line (starting_filename,
- starting_lineno,
- "end of file read inside definition");
- }
-
- main_loop:
- while (c >= 0)
- {
- int this_lineno = lineno;
-
- c = skip_white_space (getch ());
-
- /* Don't lose our cool if there are lots of comments. */
- if (lineno - this_lineno)
- {
- if (lineno - this_lineno == 1)
- obstack_1grow (obstackp, '\n');
- else
- {
- char buf[16];
- sprintf (buf, "\n# %d \"", lineno);
- len = strlen (buf);
- obstack_grow (obstackp, buf, len);
-
- len = strlen (input_filename);
- obstack_grow (obstackp, input_filename, len);
- obstack_1grow (obstackp, '\"');
- obstack_1grow (obstackp, '\n');
- }
- }
-
- while (c > ' ')
- {
- obstack_1grow (obstackp, c);
- if (c == '{') blev++;
- else if (c == '}')
- {
- blev--;
- if (blev == 0 && !look_for_semicolon)
- goto done;
- }
- else if (c == '\"')
- consume_string (obstackp);
- else if (c == ';' && look_for_semicolon && blev == 0)
- goto done;
- c = getch ();
- }
- if (c == '\n')
- lineno++;
- obstack_1grow (obstackp, c);
- }
- done:
- obstack_1grow (obstackp, '\0');
-}
-
-/* Build a default function named NAME for type TYPE.
- KIND says what to build.
-
- When KIND == 0, build default destructor.
- When KIND == 1, build virtual destructor.
- When KIND == 2, build default constructor.
- When KIND == 3, build default X(const X&) constructor.
- When KIND == 4, build default X(X&) constructor. */
-
-tree
-cons_up_default_function (type, name, kind)
- tree type, name;
- int kind;
-{
- extern tree void_list_node;
- int len;
- tree declspecs = NULL_TREE;
- tree fn, args;
- tree argtype;
-
- name = constructor_name (name);
- switch (kind)
- {
- /* Destructors. */
- case 1:
- declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]);
- /* Fall through... */
- case 0:
- name = build_parse_node (BIT_NOT_EXPR, name);
- /* Fall through... */
- case 2:
- /* Default constructor. */
- args = void_list_node;
- break;
-
- case 3:
- type = build_type_variant (type, 1, 0);
- /* Fall through... */
- case 4:
- argtype = build_reference_type (type);
- args = tree_cons (NULL_TREE,
- build_tree_list (hash_tree_chain (argtype, NULL_TREE),
- get_identifier ("arg")),
- void_list_node);
- break;
-
- default:
- my_friendly_abort (59);
- }
-
- fn = start_method (declspecs,
- build_parse_node (CALL_EXPR, name, args, NULL_TREE),
- NULL_TREE);
- if (fn == void_type_node)
- return fn;
-
- current_base_init_list = NULL_TREE;
- current_member_init_list = NULL_TREE;
-
- len = 3;
-
- {
- struct pending_inline *t;
-
- t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
- sizeof (struct pending_inline));
- t->buf = default_def;
- t->len = len;
- t->lineno = lineno;
- t->filename = input_filename;
- t->token = YYEMPTY;
- t->can_free = 0;
- t->deja_vu = 0;
- t->interface = ((interface_unknown || processing_template_defn)
- ? 1
- : (interface_only ? 0 : 2));
- store_pending_inline (fn, t);
- /* We make this declaration private (static in the C sense). */
- TREE_PUBLIC (fn) = 0;
- }
- finish_method (fn);
- DECL_CLASS_CONTEXT (fn) = type;
- /* Show that this function was generated by the compiler. */
- DECL_SOURCE_LINE (fn) = 0;
- return fn;
-}
-
-/* Heuristic to tell whether the user is missing a semicolon
- after a struct or enum declaration. Emit an error message
- if we know the user has blown it. */
-void
-check_for_missing_semicolon (type)
- tree type;
-{
- if (yychar < 0)
- yychar = yylex ();
-
- if (yychar > 255
- && yychar != IDENTIFIER
- && yychar != TYPENAME)
- {
- if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
- error ("semicolon missing after %s declaration",
- TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
- else
- error ("semicolon missing after declaration of `%s'",
- TYPE_NAME_STRING (type));
- shadow_tag (build_tree_list (0, type));
- }
- /* Could probably also hack cases where class { ... } f (); appears. */
- clear_anon_tags ();
-}
-
-void
-note_got_semicolon (type)
- tree type;
-{
- if (TREE_CODE_CLASS (TREE_CODE (type)) != 't')
- my_friendly_abort (60);
- if (IS_AGGR_TYPE (type))
- CLASSTYPE_GOT_SEMICOLON (type) = 1;
-}
-
-void
-note_list_got_semicolon (declspecs)
- tree declspecs;
-{
- tree link;
-
- for (link = declspecs; link; link = TREE_CHAIN (link))
- {
- tree type = TREE_VALUE (link);
- if (TREE_CODE_CLASS (TREE_CODE (type)) == 't')
- note_got_semicolon (type);
- }
- clear_anon_tags ();
-}
-
-/* If C is not whitespace, return C.
- Otherwise skip whitespace and return first nonwhite char read. */
-
-static int
-skip_white_space (c)
- register int c;
-{
- for (;;)
- {
- switch (c)
- {
- case '\n':
- c = check_newline ();
- break;
-
- case ' ':
- case '\t':
- case '\f':
- case '\r':
- case '\v':
- case '\b':
- do
- c = getch ();
- while (c == ' ' || c == '\t');
- break;
-
- case '\\':
- c = getch ();
- if (c == '\n')
- lineno++;
- else
- error ("stray '\\' in program");
- c = getch ();
- break;
-
- default:
- return (c);
- }
- }
-}
-
-
-
-/* Make the token buffer longer, preserving the data in it.
- P should point to just beyond the last valid character in the old buffer.
- The value we return is a pointer to the new buffer
- at a place corresponding to P. */
-
-static char *
-extend_token_buffer (p)
- char *p;
-{
- int offset = p - token_buffer;
-
- maxtoken = maxtoken * 2 + 10;
- token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
-
- return token_buffer + offset;
-}
-
-static int
-get_last_nonwhite_on_line ()
-{
- register int c;
-
- /* Is this the last nonwhite stuff on the line? */
- if (nextchar >= 0)
- c = nextchar, nextchar = -1;
- else
- c = getch ();
-
- while (c == ' ' || c == '\t')
- c = getch ();
- return c;
-}
-
-/* At the beginning of a line, increment the line number
- and process any #-directive on this line.
- If the line is a #-directive, read the entire line and return a newline.
- Otherwise, return the line's first non-whitespace character. */
-
-int
-check_newline ()
-{
- register int c;
- register int token;
-
- lineno++;
-
- /* Read first nonwhite char on the line. */
-
- do
- c = getch ();
- while (c == ' ' || c == '\t');
-
- if (c != '#')
- {
- /* If not #, return it so caller will use it. */
- return c;
- }
-
- /* Read first nonwhite char after the `#'. */
-
- do
- c = getch ();
- while (c == ' ' || c == '\t');
-
- /* If a letter follows, then if the word here is `line', skip
- it and ignore it; otherwise, ignore the line, with an error
- if the word isn't `pragma'. */
-
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
- {
- if (c == 'p')
- {
- if (getch () == 'r'
- && getch () == 'a'
- && getch () == 'g'
- && getch () == 'm'
- && getch () == 'a')
- {
- /* Read first nonwhite char after the `#pragma'. */
-
- do
- c = getch ();
- while (c == ' ' || c == '\t');
-
- if (c == 'v'
- && getch () == 't'
- && getch () == 'a'
- && getch () == 'b'
- && getch () == 'l'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
- {
- extern tree pending_vtables;
-
- /* More follows: it must be a string constant (class name). */
- token = real_yylex ();
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #pragma vtable");
- goto skipline;
- }
- if (write_virtuals != 2)
- {
- warning ("use `+e2' option to enable #pragma vtable");
- goto skipline;
- }
- pending_vtables = perm_tree_cons (NULL_TREE, get_identifier (TREE_STRING_POINTER (yylval.ttype)), pending_vtables);
- if (nextchar < 0)
- nextchar = getch ();
- c = nextchar;
- if (c != '\n')
- warning ("trailing characters ignored");
- }
- else if (c == 'u'
- && getch () == 'n'
- && getch () == 'i'
- && getch () == 't'
- && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
- {
- /* More follows: it must be a string constant (unit name). */
- token = real_yylex ();
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #pragma unit");
- goto skipline;
- }
- current_unit_name = get_identifier (TREE_STRING_POINTER (yylval.ttype));
- current_unit_language = current_lang_name;
- if (nextchar < 0)
- nextchar = getch ();
- c = nextchar;
- if (c != '\n')
- warning ("trailing characters ignored");
- }
- else if (c == 'i')
- {
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
- c = getch ();
-
- if (c == 'n'
- && getch () == 't'
- && getch () == 'e'
- && getch () == 'r'
- && getch () == 'f'
- && getch () == 'a'
- && getch () == 'c'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
- {
- /* read to newline. */
- while (c != '\n')
- c = getch ();
-
- write_virtuals = 3;
-
- if (impl_file_chain == 0)
- {
- char *filename;
- tree fi;
-
- /* If this is zero at this point, then we are
- auto-implementing. */
- if (main_input_filename == 0)
- main_input_filename = input_filename;
-
- filename = FILE_NAME_NONDIRECTORY (main_input_filename);
- fi = get_time_identifier (filename);
- fi = IDENTIFIER_CLASS_VALUE (fi);
- TREE_INT_CST_LOW (fi) = 0;
- TREE_INT_CST_HIGH (fi) = 1;
- /* Get default. */
- impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
- impl_file_chain->filename = filename;
- impl_file_chain->next = 0;
- }
-
- interface_only = interface_strcmp (input_filename);
- interface_unknown = 0;
- TREE_INT_CST_LOW (fileinfo) = interface_only;
- TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
- }
- else if (c == 'm'
- && getch () == 'p'
- && getch () == 'l'
- && getch () == 'e'
- && getch () == 'm'
- && getch () == 'e'
- && getch () == 'n'
- && getch () == 't'
- && getch () == 'a'
- && getch () == 't'
- && getch () == 'i'
- && getch () == 'o'
- && getch () == 'n'
- && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
- {
- char *main_filename = main_input_filename ? main_input_filename : input_filename;
-
- while (c == ' ' || c == '\t')
- c = getch ();
- if (c != '\n')
- {
- put_back (c);
- token = real_yylex ();
- if (token != STRING
- || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid `#pragma implementation'");
- goto skipline;
- }
- main_filename = TREE_STRING_POINTER (yylval.ttype);
- }
- main_filename = FILE_NAME_NONDIRECTORY (main_filename);
-
- /* read to newline. */
- while (c != '\n')
- c = getch ();
-
- if (write_virtuals == 3)
- {
- struct impl_files *ifiles = impl_file_chain;
- while (ifiles)
- {
- if (! strcmp (ifiles->filename, main_filename))
- break;
- ifiles = ifiles->next;
- }
- if (ifiles == 0)
- {
- ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
- ifiles->filename = main_filename;
- ifiles->next = impl_file_chain;
- impl_file_chain = ifiles;
- }
- }
- else if ((main_input_filename != 0
- && ! strcmp (main_input_filename, input_filename))
- || ! strcmp (input_filename, main_filename))
- {
- write_virtuals = 3;
- if (impl_file_chain == 0)
- {
- impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
- impl_file_chain->filename = main_filename;
- impl_file_chain->next = 0;
- }
- }
- else
- error ("`#pragma implementation' can only appear at top-level");
- interface_only = 0;
- /* We make this non-zero so that we infer decl linkage
- in the impl file only for variables first declared
- in the interface file. */
- interface_unknown = 1;
- TREE_INT_CST_LOW (fileinfo) = interface_only;
- TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
- }
- }
- }
- goto skipline;
- }
- else if (c == 'd')
- {
- if (getch () == 'e'
- && getch () == 'f'
- && getch () == 'i'
- && getch () == 'n'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
- {
-#ifdef DWARF_DEBUGGING_INFO
- if ((debug_info_level == DINFO_LEVEL_VERBOSE)
- && (write_symbols == DWARF_DEBUG))
- dwarfout_define (lineno, get_directive_line (finput));
-#endif /* DWARF_DEBUGGING_INFO */
- goto skipline;
- }
- }
- else if (c == 'u')
- {
- if (getch () == 'n'
- && getch () == 'd'
- && getch () == 'e'
- && getch () == 'f'
- && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
- {
-#ifdef DWARF_DEBUGGING_INFO
- if ((debug_info_level == DINFO_LEVEL_VERBOSE)
- && (write_symbols == DWARF_DEBUG))
- dwarfout_undef (lineno, get_directive_line (finput));
-#endif /* DWARF_DEBUGGING_INFO */
- goto skipline;
- }
- }
- else if (c == 'l')
- {
- if (getch () == 'i'
- && getch () == 'n'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t'))
- goto linenum;
- }
- else if (c == 'i')
- {
- if (getch () == 'd'
- && getch () == 'e'
- && getch () == 'n'
- && getch () == 't'
- && ((c = getch ()) == ' ' || c == '\t'))
- {
-#ifdef ASM_OUTPUT_IDENT
- extern FILE *asm_out_file;
-#endif
- /* #ident. The pedantic warning is now in cccp.c. */
-
- /* Here we have just seen `#ident '.
- A string constant should follow. */
-
- while (c == ' ' || c == '\t')
- c = getch ();
-
- /* If no argument, ignore the line. */
- if (c == '\n')
- return c;
-
- put_back (c);
- token = real_yylex ();
- if (token != STRING
- || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #ident");
- goto skipline;
- }
-
- if (! flag_no_ident)
- {
-#ifdef ASM_OUTPUT_IDENT
- ASM_OUTPUT_IDENT (asm_out_file,
- TREE_STRING_POINTER (yylval.ttype));
-#endif
- }
-
- /* Skip the rest of this line. */
- goto skipline;
- }
- }
- else if (c == 'n')
- {
- if (getch () == 'e'
- && getch () == 'w'
- && getch () == 'w'
- && getch () == 'o'
- && getch () == 'r'
- && getch () == 'l'
- && getch () == 'd'
- && ((c = getch ()) == ' ' || c == '\t'))
- {
- /* Used to test incremental compilation. */
- sorry ("#pragma newworld");
- goto skipline;
- }
- }
- error ("undefined or invalid # directive");
- goto skipline;
- }
-
-linenum:
- /* Here we have either `#line' or `# <nonletter>'.
- In either case, it should be a line number; a digit should follow. */
-
- while (c == ' ' || c == '\t')
- c = getch ();
-
- /* If the # is the only nonwhite char on the line,
- just ignore it. Check the new newline. */
- if (c == '\n')
- return c;
-
- /* Something follows the #; read a token. */
-
- put_back (c);
- token = real_yylex ();
-
- if (token == CONSTANT
- && TREE_CODE (yylval.ttype) == INTEGER_CST)
- {
- int old_lineno = lineno;
- int used_up = 0;
- /* subtract one, because it is the following line that
- gets the specified number */
-
- int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
- c = get_last_nonwhite_on_line ();
- if (c == '\n')
- {
- /* No more: store the line number and check following line. */
- lineno = l;
- return c;
- }
- put_back (c);
-
- /* More follows: it must be a string constant (filename). */
-
- /* Read the string constant, but don't treat \ as special. */
- ignore_escape_flag = 1;
- token = real_yylex ();
- ignore_escape_flag = 0;
-
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #line");
- goto skipline;
- }
-
- /* Changing files again. This means currently collected time
- is charged against header time, and body time starts back
- at 0. */
- if (flag_detailed_statistics)
- {
- int this_time = my_get_run_time ();
- tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
- header_time += this_time - body_time;
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
- += this_time - body_time;
- this_filename_time = time_identifier;
- body_time = this_time;
- }
-
- if (flag_cadillac)
- cadillac_note_source ();
-
- input_filename
- = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
- strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
- lineno = l;
- GNU_xref_file (input_filename);
-
- /* Each change of file name
- reinitializes whether we are now in a system header. */
- in_system_header = 0;
-
- if (main_input_filename == 0)
- {
- struct impl_files *ifiles = impl_file_chain;
-
- if (ifiles)
- {
- while (ifiles->next)
- ifiles = ifiles->next;
- ifiles->filename = FILE_NAME_NONDIRECTORY (input_filename);
- }
-
- main_input_filename = input_filename;
- if (write_virtuals == 3)
- walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
- }
-
- extract_interface_info ();
-
- c = get_last_nonwhite_on_line ();
- if (c == '\n')
- {
- if (flag_cadillac)
- cadillac_switch_source (-1);
- return c;
- }
- put_back (c);
-
- token = real_yylex ();
- used_up = 0;
-
- /* `1' after file name means entering new file.
- `2' after file name means just left a file. */
-
- if (token == CONSTANT
- && TREE_CODE (yylval.ttype) == INTEGER_CST)
- {
- if (TREE_INT_CST_LOW (yylval.ttype) == 1)
- {
- /* Pushing to a new file. */
- struct file_stack *p
- = (struct file_stack *) xmalloc (sizeof (struct file_stack));
- input_file_stack->line = old_lineno;
- p->next = input_file_stack;
- p->name = input_filename;
- input_file_stack = p;
- input_file_stack_tick++;
-#ifdef DWARF_DEBUGGING_INFO
- if (debug_info_level == DINFO_LEVEL_VERBOSE
- && write_symbols == DWARF_DEBUG)
- dwarfout_start_new_source_file (input_filename);
-#endif /* DWARF_DEBUGGING_INFO */
-
- used_up = 1;
- if (flag_cadillac)
- cadillac_push_source ();
- }
- else if (TREE_INT_CST_LOW (yylval.ttype) == 2)
- {
- /* Popping out of a file. */
- if (input_file_stack->next)
- {
- struct file_stack *p = input_file_stack;
-
- if (flag_cadillac)
- cadillac_pop_source ();
-
- input_file_stack = p->next;
- free (p);
- input_file_stack_tick++;
-#ifdef DWARF_DEBUGGING_INFO
- if (debug_info_level == DINFO_LEVEL_VERBOSE
- && write_symbols == DWARF_DEBUG)
- dwarfout_resume_previous_source_file (input_file_stack->line);
-#endif /* DWARF_DEBUGGING_INFO */
- }
- else
- error ("#-lines for entering and leaving files don't match");
-
- used_up = 1;
- }
- }
- else if (flag_cadillac)
- cadillac_switch_source (-1);
-
- /* If we have handled a `1' or a `2',
- see if there is another number to read. */
- if (used_up)
- {
- c = get_last_nonwhite_on_line ();
- if (c == '\n')
- {
- if (flag_cadillac)
- cadillac_switch_source (-1);
- return c;
- }
- put_back (c);
-
- token = real_yylex ();
- used_up = 0;
- }
-
- /* `3' after file name means this is a system header file. */
-
- if (token == CONSTANT
- && TREE_CODE (yylval.ttype) == INTEGER_CST
- && TREE_INT_CST_LOW (yylval.ttype) == 3)
- in_system_header = 1;
-
- /* If NEXTCHAR is not end of line, we don't care what it is. */
- if (nextchar == '\n')
- return '\n';
- }
- else
- error ("invalid #-line");
-
- /* skip the rest of this line. */
- skipline:
- if (c == '\n')
- return c;
- while ((c = getch ()) != EOF && c != '\n');
- return c;
-}
-
-#if 0
-#define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0)
-#define isdigit(char) (char >= '0' && char <= '9')
-#else
-#include <ctype.h>
-#endif
-
-#define ENDFILE -1 /* token that represents end-of-file */
-
-/* Read an escape sequence, returning its equivalent as a character,
- or store 1 in *ignore_ptr if it is backslash-newline. */
-
-static int
-readescape (ignore_ptr)
- int *ignore_ptr;
-{
- register int c = getch ();
- register int code;
- register unsigned count;
- unsigned firstdig;
- int nonnull;
-
- switch (c)
- {
- case 'x':
- if (warn_traditional)
- warning ("the meaning of `\\x' varies with -traditional");
-
- if (flag_traditional)
- return c;
-
- code = 0;
- count = 0;
- nonnull = 0;
- while (1)
- {
- c = getch ();
- if (! isxdigit (c))
- {
- put_back (c);
- break;
- }
- code *= 16;
- if (c >= 'a' && c <= 'f')
- code += c - 'a' + 10;
- if (c >= 'A' && c <= 'F')
- code += c - 'A' + 10;
- if (c >= '0' && c <= '9')
- code += c - '0';
- if (code != 0 || count != 0)
- {
- if (count == 0)
- firstdig = code;
- count++;
- }
- nonnull = 1;
- }
- if (! nonnull)
- error ("\\x used with no following hex digits");
- else if (count == 0)
- /* Digits are all 0's. Ok. */
- ;
- else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
- || (count > 1
- && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
- <= firstdig)))
- warning ("hex escape out of range");
- return code;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7':
- code = 0;
- count = 0;
- while ((c <= '7') && (c >= '0') && (count++ < 3))
- {
- code = (code * 8) + (c - '0');
- c = getch ();
- }
- put_back (c);
- return code;
-
- case '\\': case '\'': case '"':
- return c;
-
- case '\n':
- lineno++;
- *ignore_ptr = 1;
- return 0;
-
- case 'n':
- return TARGET_NEWLINE;
-
- case 't':
- return TARGET_TAB;
-
- case 'r':
- return TARGET_CR;
-
- case 'f':
- return TARGET_FF;
-
- case 'b':
- return TARGET_BS;
-
- case 'a':
- if (warn_traditional)
- warning ("the meaning of `\\a' varies with -traditional");
-
- if (flag_traditional)
- return c;
- return TARGET_BELL;
-
- case 'v':
- return TARGET_VT;
-
- case 'e':
- case 'E':
- if (pedantic)
- pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
- return 033;
-
- case '?':
- return c;
-
- /* `\(', etc, are used at beginning of line to avoid confusing Emacs. */
- case '(':
- case '{':
- case '[':
- if (pedantic)
- pedwarn ("unknown escape sequence `\\%c'", c);
- return c;
- }
- if (c >= 040 && c < 0177)
- pedwarn ("unknown escape sequence `\\%c'", c);
- else
- pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
- return c;
-}
-
-/* Value is 1 if we should try to make the next identifier look like a
- typename (when it may be a local variable or a class variable).
- Value is 0 if we treat this name in a default fashion.
- Value is -1 if we must not see a type name. */
-int looking_for_typename = 0;
-
-void
-dont_see_typename ()
-{
- looking_for_typename = -1;
- if (yychar == TYPENAME || yychar == PTYPENAME)
- {
- yychar = IDENTIFIER;
- lastiddecl = 0;
- }
-}
-
-#ifdef __GNUC__
-extern __inline int identifier_type ();
-__inline
-#endif
-int
-identifier_type (decl)
- tree decl;
-{
- if (TREE_CODE (decl) == TEMPLATE_DECL
- && DECL_TEMPLATE_IS_CLASS (decl))
- return PTYPENAME;
- if (TREE_CODE (decl) != TYPE_DECL)
- return IDENTIFIER;
- return TYPENAME;
-}
-
-void
-see_typename ()
-{
- looking_for_typename = 0;
- if (yychar == IDENTIFIER)
- {
- lastiddecl = lookup_name (yylval.ttype, -1);
- if (lastiddecl == 0)
- {
- if (flag_labels_ok)
- lastiddecl = IDENTIFIER_LABEL_VALUE (yylval.ttype);
- }
- else
- yychar = identifier_type (lastiddecl);
- }
-}
-
-tree
-do_identifier (token)
- register tree token;
-{
- register tree id = lastiddecl;
-
- if (yychar == YYEMPTY)
- yychar = yylex ();
- /* Scope class declarations before global
- declarations. */
- if (id == IDENTIFIER_GLOBAL_VALUE (token)
- && current_class_type != 0
- && TYPE_SIZE (current_class_type) == 0
- && TREE_CODE (current_class_type) != UNINSTANTIATED_P_TYPE)
- {
- /* Could be from one of the base classes. */
- tree field = lookup_field (current_class_type, token, 1, 0);
- if (field == 0)
- ;
- else if (field == error_mark_node)
- /* We have already generated the error message.
- But we still want to return this value. */
- id = lookup_field (current_class_type, token, 0, 0);
- else if (TREE_CODE (field) == VAR_DECL
- || TREE_CODE (field) == CONST_DECL)
- id = field;
- else if (TREE_CODE (field) != FIELD_DECL)
- my_friendly_abort (61);
- else
- {
- error_with_decl (field, "invalid use of member `%s' from base class `%s'",
- TYPE_NAME_STRING (DECL_FIELD_CONTEXT (field)));
- id = error_mark_node;
- return id;
- }
- }
-
- if (!id || id == error_mark_node)
- {
- if (id == error_mark_node && current_class_type != NULL_TREE)
- {
- id = lookup_nested_field (token, 1);
- /* In lookup_nested_field(), we marked this so we can gracefully
- leave this whole mess. */
- if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
- return id;
- }
- if (yychar == '(' || yychar == LEFT_RIGHT)
- {
- id = implicitly_declare (token);
- }
- else if (current_function_decl == 0)
- {
- error ("`%s' was not declared in this scope",
- IDENTIFIER_POINTER (token));
- id = error_mark_node;
- }
- else
- {
- if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node
- || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
- {
- static int undeclared_variable_notice;
-
- error ("`%s' undeclared (first use this function)",
- IDENTIFIER_POINTER (token));
-
- if (! undeclared_variable_notice)
- {
- error ("(Each undeclared identifier is reported only once");
- error ("for each function it appears in.)");
- undeclared_variable_notice = 1;
- }
- }
- id = error_mark_node;
- /* Prevent repeated error messages. */
- IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
- SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
- }
- }
- /* TREE_USED is set in `hack_identifier'. */
- if (TREE_CODE (id) == CONST_DECL)
- {
- if (IDENTIFIER_CLASS_VALUE (token) == id)
- {
- /* Check visibility. */
- enum visibility_type visibility
- = compute_visibility (TYPE_BINFO (current_class_type), id);
- if (visibility == visibility_private)
- error_with_decl (id, "enum `%s' is private");
- /* protected is OK, since it's an enum of `this'. */
- }
- id = DECL_INITIAL (id);
- }
- else
- id = hack_identifier (id, token, yychar);
- return id;
-}
-
-tree
-identifier_typedecl_value (node)
- tree node;
-{
- tree t, type;
- type = IDENTIFIER_TYPE_VALUE (node);
- if (type == NULL_TREE)
- return NULL_TREE;
-#define do(X) \
- { \
- t = (X); \
- if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
- return t; \
- }
- do (IDENTIFIER_LOCAL_VALUE (node));
- do (IDENTIFIER_CLASS_VALUE (node));
- do (IDENTIFIER_GLOBAL_VALUE (node));
-#undef do
- /* Will this one ever happen? */
- if (TYPE_NAME (type))
- return TYPE_NAME (type);
-
- /* We used to do an internal error of 62 here, but instead we will
- handle the return of a null appropriately in the callers. */
- return NULL_TREE;
-}
-
-struct try_type
-{
- tree *node_var;
- char unsigned_flag;
- char long_flag;
- char long_long_flag;
-};
-
-struct try_type type_sequence[] =
-{
- { &integer_type_node, 0, 0, 0},
- { &unsigned_type_node, 1, 0, 0},
- { &long_integer_type_node, 0, 1, 0},
- { &long_unsigned_type_node, 1, 1, 0},
- { &long_long_integer_type_node, 0, 1, 1},
- { &long_long_unsigned_type_node, 1, 1, 1}
-};
-
-int
-real_yylex ()
-{
- tree tmp;
- register int c;
- register int value;
- int wide_flag = 0;
- int dollar_seen = 0;
- int i;
-
- if (nextchar >= 0)
- c = nextchar, nextchar = -1;
- else
- c = getch ();
-
- /* Effectively do c = skip_white_space (c)
- but do it faster in the usual cases. */
- while (1)
- switch (c)
- {
- case ' ':
- case '\t':
- case '\f':
- case '\v':
- case '\b':
- c = getch ();
- break;
-
- case '\r':
- /* Call skip_white_space so we can warn if appropriate. */
-
- case '\n':
- case '/':
- case '\\':
- c = skip_white_space (c);
- default:
- goto found_nonwhite;
- }
- found_nonwhite:
-
- token_buffer[0] = c;
- token_buffer[1] = 0;
-
-/* yylloc.first_line = lineno; */
-
- switch (c)
- {
- case EOF:
- token_buffer[0] = '\0';
- end_of_file = 1;
- if (input_redirected ())
- value = END_OF_SAVED_INPUT;
- else if (do_pending_expansions ())
- /* this will set yychar for us */
- return yychar;
- else
- value = ENDFILE;
- break;
-
- case '$':
- if (dollars_in_ident)
- {
- dollar_seen = 1;
- goto letter;
- }
- value = '$';
- goto done;
-
- case 'L':
- /* Capital L may start a wide-string or wide-character constant. */
- {
- register int c = getch ();
- if (c == '\'')
- {
- wide_flag = 1;
- goto char_constant;
- }
- if (c == '"')
- {
- wide_flag = 1;
- goto string_constant;
- }
- put_back (c);
- }
-
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F': case 'G': case 'H': case 'I': case 'J':
- case 'K': case 'M': case 'N': case 'O':
- case 'P': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y':
- case 'Z':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'i': case 'j':
- case 'k': case 'l': case 'm': case 'n': case 'o':
- case 'p': case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x': case 'y':
- case 'z':
- case '_':
- letter:
- {
- register char *p;
-
- p = token_buffer;
- if (input == 0)
- {
- /* We know that `token_buffer' can hold at least on char,
- so we install C immediately.
- We may have to read the value in `putback_char', so call
- `getch' once. */
- *p++ = c;
- c = getch ();
-
- /* Make this run fast. We know that we are reading straight
- from FINPUT in this case (since identifiers cannot straddle
- input sources. */
- while (isalnum (c) || (c == '_') || c == '$')
- {
- if (p >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
- if (c == '$' && ! dollars_in_ident)
- break;
-
- *p++ = c;
- c = getc (finput);
- }
- }
- else
- {
- /* We know that `token_buffer' can hold at least on char,
- so we install C immediately. */
- *p++ = c;
- c = getch ();
-
- while (isalnum (c) || (c == '_') || c == '$')
- {
- if (p >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
- if (c == '$' && ! dollars_in_ident)
- break;
-
- *p++ = c;
- c = getch ();
- }
- }
-
- *p = 0;
- nextchar = c;
-
- value = IDENTIFIER;
- yylval.itype = 0;
-
- /* Try to recognize a keyword. Uses minimum-perfect hash function */
-
- {
- register struct resword *ptr;
-
- if (ptr = is_reserved_word (token_buffer, p - token_buffer))
- {
- if (ptr->rid)
- {
- tree old_ttype = ridpointers[(int) ptr->rid];
-
- /* If this provides a type for us, then revert lexical
- state to standard state. */
- if (TREE_CODE (old_ttype) == IDENTIFIER_NODE
- && IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0
- && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL)
- looking_for_typename = 0;
- else if (ptr->token == AGGR || ptr->token == ENUM)
- looking_for_typename = 1;
-
- /* Check if this is a language-type declaration.
- Just glimpse the next non-white character. */
- nextchar = skip_white_space (nextchar);
- if (nextchar == '"')
- {
- /* We are looking at a string. Complain
- if the token before the string is no `extern'.
-
- Could cheat some memory by placing this string
- on the temporary_, instead of the saveable_
- obstack. */
-
- if (ptr->rid != RID_EXTERN)
- error ("invalid modifier `%s' for language string",
- ptr->name);
- real_yylex ();
- value = EXTERN_LANG_STRING;
- yylval.ttype = get_identifier (TREE_STRING_POINTER (yylval.ttype));
- break;
- }
- if (ptr->token == VISSPEC)
- {
- switch (ptr->rid)
- {
- case RID_PUBLIC:
- yylval.itype = visibility_public;
- break;
- case RID_PRIVATE:
- yylval.itype = visibility_private;
- break;
- case RID_PROTECTED:
- yylval.itype = visibility_protected;
- break;
- default:
- my_friendly_abort (63);
- }
- }
- else
- yylval.ttype = old_ttype;
- }
- value = (int) ptr->token;
- }
- }
-
- /* If we did not find a keyword, look for an identifier
- (or a typename). */
-
- if (value == IDENTIFIER || value == TYPESPEC)
- GNU_xref_ref (current_function_decl, token_buffer);
-
- if (value == IDENTIFIER)
- {
- tmp = get_identifier (token_buffer);
-
-#if !defined(VMS) && defined(JOINER)
- /* Make sure that user does not collide with our internal
- naming scheme. */
- if (JOINER == '$'
- && dollar_seen
- && (THIS_NAME_P (tmp)
- || VPTR_NAME_P (tmp)
- || DESTRUCTOR_NAME_P (tmp)
- || VTABLE_NAME_P (tmp)
- || TEMP_NAME_P (tmp)
- || ANON_AGGRNAME_P (tmp)
- || ANON_PARMNAME_P (tmp)))
- warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
- token_buffer);
-#endif
-
- yylval.ttype = tmp;
-
-#if 0
- /* This can not be done this way in C++ because
- lookup_name can find ambiguous names, and yield an
- error. Because this routine can be called at token
- scan time, this is unacceptable. (mrs) */
-
- /* A user-invisible read-only initialized variable
- should be replaced by its value. We only handle strings
- since that's the only case used in C (and C++). */
- tmp = lookup_name (yylval.ttype, 0);
- if (tmp != NULL_TREE && TREE_CODE (tmp) == VAR_DECL
- && DECL_IGNORED_P (tmp)
- && TREE_READONLY (tmp)
- && DECL_INITIAL (tmp) != NULL_TREE
- && TREE_CODE (DECL_INITIAL (tmp)) == STRING_CST)
- {
- yylval.ttype = DECL_INITIAL (tmp);
- value = STRING;
- }
-#endif
- }
- if (value == NEW && ! global_bindings_p ())
- {
- looking_for_typename = 1;
- value = NEW;
- goto done;
- }
- }
- break;
-
- case '.':
- {
- register int c1 = getch ();
- token_buffer[0] = c;
- token_buffer[1] = c1;
- if (c1 == '*')
- {
- value = DOT_STAR;
- token_buffer[2] = 0;
- goto done;
- }
- if (c1 == '.')
- {
- c1 = getch ();
- if (c1 == '.')
- {
- token_buffer[2] = c1;
- token_buffer[3] = 0;
- value = ELLIPSIS;
- goto done;
- }
- nextchar = c1;
- token_buffer[2] = '\0';
- value = RANGE;
- goto done;
- }
- if (isdigit (c1))
- {
- put_back (c1);
- goto resume_numerical_scan;
- }
- nextchar = c1;
- value = '.';
- token_buffer[1] = 0;
- goto done;
- }
- case '0': case '1':
- /* Optimize for most frequent case. */
- {
- register int c1 = getch ();
- if (! isalnum (c1) && c1 != '.')
- {
- /* Terminate string. */
- token_buffer[0] = c;
- token_buffer[1] = 0;
- if (c == '0')
- yylval.ttype = integer_zero_node;
- else
- yylval.ttype = integer_one_node;
- nextchar = c1;
- value = CONSTANT;
- goto done;
- }
- put_back (c1);
- }
- /* fall through... */
- case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- resume_numerical_scan:
- {
- register char *p;
- int base = 10;
- int count = 0;
- int largest_digit = 0;
- int numdigits = 0;
- /* for multi-precision arithmetic,
- we store only 8 live bits in each short. */
- short shorts[MAX_SHORTS];
- int overflow = 0;
-
- enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
- = NOT_FLOAT;
-
- p = token_buffer;
- *p++ = c;
-
- for (count = 0; count < MAX_SHORTS; count++)
- shorts[count] = 0;
-
- if (c == '0')
- {
- *p++ = (c = getch ());
- if ((c == 'x') || (c == 'X'))
- {
- base = 16;
- *p++ = (c = getch ());
- }
- /* Leading 0 forces octal unless the 0 is the only digit. */
- else if (c >= '0' && c <= '9')
- {
- base = 8;
- numdigits++;
- }
- else
- numdigits++;
- }
-
- /* Read all the digits-and-decimal-points. */
-
- while (c == '.'
- || (isalnum (c) && (c != 'l') && (c != 'L')
- && (c != 'u') && (c != 'U')
- && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
- {
- if (c == '.')
- {
- if (base == 16)
- error ("floating constant may not be in radix 16");
- if (floatflag == AFTER_POINT)
- {
- error ("malformed floating constant");
- floatflag = TOO_MANY_POINTS;
- }
- else
- floatflag = AFTER_POINT;
-
- base = 10;
- *p++ = c = getch ();
- /* Accept '.' as the start of a floating-point number
- only when it is followed by a digit.
- Otherwise, unread the following non-digit
- and use the '.' as a structural token. */
- if (p == token_buffer + 2 && !isdigit (c))
- {
- if (c == '.')
- {
- c = getch ();
- if (c == '.')
- {
- *p++ = '.';
- *p = '\0';
- value = ELLIPSIS;
- goto done;
- }
- nextchar = c;
- token_buffer[2] = '\0';
- value = RANGE;
- goto done;
- }
- nextchar = c;
- token_buffer[1] = '\0';
- value = '.';
- goto done;
- }
- }
- else
- {
- /* It is not a decimal point.
- It should be a digit (perhaps a hex digit). */
-
- if (isdigit (c))
- {
- c = c - '0';
- }
- else if (base <= 10)
- {
- if (c == 'e' || c == 'E')
- {
- base = 10;
- floatflag = AFTER_POINT;
- break; /* start of exponent */
- }
- error ("nondigits in number and not hexadecimal");
- c = 0;
- }
- else if (c >= 'a')
- {
- c = c - 'a' + 10;
- }
- else
- {
- c = c - 'A' + 10;
- }
- if (c >= largest_digit)
- largest_digit = c;
- numdigits++;
-
- for (count = 0; count < MAX_SHORTS; count++)
- {
- shorts[count] *= base;
- if (count)
- {
- shorts[count] += (shorts[count-1] >> 8);
- shorts[count-1] &= (1<<8)-1;
- }
- else shorts[0] += c;
- }
-
- if (shorts[MAX_SHORTS - 1] >= 1<<8
- || shorts[MAX_SHORTS - 1] < - (1 << 8))
- overflow = TRUE;
-
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = (c = getch ());
- }
- }
-
- if (numdigits == 0)
- error ("numeric constant with no digits");
-
- if (largest_digit >= base)
- error ("numeric constant contains digits beyond the radix");
-
- /* Remove terminating char from the token buffer and delimit the string */
- *--p = 0;
-
- if (floatflag != NOT_FLOAT)
- {
- tree type = double_type_node;
- char f_seen = 0;
- char l_seen = 0;
- int garbage_chars = 0, exceeds_double = 0;
- REAL_VALUE_TYPE value;
- jmp_buf handler;
-
- /* Read explicit exponent if any, and put it in tokenbuf. */
-
- if ((c == 'e') || (c == 'E'))
- {
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- c = getch ();
- if ((c == '+') || (c == '-'))
- {
- *p++ = c;
- c = getch ();
- }
- if (! isdigit (c))
- error ("floating constant exponent has no digits");
- while (isdigit (c))
- {
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- c = getch ();
- }
- }
-
- *p = 0;
- errno = 0;
-
- /* Convert string to a double, checking for overflow. */
- if (setjmp (handler))
- {
- error ("floating constant out of range");
- value = dconst0;
- }
- else
- {
- set_float_handler (handler);
- /* The second argument, machine_mode, of REAL_VALUE_ATOF
- tells the desired precision of the binary result of
- decimal-to-binary conversion. */
-
- /* Read the suffixes to choose a data type. */
- switch (c)
- {
- case 'f': case 'F':
- type = float_type_node;
- value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
- if (REAL_VALUE_ISINF (value) && pedantic)
- pedwarn ("floating point number exceeds range of `float'");
- garbage_chars = -1;
- break;
-
- case 'l': case 'L':
- type = long_double_type_node;
- value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
- if (REAL_VALUE_ISINF (value) && pedantic)
- pedwarn (
- "floating point number exceeds range of `long double'");
- garbage_chars = -1;
- break;
-
- default:
- value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
- if (REAL_VALUE_ISINF (value) && pedantic)
- pedwarn ("floating point number exceeds range of `double'");
- }
- set_float_handler (NULL);
- }
-#ifdef ERANGE
- if (errno == ERANGE && !flag_traditional && pedantic)
- {
- char *p1 = token_buffer;
- /* Check for "0.0" and variants;
- SunOS 4 spuriously returns ERANGE for them. */
- while (*p1 == '0') p1++;
- if (*p1 == '.')
- {
- p1++;
- while (*p1 == '0') p1++;
- }
- if (*p1 == 'e' || *p1 == 'E')
- {
- /* with significand==0, ignore the exponent */
- p1++;
- while (*p1 != 0) p1++;
- }
- /* ERANGE is also reported for underflow,
- so test the value to distinguish overflow from that. */
- if (REAL_VALUES_LESS (dconst1, value)
- || REAL_VALUES_LESS (value, dconstm1))
- {
- pedwarn ("floating point number exceeds range of `double'");
- exceeds_double = 1;
- }
- }
-#endif
- /* Note: garbage_chars is -1 if first char is *not* garbage. */
- while (isalnum (c))
- {
- if (c == 'f' || c == 'F')
- {
- if (f_seen)
- error ("two `f's in floating constant");
- f_seen = 1;
- }
- if (c == 'l' || c == 'L')
- {
- if (l_seen)
- error ("two `l's in floating constant");
- l_seen = 1;
- }
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- c = getch ();
- garbage_chars++;
- }
-
- if (garbage_chars > 0)
- error ("garbage at end of number");
-
- /* Create a node with determined type and value. */
- yylval.ttype = build_real (type, value);
-
- put_back (c);
- *p = 0;
- }
- else
- {
- tree type;
- HOST_WIDE_INT high, low;
- int spec_unsigned = 0;
- int spec_long = 0;
- int spec_long_long = 0;
-
- while (1)
- {
- if (c == 'u' || c == 'U')
- {
- if (spec_unsigned)
- error ("two `u's in integer constant");
- spec_unsigned = 1;
- }
- else if (c == 'l' || c == 'L')
- {
- if (spec_long)
- {
- if (spec_long_long)
- error ("three `l's in integer constant");
- else if (pedantic)
- pedwarn ("ANSI C++ forbids long long integer constants");
- spec_long_long = 1;
- }
- spec_long = 1;
- }
- else
- {
- if (isalnum (c))
- {
- error ("garbage at end of number");
- while (isalnum (c))
- {
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- c = getch ();
- }
- }
- break;
- }
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- c = getch ();
- }
-
- put_back (c);
-
- /* ??? This code assumes that everything but long long is 32-bits.
- Probably this code needs to be replaced with code similar
- to that in c-lex.c, but I don't want to do it. -- RK. */
-
- if ((overflow || shorts[7] || shorts[6] || shorts[5] || shorts[4])
- && !spec_long_long)
- warning ("integer constant out of range");
-
- /* If it won't fit in a signed long long, make it unsigned.
- We can't distinguish based on the tree node because
- any integer constant fits any long long type. */
- if (shorts[7] >= (1<<8))
- spec_unsigned = 1;
-
- /* This is simplified by the fact that our constant
- is always positive. */
- high = low = 0;
-
- for (i = 0; i < MAX_SHORTS / 2; i++)
- {
- high |= (HOST_WIDE_INT) shorts[i + MAX_SHORTS / 2] << (i * 8);
- low |= (HOST_WIDE_INT) shorts[i] << (i * 8);
- }
-
- yylval.ttype = build_int_2 (low, high);
-
-#if 0
- /* Find the first allowable type that the value fits in. */
- type = 0;
- for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
- i++)
- if (!(spec_long && !type_sequence[i].long_flag)
- && !(spec_long_long && !type_sequence[i].long_long_flag)
- && !(spec_unsigned && !type_sequence[i].unsigned_flag)
- /* A hex or octal constant traditionally is unsigned. */
- && !(base != 10 && flag_traditional
- && !type_sequence[i].unsigned_flag)
- /* A decimal constant can't be unsigned int
- unless explicitly specified. */
- && !(base == 10 && !spec_unsigned
- && *type_sequence[i].node_var == unsigned_type_node))
- if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
- {
- type = *type_sequence[i].node_var;
- break;
- }
- if (flag_traditional && type == long_unsigned_type_node
- && !spec_unsigned)
- type = long_integer_type_node;
-
- if (type == 0)
- {
- type = long_long_integer_type_node;
- warning ("integer constant out of range");
- }
-
- /* Warn about some cases where the type of a given constant
- changes from traditional C to ANSI C. */
- if (warn_traditional)
- {
- tree other_type = 0;
-
- /* This computation is the same as the previous one
- except that flag_traditional is used backwards. */
- for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
- i++)
- if (!(spec_long && !type_sequence[i].long_flag)
- && !(spec_long_long && !type_sequence[i].long_long_flag)
- && !(spec_unsigned && !type_sequence[i].unsigned_flag)
- /* A hex or octal constant traditionally is unsigned. */
- && !(base != 10 && !flag_traditional
- && !type_sequence[i].unsigned_flag)
- /* A decimal constant can't be unsigned int
- unless explicitly specified. */
- && !(base == 10 && !spec_unsigned
- && *type_sequence[i].node_var == unsigned_type_node))
- if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
- {
- other_type = *type_sequence[i].node_var;
- break;
- }
- if (!flag_traditional && type == long_unsigned_type_node
- && !spec_unsigned)
- type = long_integer_type_node;
-
- if (other_type != 0 && other_type != type)
- {
- if (flag_traditional)
- warning ("type of integer constant would be different without -traditional");
- else
- warning ("type of integer constant would be different with -traditional");
- }
- }
-
-#else /* 1 */
- if (!spec_long && !spec_unsigned
- && !(flag_traditional && base != 10)
- && int_fits_type_p (yylval.ttype, integer_type_node))
- {
-#if 0
- if (warn_traditional && base != 10)
- warning ("small nondecimal constant becomes signed in ANSI C++");
-#endif
- type = integer_type_node;
- }
- else if (!spec_long && (base != 10 || spec_unsigned)
- && int_fits_type_p (yylval.ttype, unsigned_type_node))
- {
- /* Nondecimal constants try unsigned even in traditional C. */
- type = unsigned_type_node;
- }
-
- else if (!spec_unsigned && !spec_long_long
- && int_fits_type_p (yylval.ttype, long_integer_type_node))
- type = long_integer_type_node;
-
- else if (! spec_long_long
- && int_fits_type_p (yylval.ttype,
- long_unsigned_type_node))
- {
-#if 0
- if (warn_traditional && !spec_unsigned)
- warning ("large integer constant becomes unsigned in ANSI C++");
-#endif
- if (flag_traditional && !spec_unsigned)
- type = long_integer_type_node;
- else
- type = long_unsigned_type_node;
- }
-
- else if (! spec_unsigned
- && int_fits_type_p (yylval.ttype,
- long_long_integer_type_node))
- type = long_long_integer_type_node;
-
- else if (int_fits_type_p (yylval.ttype,
- long_long_unsigned_type_node))
- {
-#if 0
- if (warn_traditional && !spec_unsigned)
- warning ("large nondecimal constant is unsigned in ANSI C++");
-#endif
-
- if (flag_traditional && !spec_unsigned)
- type = long_long_integer_type_node;
- else
- type = long_long_unsigned_type_node;
- }
-
- else
- {
- type = long_long_integer_type_node;
- warning ("integer constant out of range");
- }
-#endif
-
- TREE_TYPE (yylval.ttype) = type;
- *p = 0;
- }
-
- value = CONSTANT; break;
- }
-
- case '\'':
- char_constant:
- {
- register int result = 0;
- register int num_chars = 0;
- unsigned width = TYPE_PRECISION (char_type_node);
- int max_chars;
-
- if (wide_flag)
- {
- width = WCHAR_TYPE_SIZE;
-#ifdef MULTIBYTE_CHARS
- max_chars = MB_CUR_MAX;
-#else
- max_chars = 1;
-#endif
- }
- else
- max_chars = TYPE_PRECISION (integer_type_node) / width;
-
- while (1)
- {
- tryagain:
-
- c = getch ();
-
- if (c == '\'' || c == EOF)
- break;
-
- if (c == '\\')
- {
- int ignore = 0;
- c = readescape (&ignore);
- if (ignore)
- goto tryagain;
- if (width < HOST_BITS_PER_INT
- && (unsigned) c >= (1 << width))
- pedwarn ("escape sequence out of range for character");
-#ifdef MAP_CHARACTER
- if (isprint (c))
- c = MAP_CHARACTER (c);
-#endif
- }
- else if (c == '\n')
- {
- if (pedantic)
- pedwarn ("ANSI C++ forbids newline in character constant");
- lineno++;
- }
-#ifdef MAP_CHARACTER
- else
- c = MAP_CHARACTER (c);
-#endif
-
- num_chars++;
- if (num_chars > maxtoken - 4)
- extend_token_buffer (token_buffer);
-
- token_buffer[num_chars] = c;
-
- /* Merge character into result; ignore excess chars. */
- if (num_chars < max_chars + 1)
- {
- if (width < HOST_BITS_PER_INT)
- result = (result << width) | (c & ((1 << width) - 1));
- else
- result = c;
- }
- }
-
- token_buffer[num_chars + 1] = '\'';
- token_buffer[num_chars + 2] = 0;
-
- if (c != '\'')
- error ("malformatted character constant");
- else if (num_chars == 0)
- error ("empty character constant");
- else if (num_chars > max_chars)
- {
- num_chars = max_chars;
- error ("character constant too long");
- }
- else if (num_chars != 1 && ! flag_traditional)
- warning ("multi-character character constant");
-
- /* If char type is signed, sign-extend the constant. */
- if (! wide_flag)
- {
- int num_bits = num_chars * width;
- if (TREE_UNSIGNED (char_type_node)
- || ((result >> (num_bits - 1)) & 1) == 0)
- yylval.ttype
- = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0
- >> (HOST_BITS_PER_INT - num_bits)),
- 0);
- else
- yylval.ttype
- = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0
- >> (HOST_BITS_PER_INT - num_bits)),
- -1);
- if (num_chars<=1)
- TREE_TYPE (yylval.ttype) = char_type_node;
- else
- TREE_TYPE (yylval.ttype) = integer_type_node;
- }
- else
- {
-#ifdef MULTIBYTE_CHARS
- /* Set the initial shift state and convert the next sequence. */
- result = 0;
- /* In all locales L'\0' is zero and mbtowc will return zero,
- so don't use it. */
- if (num_chars > 1
- || (num_chars == 1 && token_buffer[1] != '\0'))
- {
- wchar_t wc;
- (void) mbtowc (NULL, NULL, 0);
- if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars)
- result = wc;
- else
- warning ("Ignoring invalid multibyte character");
- }
-#endif
- yylval.ttype = build_int_2 (result, 0);
- TREE_TYPE (yylval.ttype) = wchar_type_node;
- }
-
- value = CONSTANT;
- break;
- }
-
- case '"':
- string_constant:
- {
- register char *p;
-
- c = getch ();
- p = token_buffer + 1;
-
- while (c != '"' && c >= 0)
- {
- /* ignore_escape_flag is set for reading the filename in #line. */
- if (!ignore_escape_flag && c == '\\')
- {
- int ignore = 0;
- c = readescape (&ignore);
- if (ignore)
- goto skipnewline;
- if (!wide_flag
- && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
- && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
- pedwarn ("escape sequence out of range for character");
- }
- else if (c == '\n')
- {
- if (pedantic)
- pedwarn ("ANSI C++ forbids newline in string constant");
- lineno++;
- }
-
- if (p == token_buffer + maxtoken)
- p = extend_token_buffer (p);
- *p++ = c;
-
- skipnewline:
- c = getch ();
- if (c == EOF) {
- error("Unterminated string");
- break;
- }
- }
- *p = 0;
-
- /* We have read the entire constant.
- Construct a STRING_CST for the result. */
-
- if (wide_flag)
- {
- /* If this is a L"..." wide-string, convert the multibyte string
- to a wide character string. */
- char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES);
- int len;
-
-#ifdef MULTIBYTE_CHARS
- len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);
- if (len < 0 || len >= (p - token_buffer))
- {
- warning ("Ignoring invalid multibyte string");
- len = 0;
- }
- bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);
-#else
- {
- union { long l; char c[sizeof (long)]; } u;
- int big_endian;
- char *wp, *cp;
-
- /* Determine whether host is little or big endian. */
- u.l = 1;
- big_endian = u.c[sizeof (long) - 1];
- wp = widep + (big_endian ? WCHAR_BYTES - 1 : 0);
-
- bzero (widep, (p - token_buffer) * WCHAR_BYTES);
- for (cp = token_buffer + 1; cp < p; cp++)
- *wp = *cp, wp += WCHAR_BYTES;
- len = p - token_buffer - 1;
- }
-#endif
- yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
- TREE_TYPE (yylval.ttype) = wchar_array_type_node;
- }
- else
- {
- yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
- TREE_TYPE (yylval.ttype) = char_array_type_node;
- }
-
- *p++ = '"';
- *p = 0;
-
- value = STRING; break;
- }
-
- case '+':
- case '-':
- case '&':
- case '|':
- case '<':
- case '>':
- case '*':
- case '/':
- case '%':
- case '^':
- case '!':
- case '=':
- {
- register int c1;
-
- combine:
-
- switch (c)
- {
- case '+':
- yylval.code = PLUS_EXPR; break;
- case '-':
- yylval.code = MINUS_EXPR; break;
- case '&':
- yylval.code = BIT_AND_EXPR; break;
- case '|':
- yylval.code = BIT_IOR_EXPR; break;
- case '*':
- yylval.code = MULT_EXPR; break;
- case '/':
- yylval.code = TRUNC_DIV_EXPR; break;
- case '%':
- yylval.code = TRUNC_MOD_EXPR; break;
- case '^':
- yylval.code = BIT_XOR_EXPR; break;
- case LSHIFT:
- yylval.code = LSHIFT_EXPR; break;
- case RSHIFT:
- yylval.code = RSHIFT_EXPR; break;
- case '<':
- yylval.code = LT_EXPR; break;
- case '>':
- yylval.code = GT_EXPR; break;
- }
-
- token_buffer[1] = c1 = getch ();
- token_buffer[2] = 0;
-
- if (c1 == '=')
- {
- switch (c)
- {
- case '<':
- value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
- case '>':
- value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
- case '!':
- value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
- case '=':
- value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
- }
- value = ASSIGN; goto done;
- }
- else if (c == c1)
- switch (c)
- {
- case '+':
- value = PLUSPLUS; goto done;
- case '-':
- value = MINUSMINUS; goto done;
- case '&':
- value = ANDAND; goto done;
- case '|':
- value = OROR; goto done;
- case '<':
- c = LSHIFT;
- goto combine;
- case '>':
- c = RSHIFT;
- goto combine;
- }
- else if ((c == '-') && (c1 == '>'))
- {
- nextchar = skip_white_space (getch ());
- if (nextchar == '(')
- {
- int next_c = skip_white_space (getch ());
- if (next_c == ')')
- {
- nextchar = -1;
- value = POINTSAT_LEFT_RIGHT;
- goto done;
- }
- put_back (next_c);
- }
- if (nextchar == '*')
- {
- nextchar = -1;
- value = POINTSAT_STAR;
- }
- else
- value = POINTSAT;
- goto done;
- }
- else if (c1 == '?' && (c == '<' || c == '>'))
- {
- token_buffer[3] = 0;
-
- c1 = getch ();
- yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR);
- if (c1 == '=')
- {
- /* <?= or >?= expression. */
- token_buffer[2] = c1;
- value = ASSIGN;
- }
- else
- {
- value = MIN_MAX;
- nextchar = c1;
- }
- if (pedantic)
- error ("use of `operator %s' is not standard C++",
- token_buffer);
- goto done;
- }
-
- nextchar = c1;
- token_buffer[1] = 0;
-
- value = c;
- goto done;
- }
-
- case ':':
- c = getch ();
- if (c == ':')
- {
- token_buffer[1] = ':';
- token_buffer[2] = '\0';
- value = SCOPE;
- yylval.itype = 1;
- }
- else
- {
- nextchar = c;
- value = ':';
- }
- break;
-
- case 0:
- /* Don't make yyparse think this is eof. */
- value = 1;
- break;
-
- case '(':
- /* try, weakly, to handle casts to pointers to functions. */
- nextchar = skip_white_space (getch ());
- if (nextchar == '*')
- {
- int next_c = skip_white_space (getch ());
- if (next_c == ')')
- {
- nextchar = -1;
- yylval.ttype = build1 (INDIRECT_REF, 0, 0);
- value = PAREN_STAR_PAREN;
- }
- else
- {
- put_back (next_c);
- value = c;
- }
- }
- else if (nextchar == ')')
- {
- nextchar = -1;
- yylval.ttype = NULL_TREE;
- value = LEFT_RIGHT;
- }
- else value = c;
- break;
-
- default:
- value = c;
- }
-
-done:
-/* yylloc.last_line = lineno; */
-#ifdef GATHER_STATISTICS
- token_count[value] += 1;
-#endif
-
- return value;
-}
-
-typedef enum
-{
- d_kind, t_kind, s_kind, r_kind, e_kind, c_kind,
- id_kind, op_id_kind, perm_list_kind, temp_list_kind,
- vec_kind, x_kind, lang_decl, lang_type, all_kinds
-} tree_node_kind;
-extern int tree_node_counts[];
-extern int tree_node_sizes[];
-extern char *tree_node_kind_names[];
-
-/* Place to save freed lang_decls which were allocated on the
- permanent_obstack. @@ Not currently used. */
-tree free_lang_decl_chain;
-
-tree
-build_lang_decl (code, name, type)
- enum tree_code code;
- tree name;
- tree type;
-{
- register tree t = build_decl (code, name, type);
- struct obstack *obstack = current_obstack;
- register int i = sizeof (struct lang_decl) / sizeof (int);
- register int *pi;
-
- if (! TREE_PERMANENT (t))
- obstack = saveable_obstack;
- else
- /* Could be that saveable is permanent and current is not. */
- obstack = &permanent_obstack;
-
- if (free_lang_decl_chain && obstack == &permanent_obstack)
- {
- pi = (int *)free_lang_decl_chain;
- free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
- }
- else
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
-
- while (i > 0)
- pi[--i] = 0;
-
- DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
- LANG_DECL_PERMANENT ((struct lang_decl *) pi)
- = obstack == &permanent_obstack;
- my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi)
- == TREE_PERMANENT (t), 234);
- DECL_MAIN_VARIANT (t) = t;
- if (current_lang_name == lang_name_cplusplus)
- {
- DECL_LANGUAGE (t) = lang_cplusplus;
-#ifndef NO_AUTO_OVERLOAD
- if (code == FUNCTION_DECL && name != 0
- && ! (IDENTIFIER_LENGTH (name) == 4
- && IDENTIFIER_POINTER (name)[0] == 'm'
- && strcmp (IDENTIFIER_POINTER (name), "main") == 0)
- && ! (IDENTIFIER_LENGTH (name) > 10
- && IDENTIFIER_POINTER (name)[0] == '_'
- && IDENTIFIER_POINTER (name)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
- TREE_OVERLOADED (name) = 1;
-#endif
- }
- else if (current_lang_name == lang_name_c)
- DECL_LANGUAGE (t) = lang_c;
- else my_friendly_abort (64);
-
-#if 0 /* not yet, should get fixed properly later */
- if (code == TYPE_DECL)
- {
- tree id;
- id = get_identifier (build_overload_name (type, 1, 1));
- DECL_ASSEMBLER_NAME (t) = id;
- }
-
-#endif
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int)lang_decl] += 1;
- tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
-#endif
-
- return t;
-}
-
-tree
-build_lang_field_decl (code, name, type)
- enum tree_code code;
- tree name;
- tree type;
-{
- extern struct obstack *current_obstack, *saveable_obstack;
- register tree t = build_decl (code, name, type);
- struct obstack *obstack = current_obstack;
- register int i = sizeof (struct lang_decl_flags) / sizeof (int);
- register int *pi;
-#if 0 /* not yet, should get fixed properly later */
-
- if (code == TYPE_DECL)
- {
- tree id;
- id = get_identifier (build_overload_name (type, 1, 1));
- DECL_ASSEMBLER_NAME (t) = id;
- }
-#endif
-
- if (! TREE_PERMANENT (t))
- obstack = saveable_obstack;
- else
- my_friendly_assert (obstack == &permanent_obstack, 235);
-
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
- while (i > 0)
- pi[--i] = 0;
-
- DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
- return t;
-}
-
-void
-copy_lang_decl (node)
- tree node;
-{
- int size;
- int *pi;
-
- if (TREE_CODE (node) == FIELD_DECL)
- size = sizeof (struct lang_decl_flags);
- else
- size = sizeof (struct lang_decl);
- pi = (int *)obstack_alloc (&permanent_obstack, size);
- bcopy ((char *)DECL_LANG_SPECIFIC (node), (char *)pi, size);
- DECL_LANG_SPECIFIC (node) = (struct lang_decl *)pi;
-}
-
-tree
-make_lang_type (code)
- enum tree_code code;
-{
- extern struct obstack *current_obstack, *saveable_obstack;
- register tree t = make_node (code);
- struct obstack *obstack = current_obstack;
- register int i = sizeof (struct lang_type) / sizeof (int);
- register int *pi;
-
- /* Set up some flags that give proper default behavior. */
- IS_AGGR_TYPE (t) = 1;
-
- if (! TREE_PERMANENT (t))
- obstack = saveable_obstack;
- else
- my_friendly_assert (obstack == &permanent_obstack, 236);
-
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
- while (i > 0)
- pi[--i] = 0;
-
- TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi;
- CLASSTYPE_AS_LIST (t) = build_tree_list (NULL_TREE, t);
- CLASSTYPE_INTERFACE_UNKNOWN (t) = interface_unknown;
- CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
- TYPE_BINFO (t) = make_binfo (integer_zero_node, t, 0, 0, 0);
- CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
-
- /* Make sure this is laid out, for ease of use later.
- In the presence of parse errors, the normal was of assuring
- this might not ever get executed, so we lay it out *immediately*. */
- build_pointer_type (t);
-
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int)lang_type] += 1;
- tree_node_sizes[(int)lang_type] += sizeof(struct lang_type);
-#endif
-
- return t;
-}
-
-void
-copy_decl_lang_specific (decl)
- tree decl;
-{
- extern struct obstack *current_obstack, *saveable_obstack;
- register int *old = (int *)DECL_LANG_SPECIFIC (decl);
- struct obstack *obstack = current_obstack;
- register int i = sizeof (struct lang_decl) / sizeof (int);
- register int *pi;
-
- if (! TREE_PERMANENT (decl))
- obstack = saveable_obstack;
- else
- my_friendly_assert (obstack == &permanent_obstack, 237);
-
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
- while (i-- > 0)
- pi[i] = old[i];
-
- DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) pi;
-
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int)lang_decl] += 1;
- tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
-#endif
-}
-
-void
-dump_time_statistics ()
-{
- register tree prev = 0, decl, next;
- int this_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
- += this_time - body_time;
-
- fprintf (stderr, "\n******\n");
- print_time ("header files (total)", header_time);
- print_time ("main file (total)", this_time - body_time);
- fprintf (stderr, "ratio = %g : 1\n",
- (double)header_time / (double)(this_time - body_time));
- fprintf (stderr, "\n******\n");
-
- for (decl = filename_times; decl; decl = next)
- {
- next = IDENTIFIER_GLOBAL_VALUE (decl);
- IDENTIFIER_GLOBAL_VALUE (decl) = prev;
- prev = decl;
- }
-
- for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
- print_time (IDENTIFIER_POINTER (decl),
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
-}
-
-void
-compiler_error (s, v, v2)
- char *s;
- HOST_WIDE_INT v, v2; /* @@also used as pointer */
-{
- char buf[1024];
- sprintf (buf, s, v, v2);
- error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
-}
-
-void
-compiler_error_with_decl (decl, s)
- tree decl;
- char *s;
-{
- char *name;
- count_error (0);
-
- report_error_function (0);
-
- if (TREE_CODE (decl) == PARM_DECL)
- fprintf (stderr, "%s:%d: ",
- DECL_SOURCE_FILE (DECL_CONTEXT (decl)),
- DECL_SOURCE_LINE (DECL_CONTEXT (decl)));
- else
- fprintf (stderr, "%s:%d: ",
- DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
-
- name = lang_printable_name (decl);
- if (name)
- fprintf (stderr, s, name);
- else
- fprintf (stderr, s, "((anonymous))");
- fprintf (stderr, " (compiler error)\n");
-}
-
-void
-yyerror (string)
- char *string;
-{
- extern int end_of_file;
- char buf[200];
-
- strcpy (buf, string);
-
- /* We can't print string and character constants well
- because the token_buffer contains the result of processing escapes. */
- if (end_of_file)
- strcat (buf, input_redirected ()
- ? " at end of saved text"
- : " at end of input");
- else if (token_buffer[0] == 0)
- strcat (buf, " at null character");
- else if (token_buffer[0] == '"')
- strcat (buf, " before string constant");
- else if (token_buffer[0] == '\'')
- strcat (buf, " before character constant");
- else if (token_buffer[0] < 040 || (unsigned char) token_buffer[0] >= 0177)
- sprintf (buf + strlen (buf), " before character 0%o",
- (unsigned char) token_buffer[0]);
- else
- strcat (buf, " before `%s'");
-
- error (buf, token_buffer);
-}
diff --git a/gnu/gcc2/cc1plus/cp-lex.h b/gnu/gcc2/cc1plus/cp-lex.h
deleted file mode 100644
index 9df38e5ee403..000000000000
--- a/gnu/gcc2/cc1plus/cp-lex.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Define constants and variables for communication with cp-parse.y.
- Copyright (C) 1987, 1992, 1993 Free Software Foundation, Inc.
- Hacked by Michael Tiemann (tiemann@cygnus.com)
- and by Brendan Kehoe (brendan@cygnus.com).
-
-This file is part of GNU CC.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY. No author or distributor
-accepts responsibility to anyone for the consequences of using it
-or for whether it serves any particular purpose or works at all,
-unless he says so in writing. Refer to the GNU CC General Public
-License for full details.
-
-Everyone is granted permission to copy, modify and redistribute
-GNU CC, but only under the conditions described in the
-GNU CC General Public License. A copy of this license is
-supposed to have been given to you along with GNU CC so you
-can know your rights and responsibilities. It should be in a
-file named COPYING. Among other things, the copyright notice
-and this notice must be preserved on all copies. */
-
-
-
-enum rid
-{
- RID_UNUSED,
- RID_INT,
- RID_CHAR,
- RID_WCHAR,
- RID_FLOAT,
- RID_DOUBLE,
- RID_VOID,
-
- /* C++ extension */
- RID_CLASS,
- RID_RECORD,
- RID_UNION,
- RID_ENUM,
- RID_LONGLONG,
-
- /* This is where grokdeclarator starts its search when setting the specbits.
- The first seven are in the order of most frequently used, as found
- building libg++. */
-
- RID_EXTERN,
- RID_CONST,
- RID_LONG,
- RID_TYPEDEF,
- RID_UNSIGNED,
- RID_SHORT,
- RID_INLINE,
-
- RID_STATIC,
-
- RID_REGISTER,
- RID_VOLATILE,
- RID_FRIEND,
- RID_VIRTUAL,
- RID_PUBLIC,
- RID_PRIVATE,
- RID_PROTECTED,
- RID_SIGNED,
- RID_EXCEPTION,
- RID_RAISES,
- RID_AUTO,
-
- /* Note this is 31, and is unusable in shifts where ints are 32 bits.
- As soon as a new rid has to be added to this enum, you have to
- stop and come up with a better way to do all of this than by
- doing `specbits & (1 << (int) RID_FOO)', since you'll end up
- with an integer overflow. */
- RID_UNUSED1,
-
- RID_MAX
-};
-
-#define NORID RID_UNUSED
-
-#define RID_FIRST_MODIFIER RID_EXTERN
-
-/* The integral type that can represent all values of RIDBIT. */
-typedef unsigned long RID_BIT_TYPE;
-
-/* A bit that represents the given RID_... value. */
-#define RIDBIT(N) ((RID_BIT_TYPE) 1 << (int) (N))
-
-/* The elements of `ridpointers' are identifier nodes
- for the reserved type names and storage classes.
- It is indexed by a RID_... value. */
-extern tree ridpointers[(int) RID_MAX];
-
-/* the declaration found for the last IDENTIFIER token read in.
- yylex must look this up to detect typedefs, which get token type TYPENAME,
- so it is left around in case the identifier is not a typedef but is
- used in a context which makes it a reference to a variable. */
-extern tree lastiddecl;
-
-extern char *token_buffer; /* Pointer to token buffer. */
-
-/* Back-door communication channel to the lexer. */
-extern int looking_for_typename;
-
-extern tree make_pointer_declarator (), make_reference_declarator ();
-extern void reinit_parse_for_function ();
-extern void reinit_parse_for_method ();
-extern int yylex ();
diff --git a/gnu/gcc2/cc1plus/cp-method.c b/gnu/gcc2/cc1plus/cp-method.c
deleted file mode 100644
index ab98812ef7d5..000000000000
--- a/gnu/gcc2/cc1plus/cp-method.c
+++ /dev/null
@@ -1,2679 +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 "obstack.h"
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-/* TREE_LIST of the current inline functions that need to be
- processed. */
-struct pending_inline *pending_inlines;
-
-/* 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'))
-
-/* Counter to help build parameter names in case they were omitted. */
-static int dummy_name;
-static int in_parmlist;
-
-/* This points to a safe place to resume processing in case an expression
- generates an error while we're trying to format it. */
-static int scratch_error_offset;
-
-static void dump_type (), dump_decl ();
-static void dump_init (), dump_unary_op (), dump_binary_op ();
-
-#ifdef NO_AUTO_OVERLOAD
-int is_overloaded ();
-#endif
-
-void
-init_method ()
-{
- gcc_obstack_init (&scratch_obstack);
- scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
-}
-
-tree
-make_anon_parm_name ()
-{
- char buf[32];
-
- sprintf (buf, ANON_PARMNAME_FORMAT, dummy_name++);
- return get_identifier (buf);
-}
-
-void
-clear_anon_parm_name ()
-{
- /* recycle these names. */
- dummy_name = 0;
-}
-
-static void
-dump_readonly_or_volatile (t)
- tree t;
-{
- if (TYPE_READONLY (t))
- OB_PUTS ("const ");
- if (TYPE_VOLATILE (t))
- OB_PUTS ("volatile ");
-}
-
-static void
-dump_aggr_type (t)
- tree t;
-{
- tree name;
- char *aggr_string;
- char *context_string = 0;
-
- if (TYPE_READONLY (t))
- OB_PUTS ("const ");
- if (TYPE_VOLATILE (t))
- OB_PUTS ("volatile ");
- if (TREE_CODE (t) == ENUMERAL_TYPE)
- aggr_string = "enum";
- else if (TREE_CODE (t) == UNION_TYPE)
- aggr_string = "union";
- else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
- aggr_string = "class";
- else
- aggr_string = "struct";
-
- name = TYPE_NAME (t);
-
- if (TREE_CODE (name) == TYPE_DECL)
- {
-#if 0 /* not yet, should get fixed properly later */
- if (DECL_CONTEXT (name))
- context_string = TYPE_NAME_STRING (DECL_CONTEXT (name));
-#else
- if (DECL_LANG_SPECIFIC (name) && DECL_CLASS_CONTEXT (name))
- context_string = TYPE_NAME_STRING (DECL_CLASS_CONTEXT (name));
-#endif
- name = DECL_NAME (name);
- }
-
- obstack_grow (&scratch_obstack, aggr_string, strlen (aggr_string));
- OB_PUTC (' ');
- if (context_string)
- {
- obstack_grow (&scratch_obstack, context_string, strlen (context_string));
- OB_PUTC2 (':', ':');
- }
- OB_PUTID (name);
-}
-
-/* This must be large enough to hold any anonymous parm name. */
-static char anon_buffer[sizeof (ANON_PARMNAME_FORMAT) + 20];
-/* This must be large enough to hold any printed integer or floatingpoint value. */
-static char digit_buffer[128];
-
-static void
-dump_type_prefix (t, p)
- tree t;
- int *p;
-{
- int old_p = 0;
-
- if (t == NULL_TREE)
- return;
-
- switch (TREE_CODE (t))
- {
- case ERROR_MARK:
- sprintf (anon_buffer, ANON_PARMNAME_FORMAT, dummy_name++);
- OB_PUTCP (anon_buffer);
- break;
-
- case UNKNOWN_TYPE:
- OB_PUTS ("<unknown type>");
- return;
-
- case TREE_LIST:
- dump_type (TREE_VALUE (t), &old_p);
- if (TREE_CHAIN (t))
- {
- if (TREE_CHAIN (t) != void_list_node)
- {
- OB_PUTC (',');
- dump_type (TREE_CHAIN (t), &old_p);
- }
- }
- else OB_PUTS ("...");
- return;
-
- case POINTER_TYPE:
- *p += 1;
- dump_type_prefix (TREE_TYPE (t), p);
- while (*p)
- {
- OB_PUTC ('*');
- *p -= 1;
- }
- if (TYPE_READONLY (t))
- OB_PUTS ("const ");
- if (TYPE_VOLATILE (t))
- OB_PUTS ("volatile ");
- return;
-
- case OFFSET_TYPE:
- {
- tree type = TREE_TYPE (t);
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- type = TREE_TYPE (type);
- if (in_parmlist)
- OB_PUTS ("auto ");
- }
-
- dump_type_prefix (type, &old_p);
-
- OB_PUTC ('(');
- dump_type (TYPE_OFFSET_BASETYPE (t), &old_p);
- OB_PUTC2 (':', ':');
- while (*p)
- {
- OB_PUTC ('*');
- *p -= 1;
- }
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- return;
- }
-
- case METHOD_TYPE:
- {
- tree type = TREE_TYPE (t);
- if (in_parmlist)
- OB_PUTS ("auto ");
-
- dump_type_prefix (type, &old_p);
-
- OB_PUTC ('(');
- dump_type (TYPE_METHOD_BASETYPE (t), &old_p);
- OB_PUTC2 (':', ':');
- while (*p)
- {
- OB_PUTC ('*');
- *p -= 1;
- }
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- return;
- }
-
- case REFERENCE_TYPE:
- dump_type_prefix (TREE_TYPE (t), p);
- OB_PUTC ('&');
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- return;
-
- case ARRAY_TYPE:
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- dump_type_prefix (TREE_TYPE (t), p);
- return;
-
- case FUNCTION_TYPE:
- if (in_parmlist)
- OB_PUTS ("auto ");
- dump_type_prefix (TREE_TYPE (t), &old_p);
- OB_PUTC ('(');
- while (*p)
- {
- OB_PUTC ('*');
- *p -= 1;
- }
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- return;
-
- case IDENTIFIER_NODE:
- OB_PUTID (t);
- OB_PUTC (' ');
- break;
-
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- dump_aggr_type (t);
- break;
-
- case TYPE_DECL:
- if (TYPE_READONLY (t))
- OB_PUTS ("const ");
- if (TYPE_VOLATILE (t))
- OB_PUTS ("volatile ");
- OB_PUTID (DECL_NAME (t));
- OB_PUTC (' ');
- break;
-
- case INTEGER_TYPE:
-#if 0
- /* Normally, `unsigned' is part of the deal. Not so if it comes
- with `const' or `volatile'. */
- if (TYPE_MAIN_VARIANT (t) == unsigned_type (TYPE_MAIN_VARIANT (t))
- && (TYPE_READONLY (t) || TYPE_VOLATILE (t)))
- OB_PUTS ("unsigned ");
-#endif
- /* fall through. */
- case REAL_TYPE:
- case VOID_TYPE:
- if (TYPE_READONLY (t))
- OB_PUTS ("const ");
- if (TYPE_VOLATILE (t))
- OB_PUTS ("volatile ");
- OB_PUTID (TYPE_IDENTIFIER (t));
- OB_PUTC (' ');
- break;
-
- default:
- my_friendly_abort (65);
- }
-}
-
-static void
-dump_type_suffix (t, p)
- tree t;
- int *p;
-{
- int old_p = 0;
-
- if (t == NULL_TREE)
- return;
-
- switch (TREE_CODE (t))
- {
- case ERROR_MARK:
- sprintf (anon_buffer, ANON_PARMNAME_FORMAT, dummy_name++);
- OB_PUTCP (anon_buffer);
- break;
-
- case UNKNOWN_TYPE:
- return;
-
- case POINTER_TYPE:
- dump_type_suffix (TREE_TYPE (t), p);
- return;
-
- case OFFSET_TYPE:
- {
- tree type = TREE_TYPE (t);
-
- OB_PUTC (')');
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
-#if 0
- tree next_arg = TREE_CHAIN (TYPE_ARG_TYPES (type));
- OB_PUTC ('(');
- if (next_arg)
- {
- if (next_arg != void_list_node)
- {
- in_parmlist++;
- dump_type (next_arg, &old_p);
- in_parmlist--;
- }
- }
- else OB_PUTS ("...");
- OB_PUTC (')');
- dump_type_suffix (TREE_TYPE (type), p);
-#else
- my_friendly_abort (66);
-#endif
- }
- return;
- }
-
- case METHOD_TYPE:
- {
- tree next_arg;
- OB_PUTC (')');
- next_arg = TREE_CHAIN (TYPE_ARG_TYPES (t));
- OB_PUTC ('(');
- if (next_arg)
- {
- if (next_arg != void_list_node)
- {
- in_parmlist++;
- dump_type (next_arg, &old_p);
- in_parmlist--;
- }
- }
- else OB_PUTS ("...");
- OB_PUTC (')');
- dump_readonly_or_volatile (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))));
- dump_type_suffix (TREE_TYPE (t), p);
- return;
- }
-
- case REFERENCE_TYPE:
- dump_type_suffix (TREE_TYPE (t), p);
- return;
-
- case ARRAY_TYPE:
- dump_type_suffix (TREE_TYPE (t), p);
- OB_PUTC2 ('[', ']');
- return;
-
- case FUNCTION_TYPE:
- OB_PUTC2 (')', '(');
- if (TYPE_ARG_TYPES (t) && TYPE_ARG_TYPES (t) != void_list_node)
- {
- in_parmlist++;
- dump_type (TYPE_ARG_TYPES (t), &old_p);
- in_parmlist--;
- }
- OB_PUTC (')');
- dump_type_suffix (TREE_TYPE (t), p);
- return;
-
- case IDENTIFIER_NODE:
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- case TYPE_DECL:
- case INTEGER_TYPE:
- case REAL_TYPE:
- case VOID_TYPE:
- return;
-
- default:
- my_friendly_abort (67);
- }
-}
-
-static void
-dump_type (t, p)
- tree t;
- int *p;
-{
- int old_p = 0;
-
- if (t == NULL_TREE)
- return;
-
- switch (TREE_CODE (t))
- {
- case ERROR_MARK:
- sprintf (anon_buffer, ANON_PARMNAME_FORMAT, dummy_name++);
- OB_PUTCP (anon_buffer);
- break;
-
- case UNKNOWN_TYPE:
- OB_PUTS ("<unknown type>");
- return;
-
- case TREE_LIST:
- dump_type (TREE_VALUE (t), &old_p);
- if (TREE_CHAIN (t))
- {
- if (TREE_CHAIN (t) != void_list_node)
- {
- OB_PUTC (',');
- dump_type (TREE_CHAIN (t), &old_p);
- }
- }
- else OB_PUTS ("...");
- return;
-
- case POINTER_TYPE:
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- *p += 1;
- dump_type (TREE_TYPE (t), p);
- while (*p)
- {
- OB_PUTC ('*');
- *p -= 1;
- }
- return;
-
- case REFERENCE_TYPE:
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- dump_type (TREE_TYPE (t), p);
- OB_PUTC ('&');
- return;
-
- case ARRAY_TYPE:
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- dump_type (TREE_TYPE (t), p);
- OB_PUTC2 ('[', ']');
- return;
-
- case OFFSET_TYPE:
- case METHOD_TYPE:
- case FUNCTION_TYPE:
- dump_type_prefix (t, p);
- dump_type_suffix (t, p);
- return;
-
- case IDENTIFIER_NODE:
- OB_PUTID (t);
- OB_PUTC (' ');
- break;
-
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- dump_aggr_type (t);
- break;
-
- case TYPE_DECL:
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- OB_PUTID (DECL_NAME (t));
- OB_PUTC (' ');
- break;
-
- case INTEGER_TYPE:
- /* Normally, `unsigned' is part of the deal. Not so if it comes
- with `const' or `volatile'. */
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
-#if 0
- if (TYPE_MAIN_VARIANT (t) == unsigned_type (TYPE_MAIN_VARIANT (t))
- && (TYPE_READONLY (t) | TYPE_VOLATILE (t)))
- OB_PUTS ("unsigned ");
-#endif
- OB_PUTID (TYPE_IDENTIFIER (t));
- OB_PUTC (' ');
- break;
-
- case REAL_TYPE:
- case VOID_TYPE:
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t);
- OB_PUTID (TYPE_IDENTIFIER (t));
- OB_PUTC (' ');
- break;
-
- case TEMPLATE_TYPE_PARM:
- OB_PUTS ("<template type parm ");
- OB_PUTID (TYPE_IDENTIFIER (t));
- OB_PUTC ('>');
- break;
-
- case UNINSTANTIATED_P_TYPE:
- OB_PUTID (DECL_NAME (UPT_TEMPLATE (t)));
- OB_PUTS ("<...>");
- break;
-
- default:
- my_friendly_abort (68);
- }
-}
-
-static void
-dump_decl (t)
- tree t;
-{
- int p = 0;
-
- if (t == NULL_TREE)
- return;
-
- switch (TREE_CODE (t))
- {
- case ERROR_MARK:
- OB_PUTS (" /* decl error */ ");
- break;
-
- case PARM_DECL:
- dump_type_prefix (TREE_TYPE (t), &p);
- if (DECL_NAME (t))
- dump_decl (DECL_NAME (t));
- else
- {
- sprintf (anon_buffer, ANON_PARMNAME_FORMAT, dummy_name++);
- OB_PUTCP (anon_buffer);
- break;
- }
- dump_type_suffix (TREE_TYPE (t), &p);
- return;
-
- case CALL_EXPR:
- dump_decl (TREE_OPERAND (t, 0));
- OB_PUTC ('(');
- in_parmlist++;
- dump_decl (TREE_OPERAND (t, 1));
- in_parmlist--;
- t = tree_last (TYPE_ARG_TYPES (TREE_TYPE (t)));
- if (!t || t != void_list_node)
- OB_PUTS ("...");
- OB_PUTC (')');
- return;
-
- case ARRAY_REF:
- dump_decl (TREE_OPERAND (t, 0));
- OB_PUTC ('[');
- dump_decl (TREE_OPERAND (t, 1));
- OB_PUTC (']');
- return;
-
- case TYPE_DECL:
- OB_PUTID (DECL_NAME (t));
- OB_PUTC (' ');
- break;
-
- case TYPE_EXPR:
- my_friendly_abort (69);
- break;
-
- case IDENTIFIER_NODE:
- if (t == ansi_opname[(int) TYPE_EXPR])
- {
- OB_PUTS ("operator ");
- /* Not exactly IDENTIFIER_TYPE_VALUE. */
- dump_type (TREE_TYPE (t), &p);
- return;
- }
- else if (IDENTIFIER_OPNAME_P (t))
- {
- char *name_string = operator_name_string (t);
- OB_PUTS ("operator ");
- OB_PUTCP (name_string);
- OB_PUTC (' ');
- }
- else
- {
- OB_PUTID (t);
- OB_PUTC (' ');
- }
- break;
-
- case BIT_NOT_EXPR:
- OB_PUTC2 ('~', ' ');
- dump_decl (TREE_OPERAND (t, 0));
- return;
-
- case SCOPE_REF:
- OB_PUTID (TREE_OPERAND (t, 0));
- OB_PUTC2 (':', ':');
- dump_decl (TREE_OPERAND (t, 1));
- return;
-
- case INDIRECT_REF:
- OB_PUTC ('*');
- dump_decl (TREE_OPERAND (t, 0));
- return;
-
- case ADDR_EXPR:
- OB_PUTC ('&');
- dump_decl (TREE_OPERAND (t, 0));
- return;
-
- default:
- my_friendly_abort (70);
- }
-}
-
-static void
-dump_init_list (l)
- tree l;
-{
- while (l)
- {
- dump_init (TREE_VALUE (l));
- if (TREE_CHAIN (l))
- OB_PUTC (',');
- l = TREE_CHAIN (l);
- }
-}
-
-static void
-dump_init (t)
- tree t;
-{
- int dummy;
-
- switch (TREE_CODE (t))
- {
- case VAR_DECL:
- case PARM_DECL:
- OB_PUTC (' ');
- OB_PUTID (DECL_NAME (t));
- OB_PUTC (' ');
- break;
-
- case FUNCTION_DECL:
- {
- tree name = DECL_ASSEMBLER_NAME (t);
-
- if (DESTRUCTOR_NAME_P (name))
- {
- OB_PUTC2 (' ', '~');
- OB_PUTID (DECL_NAME (t));
- }
- else if (IDENTIFIER_TYPENAME_P (name))
- {
- dummy = 0;
- OB_PUTS ("operator ");
- dump_type (TREE_TYPE (name), &dummy);
- }
- else if (IDENTIFIER_OPNAME_P (name))
- {
- char *name_string = operator_name_string (name);
- OB_PUTS ("operator ");
- OB_PUTCP (name_string);
- OB_PUTC (' ');
- }
- else
- {
- OB_PUTC (' ');
- OB_PUTID (DECL_NAME (t));
- }
- OB_PUTC (' ');
- }
- break;
-
- case CONST_DECL:
- dummy = 0;
- OB_PUTC2 ('(', '(');
- dump_type (TREE_TYPE (t), &dummy);
- OB_PUTC (')');
- dump_init (DECL_INITIAL (t));
- OB_PUTC (')');
- return;
-
- case INTEGER_CST:
- /* If it's an enum, output its tag, rather than its value. */
- if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
- {
- char *p = enum_name_string (t, TREE_TYPE (t));
- OB_PUTC (' ');
- OB_PUTCP (p);
- OB_PUTC (' ');
- }
- else
- sprintf (digit_buffer, " %d ", TREE_INT_CST_LOW (t));
- OB_PUTCP (digit_buffer);
- break;
-
- case REAL_CST:
- sprintf (digit_buffer, " %g ", TREE_REAL_CST (t));
- OB_PUTCP (digit_buffer);
- break;
-
- case STRING_CST:
- {
- char *p = TREE_STRING_POINTER (t);
- int len = TREE_STRING_LENGTH (t) - 1;
- int i;
-
- OB_PUTC ('\"');
- for (i = 0; i < len; i++)
- {
- register char c = p[i];
- if (c == '\"' || c == '\\')
- OB_PUTC ('\\');
- if (c >= ' ' && c < 0177)
- OB_PUTC (c);
- else
- {
- sprintf (digit_buffer, "\\%03o", c);
- OB_PUTCP (digit_buffer);
- }
- }
- OB_PUTC ('\"');
- }
- return;
-
- case COMPOUND_EXPR:
- dump_binary_op (",", t, 1);
- break;
-
- case COND_EXPR:
- OB_PUTC ('(');
- dump_init (TREE_OPERAND (t, 0));
- OB_PUTS (" ? ");
- dump_init (TREE_OPERAND (t, 1));
- OB_PUTS (" : ");
- dump_init (TREE_OPERAND (t, 2));
- OB_PUTC (')');
- return;
-
- case SAVE_EXPR:
- if (TREE_HAS_CONSTRUCTOR (t))
- {
- dummy = 0;
- OB_PUTS ("new ");
- dump_type (TREE_TYPE (TREE_TYPE (t)), &dummy);
- PARM_DECL_EXPR (t) = 1;
- }
- else
- {
- sorry ("operand of SAVE_EXPR not understood");
- scratch_obstack.next_free
- = obstack_base (&scratch_obstack) + scratch_error_offset;
- }
- return;
-
- case NEW_EXPR:
- OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
- OB_PUTC ('(');
- dump_init_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
- OB_PUTC (')');
- return;
-
- case CALL_EXPR:
- OB_PUTC ('(');
- dump_init (TREE_OPERAND (t, 0));
- dump_init_list (TREE_OPERAND (t, 1));
- OB_PUTC (')');
- return;
-
- case WITH_CLEANUP_EXPR:
- /* Note that this only works for G++ cleanups. If somebody
- builds a general cleanup, there's no way to represent it. */
- dump_init (TREE_OPERAND (t, 0));
- return;
-
- case TARGET_EXPR:
- /* Note that this only works for G++ target exprs. If somebody
- builds a general TARGET_EXPR, there's no way to represent that
- it initializes anything other that the parameter slot for the
- default argument. Note we may have cleared out the first
- operand in expand_expr, so don't go killing ourselves. */
- if (TREE_OPERAND (t, 1))
- dump_init (TREE_OPERAND (t, 1));
- return;
-
- case MODIFY_EXPR:
- case PLUS_EXPR:
- case MINUS_EXPR:
- case MULT_EXPR:
- case TRUNC_DIV_EXPR:
- case TRUNC_MOD_EXPR:
- case MIN_EXPR:
- case MAX_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- case BIT_AND_EXPR:
- case BIT_ANDTC_EXPR:
- case TRUTH_ANDIF_EXPR:
- case TRUTH_ORIF_EXPR:
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- dump_binary_op (opname_tab[(int) TREE_CODE (t)], t,
- strlen (opname_tab[(int) TREE_CODE (t)]));
- return;
-
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- dump_binary_op ("/", t, 1);
- return;
-
- case CEIL_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case ROUND_MOD_EXPR:
- dump_binary_op ("%", t, 1);
- return;
-
- case COMPONENT_REF:
- dump_binary_op (".", t, 1);
- return;
-
- case CONVERT_EXPR:
- dump_unary_op ("+", t, 1);
- return;
-
- case ADDR_EXPR:
- if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
- || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)
- dump_init (TREE_OPERAND (t, 0));
- else
- dump_unary_op ("&", t, 1);
- return;
-
- case INDIRECT_REF:
- if (TREE_HAS_CONSTRUCTOR (t))
- {
- t = TREE_OPERAND (t, 0);
- my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237);
- dump_init (TREE_OPERAND (t, 0));
- OB_PUTC ('(');
- dump_init_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
- OB_PUTC (')');
- }
- else
- dump_unary_op ("*", t, 1);
- return;
-
- case NEGATE_EXPR:
- case BIT_NOT_EXPR:
- case TRUTH_NOT_EXPR:
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
- dump_unary_op (opname_tab [(int)TREE_CODE (t)], t,
- strlen (opname_tab[(int) TREE_CODE (t)]));
- return;
-
- case POSTDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- OB_PUTC ('(');
- dump_init (TREE_OPERAND (t, 0));
- OB_PUTCP (opname_tab[(int)TREE_CODE (t)]);
- OB_PUTC (')');
- return;
-
- case NOP_EXPR:
- dummy = 0;
- OB_PUTC2 ('(', '(');
- dump_type (TREE_TYPE (t), &dummy);
- OB_PUTC (')');
- dump_init (TREE_OPERAND (t, 0));
- OB_PUTC (')');
- return;
-
- case CONSTRUCTOR:
- OB_PUTC ('{');
- dump_init_list (CONSTRUCTOR_ELTS (t));
- OB_PUTC ('}');
- return;
-
- /* This list is incomplete, but should suffice for now.
- It is very important that `sorry' does not call
- `report_error_function'. That could cause an infinite loop. */
- default:
- sorry ("`%s' not supported for default parameters",
- tree_code_name[(int) TREE_CODE (t)]);
-
- /* fall through to ERROR_MARK... */
- case ERROR_MARK:
- scratch_obstack.next_free
- = obstack_base (&scratch_obstack) + scratch_error_offset;
- return;
- }
-}
-
-static void
-dump_binary_op (opstring, t, len)
- char *opstring;
- tree t;
- int len;
-{
- OB_PUTC ('(');
- dump_init (TREE_OPERAND (t, 0));
- OB_PUTC (' ');
- OB_PUTCP (opstring);
- OB_PUTC (' ');
- dump_init (TREE_OPERAND (t, 1));
- OB_PUTC (')');
-}
-
-static void
-dump_unary_op (opstring, t, len)
- char *opstring;
- tree t;
- int len;
-{
- OB_PUTC ('(');
- OB_PUTC (' ');
- OB_PUTCP (opstring);
- OB_PUTC (' ');
- dump_init (TREE_OPERAND (t, 0));
- OB_PUTC (')');
-}
-
-/* Pretty printing for announce_function. CNAME is the TYPE_DECL for
- the class that FNDECL belongs to, if we could not figure that out
- from FNDECL itself. FNDECL is the declaration of the function we
- are interested in seeing. PRINT_RET_TYPE_P is non-zero if we
- should print the type that this function returns. */
-
-char *
-fndecl_as_string (cname, fndecl, print_ret_type_p)
- tree cname, fndecl;
- int print_ret_type_p;
-{
- tree name = DECL_ASSEMBLER_NAME (fndecl);
- tree fntype = TREE_TYPE (fndecl);
- tree parmtypes = TYPE_ARG_TYPES (fntype);
- int p = 0;
- int spaces = 0;
-
- OB_INIT ();
-
- if (DECL_CLASS_CONTEXT (fndecl))
- cname = TYPE_NAME (DECL_CLASS_CONTEXT (fndecl));
-
- if (DECL_STATIC_FUNCTION_P (fndecl))
- OB_PUTS ("static ");
-
- if (print_ret_type_p && ! IDENTIFIER_TYPENAME_P (name))
- {
- dump_type_prefix (TREE_TYPE (fntype), &p);
- OB_PUTC (' ');
- }
-
- if (cname)
- {
- dump_type (cname, &p);
- *((char *) obstack_next_free (&scratch_obstack) - 1) = ':';
- OB_PUTC (':');
- if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes)
- parmtypes = TREE_CHAIN (parmtypes);
- if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl))
- /* Skip past "in_charge" identifier. */
- parmtypes = TREE_CHAIN (parmtypes);
- }
-
- if (DESTRUCTOR_NAME_P (name))
- {
- OB_PUTC ('~');
- parmtypes = TREE_CHAIN (parmtypes);
- dump_decl (DECL_NAME (fndecl));
- }
- else if (IDENTIFIER_TYPENAME_P (name))
- {
- /* This cannot use the hack that the operator's return
- type is stashed off of its name because it may be
- used for error reporting. In the case of conflicting
- declarations, both will have the same name, yet
- the types will be different, hence the TREE_TYPE field
- of the first name will be clobbered by the second. */
- OB_PUTS ("operator ");
- dump_type (TREE_TYPE (TREE_TYPE (fndecl)), &p);
- }
- else if (IDENTIFIER_OPNAME_P (name))
- {
- char *name_string = operator_name_string (name);
- OB_PUTS ("operator ");
- OB_PUTCP (name_string);
- OB_PUTC (' ');
- }
- else
- dump_decl (DECL_NAME (fndecl));
-
- OB_PUTC ('(');
- if (parmtypes)
- {
- in_parmlist++;
- if (parmtypes != void_list_node)
- spaces = 2;
- while (parmtypes && parmtypes != void_list_node)
- {
- char *last_space;
- dump_type (TREE_VALUE (parmtypes), &p);
- last_space = (char *)obstack_next_free (&scratch_obstack);
- while (last_space[-1] == ' ')
- last_space--;
- scratch_obstack.next_free = last_space;
- if (TREE_PURPOSE (parmtypes))
- {
- scratch_error_offset = obstack_object_size (&scratch_obstack);
- OB_PUTS (" (= ");
- dump_init (TREE_PURPOSE (parmtypes));
- OB_PUTC (')');
- }
- OB_PUTC2 (',', ' ');
- parmtypes = TREE_CHAIN (parmtypes);
- }
- in_parmlist--;
- }
-
- if (parmtypes)
- {
- if (spaces)
- scratch_obstack.next_free = obstack_next_free (&scratch_obstack)-spaces;
- }
- else
- OB_PUTS ("...");
-
- OB_PUTC (')');
-
- if (print_ret_type_p && ! IDENTIFIER_TYPENAME_P (name))
- dump_type_suffix (TREE_TYPE (fntype), &p);
-
- if (TREE_CODE (fntype) == METHOD_TYPE)
- dump_readonly_or_volatile (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))));
-
- OB_FINISH ();
-
- return (char *)obstack_base (&scratch_obstack);
-}
-
-/* Same, but handtype a _TYPE. */
-char *
-type_as_string (typ)
- tree typ;
-{
- int p = 0;
-
- OB_INIT ();
-
- dump_type(typ,&p);
-
- OB_FINISH ();
-
- return (char *)obstack_base (&scratch_obstack);
-}
-
-/* A cross between type_as_string and fndecl_as_string. */
-char *
-decl_as_string (decl)
- tree decl;
-{
- OB_INIT ();
-
- dump_decl(decl);
-
- OB_FINISH ();
-
- return (char *)obstack_base (&scratch_obstack);
-}
-
-/* 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 */
- 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 */
- 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, err_name)
- struct candidate *cp;
- tree parmtypes;
- char *name_kind, *err_name;
-{
- 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);
- error ("type unification failed for function template `%s'", err_name);
- return;
-
- case -3:
- if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))))
- error ("call to const %s `%s' with non-const object", name_kind, err_name);
- else
- error ("call to non-const %s `%s' with const object", name_kind, err_name);
- return;
- case -2:
- error ("too few arguments for %s `%s'", name_kind, err_name);
- return;
- case -1:
- error ("too many arguments for %s `%s'", name_kind, err_name);
- 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 `");
-
- tmp_firstobj = scratch_firstobj;
- scratch_firstobj = 0;
- fndecl_as_string (0, cp->function, 0);
- scratch_firstobj = tmp_firstobj;
-
- /* We know that the last char written is next_free-1. */
- ((char *) obstack_next_free (&scratch_obstack))[-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);
- dump_type (TREE_TYPE (TREE_VALUE (tta)), &i);
- }
- }
- 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 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)
- 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;
- }
-#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 PT 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_VEC_ELT (parmlist, i);
- tree arg = TREE_VEC_ELT (arglist, i);
- if (TREE_CODE (parm) == IDENTIFIER_NODE)
- {
- /* 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);
- }
- }
- }
- else
- {
- 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 ();
-
- 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 (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 ("parameter type with unspecified array bounds invalid");
- icat (1);
- }
- 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 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');
- icat (i);
- 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);
-}
-
-/* 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);
-
- if (dname == ansi_opname[(int) NEW_EXPR]
- && parms != NULL_TREE
- && TREE_CODE (parms) == TREE_LIST
- && TREE_VALUE (parms) == sizetype
- && TREE_CHAIN (parms) == void_list_node)
- return get_identifier ("__builtin_new");
- else if (dname == ansi_opname[(int) DELETE_EXPR]
- && parms != NULL_TREE
- && TREE_CODE (parms) == TREE_LIST
- && TREE_VALUE (parms) == ptr_type_node
- && TREE_CHAIN (parms) == void_list_node)
- return get_identifier ("__builtin_delete");
- else if (dname == ansi_opname[(int) DELETE_EXPR]
- && parms != NULL_TREE
- && TREE_CODE (parms) == TREE_LIST
- && TREE_VALUE (parms) == ptr_type_node
- && TREE_CHAIN (parms) != NULL_TREE
- && TREE_CODE (TREE_CHAIN (parms)) == TREE_LIST
- && TREE_VALUE (TREE_CHAIN (parms)) == sizetype
- && TREE_CHAIN (TREE_CHAIN (parms)) == void_list_node)
- return get_identifier ("__builtin_delete");
-
- 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
- parms = temp_tree_cons (NULL_TREE, TREE_TYPE (TREE_VALUE (parms)), 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);
- }
- return get_identifier (obstack_base (&scratch_obstack));
-}
-
-/* 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;
- 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 nonzero 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 NEW_EXPR:
- {
- /* For operators `new' (`delete'), only check visibility
- if we are in a constructor (destructor), and we are
- allocating for that constructor's (destructor's) type. */
-
- fnname = ansi_opname[(int) NEW_EXPR];
- if (flags & LOOKUP_GLOBAL)
- return build_overload_call (fnname, tree_cons (NULL_TREE, xarg2, arg3),
- flags & LOOKUP_COMPLAIN,
- (struct candidate *)0);
-
- if (current_function_decl == NULL_TREE
- || !DECL_CONSTRUCTOR_P (current_function_decl)
- || current_class_type != TYPE_MAIN_VARIANT (type1))
- flags = LOOKUP_COMPLAIN;
- rval = build_method_call (build1 (NOP_EXPR, xarg1, error_mark_node),
- fnname, tree_cons (NULL_TREE, xarg2, arg3),
- 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 DELETE_EXPR:
- {
- /* See comment above. */
-
- fnname = ansi_opname[(int) DELETE_EXPR];
- if (flags & LOOKUP_GLOBAL)
- return build_overload_call (fnname,
- tree_cons (NULL_TREE, xarg1,
- build_tree_list (NULL_TREE, xarg2)),
- flags & LOOKUP_COMPLAIN,
- (struct candidate *)0);
-
- if (current_function_decl == NULL_TREE
- || !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (current_function_decl))
- || current_class_type != TYPE_MAIN_VARIANT (type1))
- flags = LOOKUP_COMPLAIN;
- rval = build_method_call (build1 (NOP_EXPR, TREE_TYPE (xarg1),
- error_mark_node),
- 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))
- {
- /* 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 = IDENTIFIER_GLOBAL_VALUE (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 & LOOKUP_COMPLAIN,
- (struct candidate *)0);
- }
-
- /* If we did not win, do not lose yet, since type conversion may work. */
- if (TREE_CODE (rval) == ERROR_MARK)
- {
- if (flags & LOOKUP_COMPLAIN)
- return rval;
- return 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
- && (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 (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_CLASS_CONTEXT (value) != current_class_type)
- {
- tree path;
- enum visibility_type visibility;
- 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);
- visibility = compute_visibility (path, value);
- if (visibility != visibility_public)
- {
- if (TREE_CODE (value) == VAR_DECL)
- error ("static member `%s' is from private base class",
- IDENTIFIER_POINTER (name));
- 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;
-}
-
-
-/* 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);
- if (TREE_OPERAND (tmp, 0)
- && TREE_OPERAND (tmp, 0) != void_list_node)
- {
- error ("operator <typename> requires empty parameter list");
- TREE_OPERAND (tmp, 0) = NULL_TREE;
- }
- 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)
- return build_method_call (of, name, NULL_TREE, NULL_TREE, flags);
- else if (of)
- {
- tree this_this;
-
- if (current_class_decl == NULL_TREE)
- {
- error ("object required for `operator <typename>' call");
- return error_mark_node;
- }
-
- this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl);
- 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);
-
- error ("object required for `operator <typename>' call");
- 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)
- {
- error ("object required for `operator <typename>' call");
- 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);
-
- error ("object required for `operator <typename>' member reference");
- return error_mark_node;
-}
diff --git a/gnu/gcc2/cc1plus/cp-parse.c b/gnu/gcc2/cc1plus/cp-parse.c
deleted file mode 100644
index 3356f1b2fcfe..000000000000
--- a/gnu/gcc2/cc1plus/cp-parse.c
+++ /dev/null
@@ -1,7295 +0,0 @@
-
-/* A Bison parser, made from cp-parse.y */
-
-#define YYBISON 1 /* Identify Bison output. */
-
-#define IDENTIFIER 258
-#define TYPENAME 259
-#define SCOPED_TYPENAME 260
-#define SCSPEC 261
-#define TYPESPEC 262
-#define TYPE_QUAL 263
-#define CONSTANT 264
-#define STRING 265
-#define ELLIPSIS 266
-#define SIZEOF 267
-#define ENUM 268
-#define IF 269
-#define ELSE 270
-#define WHILE 271
-#define DO 272
-#define FOR 273
-#define SWITCH 274
-#define CASE 275
-#define DEFAULT 276
-#define BREAK 277
-#define CONTINUE 278
-#define RETURN 279
-#define GOTO 280
-#define ASM_KEYWORD 281
-#define GCC_ASM_KEYWORD 282
-#define TYPEOF 283
-#define ALIGNOF 284
-#define HEADOF 285
-#define CLASSOF 286
-#define ATTRIBUTE 287
-#define EXTENSION 288
-#define LABEL 289
-#define AGGR 290
-#define VISSPEC 291
-#define DELETE 292
-#define NEW 293
-#define OVERLOAD 294
-#define THIS 295
-#define OPERATOR 296
-#define DYNAMIC 297
-#define POINTSAT_LEFT_RIGHT 298
-#define LEFT_RIGHT 299
-#define TEMPLATE 300
-#define SCOPE 301
-#define START_DECLARATOR 302
-#define EMPTY 303
-#define TYPENAME_COLON 304
-#define ASSIGN 305
-#define RANGE 306
-#define OROR 307
-#define ANDAND 308
-#define MIN_MAX 309
-#define EQCOMPARE 310
-#define ARITHCOMPARE 311
-#define LSHIFT 312
-#define RSHIFT 313
-#define UNARY 314
-#define PLUSPLUS 315
-#define MINUSMINUS 316
-#define HYPERUNARY 317
-#define PAREN_STAR_PAREN 318
-#define POINTSAT 319
-#define POINTSAT_STAR 320
-#define DOT_STAR 321
-#define RAISE 322
-#define RAISES 323
-#define RERAISE 324
-#define TRY 325
-#define EXCEPT 326
-#define CATCH 327
-#define THROW 328
-#define ANSI_TRY 329
-#define ANSI_THROW 330
-#define TYPENAME_ELLIPSIS 331
-#define PTYPENAME 332
-#define PRE_PARSED_FUNCTION_DECL 333
-#define EXTERN_LANG_STRING 334
-#define ALL 335
-#define PRE_PARSED_CLASS_DECL 336
-#define TYPENAME_DEFN 337
-#define IDENTIFIER_DEFN 338
-#define PTYPENAME_DEFN 339
-#define END_OF_SAVED_INPUT 340
-
-#line 42 "cp-parse.y"
-
-#if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG)
-#undef YYDEBUG
-#define YYDEBUG 1
-#endif
-
-#include "config.h"
-
-#include <stdio.h>
-#include <errno.h>
-
-#include "tree.h"
-#include "input.h"
-#include "flags.h"
-#include "cp-lex.h"
-#include "cp-tree.h"
-
-/* Since parsers are distinct for each language, put the language string
- definition here. (fnf) */
-char *language_string = "GNU C++";
-
-extern tree void_list_node;
-extern struct obstack permanent_obstack;
-
-#ifndef errno
-extern int errno;
-#endif
-
-extern int end_of_file;
-
-void yyerror ();
-
-/* Like YYERROR but do call yyerror. */
-#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
-
-static void position_after_white_space ();
-
-/* Contains the statement keyword (if/while/do) to include in an
- error message if the user supplies an empty conditional expression. */
-static char *cond_stmt_keyword;
-
-/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
-int have_extern_spec;
-int used_extern_spec;
-
-void yyhook ();
-
-/* Cons up an empty parameter list. */
-#ifdef __GNUC__
-__inline
-#endif
-static tree
-empty_parms ()
-{
- tree parms;
-
- if (strict_prototype)
- parms = void_list_node;
- else
- parms = NULL_TREE;
- return parms;
-}
-
-#line 108 "cp-parse.y"
-typedef union {long itype; tree ttype; char *strtype; enum tree_code code; } YYSTYPE;
-#line 267 "cp-parse.y"
-
-/* List of types and structure classes of the current declaration. */
-static tree current_declspecs;
-
-/* When defining an aggregate, this is the most recent one being defined. */
-static tree current_aggr;
-
-/* Tell yyparse how to print a token's value, if yydebug is set. */
-
-#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
-extern void yyprint ();
-extern tree combine_strings PROTO((tree));
-extern tree truthvalue_conversion PROTO((tree));
-
-#ifndef YYLTYPE
-typedef
- struct yyltype
- {
- int timestamp;
- int first_line;
- int first_column;
- int last_line;
- int last_column;
- char *text;
- }
- yyltype;
-
-#define YYLTYPE yyltype
-#endif
-
-#include <stdio.h>
-
-#ifndef __STDC__
-#define const
-#endif
-
-
-
-#define YYFINAL 1276
-#define YYFLAG -32768
-#define YYNTBASE 110
-
-#define YYTRANSLATE(x) ((unsigned)(x) <= 340 ? yytranslate[x] : 304)
-
-static const char yytranslate[] = { 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 108, 2, 2, 2, 73, 61, 2, 83,
- 104, 71, 69, 51, 70, 81, 72, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 55, 105, 65,
- 53, 66, 54, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 84, 2, 109, 60, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 50, 59, 106, 107, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 52, 56, 57, 58, 62, 63,
- 64, 67, 68, 74, 75, 76, 77, 78, 79, 80,
- 82, 85, 86, 87, 88, 89, 90, 91, 92, 93,
- 94, 95, 96, 97, 98, 99, 100, 101, 102, 103
-};
-
-static const short yyprhs[] = { 0,
- 0, 1, 3, 4, 7, 10, 11, 12, 14, 16,
- 18, 20, 22, 24, 30, 35, 39, 44, 49, 51,
- 52, 58, 60, 64, 67, 72, 76, 78, 82, 84,
- 88, 89, 95, 96, 102, 103, 109, 110, 116, 120,
- 124, 131, 139, 144, 148, 152, 154, 156, 158, 160,
- 162, 165, 169, 173, 177, 181, 184, 187, 190, 193,
- 195, 199, 204, 208, 214, 219, 223, 227, 230, 234,
- 238, 241, 248, 255, 260, 265, 267, 274, 279, 283,
- 290, 295, 299, 302, 305, 307, 311, 316, 319, 323,
- 324, 325, 327, 331, 334, 338, 340, 345, 348, 353,
- 356, 361, 364, 370, 374, 376, 378, 380, 382, 384,
- 386, 388, 390, 392, 395, 397, 401, 406, 411, 413,
- 415, 416, 417, 419, 423, 425, 427, 428, 435, 436,
- 438, 439, 442, 444, 446, 448, 450, 452, 454, 456,
- 458, 462, 464, 468, 472, 474, 475, 479, 482, 485,
- 488, 491, 494, 497, 502, 505, 510, 514, 521, 528,
- 538, 543, 551, 557, 566, 576, 586, 593, 603, 610,
- 620, 624, 631, 634, 639, 645, 647, 652, 660, 665,
- 670, 675, 677, 681, 685, 689, 693, 697, 701, 705,
- 709, 713, 717, 721, 725, 729, 733, 737, 741, 745,
- 751, 755, 759, 763, 766, 768, 770, 772, 774, 778,
- 782, 783, 788, 789, 796, 799, 804, 807, 811, 814,
- 817, 819, 824, 829, 832, 838, 842, 845, 848, 851,
- 857, 861, 867, 871, 878, 883, 885, 890, 893, 899,
- 900, 902, 904, 907, 909, 912, 913, 916, 919, 922,
- 926, 930, 934, 938, 941, 944, 946, 948, 951, 954,
- 956, 959, 962, 966, 968, 970, 973, 976, 978, 980,
- 983, 986, 988, 991, 994, 998, 1000, 1003, 1005, 1007,
- 1009, 1011, 1016, 1021, 1023, 1025, 1027, 1029, 1031, 1035,
- 1037, 1041, 1042, 1047, 1048, 1056, 1061, 1062, 1070, 1075,
- 1076, 1084, 1089, 1090, 1097, 1099, 1103, 1105, 1110, 1119,
- 1121, 1125, 1127, 1130, 1134, 1139, 1141, 1143, 1147, 1152,
- 1159, 1163, 1169, 1170, 1178, 1183, 1184, 1191, 1195, 1198,
- 1203, 1205, 1206, 1208, 1209, 1211, 1213, 1216, 1222, 1225,
- 1228, 1231, 1234, 1237, 1240, 1243, 1247, 1251, 1254, 1255,
- 1259, 1260, 1264, 1267, 1269, 1271, 1272, 1274, 1277, 1279,
- 1283, 1285, 1287, 1290, 1293, 1296, 1300, 1302, 1304, 1306,
- 1309, 1312, 1314, 1315, 1317, 1322, 1326, 1328, 1331, 1334,
- 1338, 1344, 1350, 1354, 1358, 1362, 1366, 1370, 1376, 1382,
- 1386, 1390, 1394, 1398, 1400, 1403, 1406, 1410, 1414, 1415,
- 1417, 1421, 1426, 1433, 1438, 1442, 1445, 1450, 1457, 1462,
- 1466, 1469, 1471, 1475, 1477, 1481, 1484, 1487, 1488, 1490,
- 1493, 1495, 1498, 1499, 1502, 1503, 1506, 1512, 1518, 1522,
- 1528, 1533, 1537, 1541, 1547, 1549, 1551, 1557, 1561, 1565,
- 1567, 1573, 1579, 1583, 1589, 1594, 1598, 1602, 1604, 1606,
- 1610, 1614, 1620, 1626, 1630, 1636, 1640, 1644, 1648, 1653,
- 1657, 1659, 1661, 1664, 1667, 1670, 1674, 1678, 1686, 1694,
- 1700, 1708, 1712, 1720, 1728, 1734, 1742, 1746, 1748, 1751,
- 1754, 1756, 1759, 1763, 1767, 1770, 1772, 1776, 1780, 1783,
- 1789, 1793, 1798, 1802, 1807, 1810, 1814, 1817, 1821, 1826,
- 1830, 1835, 1841, 1847, 1849, 1851, 1854, 1857, 1860, 1861,
- 1862, 1864, 1866, 1869, 1873, 1875, 1878, 1881, 1887, 1893,
- 1894, 1895, 1901, 1903, 1906, 1908, 1910, 1912, 1915, 1916,
- 1921, 1923, 1924, 1925, 1931, 1932, 1933, 1941, 1942, 1943,
- 1944, 1954, 1955, 1956, 1957, 1967, 1968, 1975, 1976, 1982,
- 1983, 1991, 1992, 1997, 2000, 2003, 2006, 2010, 2017, 2026,
- 2037, 2050, 2055, 2059, 2062, 2065, 2067, 2070, 2074, 2081,
- 2086, 2093, 2098, 2102, 2103, 2111, 2114, 2115, 2121, 2125,
- 2127, 2130, 2134, 2138, 2141, 2144, 2146, 2147, 2152, 2155,
- 2159, 2163, 2164, 2165, 2170, 2171, 2172, 2177, 2178, 2183,
- 2184, 2186, 2187, 2188, 2197, 2201, 2206, 2211, 2215, 2220,
- 2227, 2234, 2235, 2237, 2238, 2240, 2242, 2243, 2245, 2247,
- 2251, 2256, 2258, 2262, 2263, 2265, 2269, 2272, 2274, 2276,
- 2279, 2282, 2284, 2288, 2292, 2298, 2302, 2308, 2312, 2316,
- 2318, 2320, 2323, 2325, 2326, 2328, 2329, 2332, 2337, 2339,
- 2341, 2343, 2346, 2349, 2352, 2354, 2356, 2358, 2362, 2364,
- 2368, 2371, 2374, 2377, 2380, 2383, 2386, 2389, 2392, 2395,
- 2398, 2401, 2404, 2407, 2410, 2413, 2416, 2419, 2422, 2425,
- 2428, 2431, 2434, 2437, 2441, 2444, 2447, 2450, 2454, 2457,
- 2461, 2464, 2467, 2471
-};
-
-static const short yyrhs[] = { -1,
- 111, 0, 0, 112, 116, 0, 111, 116, 0, 0,
- 0, 26, 0, 27, 0, 131, 0, 130, 0, 124,
- 0, 122, 0, 115, 83, 167, 104, 105, 0, 117,
- 50, 111, 106, 0, 117, 50, 106, 0, 117, 113,
- 131, 114, 0, 117, 113, 130, 114, 0, 97, 0,
- 0, 45, 65, 119, 120, 66, 0, 121, 0, 120,
- 51, 121, 0, 200, 140, 0, 200, 141, 55, 212,
- 0, 200, 49, 212, 0, 293, 0, 39, 123, 105,
- 0, 3, 0, 123, 51, 3, 0, 0, 118, 201,
- 50, 125, 105, 0, 0, 118, 202, 50, 126, 105,
- 0, 0, 118, 201, 55, 127, 105, 0, 0, 118,
- 202, 55, 128, 105, 0, 118, 201, 105, 0, 118,
- 202, 105, 0, 118, 231, 298, 182, 189, 129, 0,
- 118, 173, 172, 298, 182, 189, 129, 0, 118, 175,
- 172, 129, 0, 118, 1, 106, 0, 118, 1, 105,
- 0, 50, 0, 55, 0, 105, 0, 53, 0, 24,
- 0, 181, 105, 0, 175, 181, 105, 0, 175, 172,
- 105, 0, 173, 180, 105, 0, 173, 172, 105, 0,
- 175, 105, 0, 173, 105, 0, 1, 105, 0, 1,
- 106, 0, 105, 0, 132, 136, 244, 0, 132, 135,
- 136, 244, 0, 132, 168, 244, 0, 132, 135, 105,
- 168, 244, 0, 132, 135, 168, 244, 0, 173, 172,
- 1, 0, 175, 231, 1, 0, 231, 1, 0, 173,
- 172, 298, 0, 175, 231, 298, 0, 231, 298, 0,
- 4, 83, 291, 104, 226, 298, 0, 234, 83, 291,
- 104, 226, 298, 0, 4, 44, 226, 298, 0, 234,
- 44, 226, 298, 0, 96, 0, 173, 83, 291, 104,
- 226, 298, 0, 173, 44, 226, 298, 0, 173, 172,
- 298, 0, 175, 83, 291, 104, 226, 298, 0, 175,
- 44, 226, 298, 0, 175, 172, 298, 0, 231, 298,
- 0, 24, 3, 0, 134, 0, 134, 53, 193, 0,
- 134, 83, 156, 104, 0, 134, 44, 0, 55, 137,
- 138, 0, 0, 0, 139, 0, 138, 51, 139, 0,
- 138, 1, 0, 83, 156, 104, 0, 44, 0, 140,
- 83, 156, 104, 0, 140, 44, 0, 144, 83, 156,
- 104, 0, 144, 44, 0, 234, 83, 156, 104, 0,
- 234, 44, 0, 232, 140, 83, 156, 104, 0, 232,
- 140, 44, 0, 3, 0, 4, 0, 95, 0, 101,
- 0, 100, 0, 102, 0, 3, 0, 4, 0, 95,
- 0, 107, 140, 0, 303, 0, 144, 145, 151, 0,
- 95, 65, 147, 66, 0, 4, 65, 147, 66, 0,
- 50, 0, 55, 0, 0, 0, 148, 0, 147, 51,
- 148, 0, 223, 0, 160, 0, 0, 99, 208, 150,
- 214, 215, 106, 0, 0, 149, 0, 0, 149, 152,
- 0, 70, 0, 69, 0, 75, 0, 76, 0, 108,
- 0, 156, 0, 160, 0, 44, 0, 83, 154, 104,
- 0, 160, 0, 156, 51, 160, 0, 156, 51, 1,
- 0, 161, 0, 0, 33, 158, 159, 0, 71, 159,
- 0, 61, 159, 0, 107, 159, 0, 153, 159, 0,
- 58, 140, 0, 12, 157, 0, 12, 83, 223, 104,
- 0, 29, 157, 0, 29, 83, 223, 104, 0, 165,
- 164, 223, 0, 165, 164, 83, 156, 104, 223, 0,
- 165, 164, 178, 83, 156, 104, 0, 165, 164, 83,
- 156, 104, 178, 83, 156, 104, 0, 165, 164, 178,
- 44, 0, 165, 164, 83, 156, 104, 178, 44, 0,
- 165, 164, 223, 53, 193, 0, 165, 164, 83, 156,
- 104, 223, 53, 193, 0, 165, 164, 83, 176, 224,
- 104, 84, 227, 109, 0, 165, 164, 83, 225, 224,
- 104, 84, 227, 109, 0, 165, 164, 83, 176, 224,
- 104, 0, 165, 164, 83, 156, 104, 83, 176, 224,
- 104, 0, 165, 164, 83, 225, 224, 104, 0, 165,
- 164, 83, 156, 104, 83, 225, 224, 104, 0, 165,
- 164, 49, 0, 165, 164, 83, 156, 104, 49, 0,
- 166, 159, 0, 166, 84, 109, 159, 0, 166, 84,
- 154, 109, 159, 0, 157, 0, 83, 223, 104, 160,
- 0, 83, 223, 104, 50, 194, 198, 106, 0, 30,
- 83, 154, 104, 0, 31, 83, 154, 104, 0, 31,
- 83, 4, 104, 0, 159, 0, 160, 69, 160, 0,
- 160, 70, 160, 0, 160, 71, 160, 0, 160, 72,
- 160, 0, 160, 73, 160, 0, 160, 67, 160, 0,
- 160, 68, 160, 0, 160, 64, 160, 0, 160, 65,
- 160, 0, 160, 66, 160, 0, 160, 63, 160, 0,
- 160, 62, 160, 0, 160, 61, 160, 0, 160, 59,
- 160, 0, 160, 60, 160, 0, 160, 58, 160, 0,
- 160, 57, 160, 0, 160, 54, 286, 55, 160, 0,
- 160, 53, 160, 0, 160, 52, 160, 0, 161, 82,
- 160, 0, 170, 160, 0, 3, 0, 303, 0, 9,
- 0, 167, 0, 83, 154, 104, 0, 83, 1, 104,
- 0, 0, 83, 162, 245, 104, 0, 0, 161, 83,
- 156, 104, 163, 152, 0, 161, 44, 0, 161, 84,
- 154, 109, 0, 169, 142, 0, 169, 232, 142, 0,
- 161, 75, 0, 161, 76, 0, 40, 0, 8, 83,
- 156, 104, 0, 178, 83, 156, 104, 0, 178, 44,
- 0, 46, 178, 83, 156, 104, 0, 46, 178, 44,
- 0, 46, 3, 0, 46, 303, 0, 232, 142, 0,
- 232, 142, 83, 156, 104, 0, 232, 142, 44, 0,
- 169, 142, 83, 156, 104, 0, 169, 142, 44, 0,
- 169, 232, 142, 83, 156, 104, 0, 169, 232, 142,
- 44, 0, 38, 0, 38, 50, 156, 106, 0, 38,
- 42, 0, 38, 42, 83, 167, 104, 0, 0, 46,
- 0, 37, 0, 46, 166, 0, 10, 0, 167, 10,
- 0, 0, 161, 81, 0, 161, 79, 0, 161, 80,
- 0, 173, 180, 105, 0, 173, 172, 105, 0, 175,
- 181, 105, 0, 175, 172, 105, 0, 173, 105, 0,
- 175, 105, 0, 229, 0, 231, 0, 47, 229, 0,
- 47, 231, 0, 178, 0, 175, 178, 0, 178, 174,
- 0, 175, 178, 174, 0, 179, 0, 6, 0, 174,
- 179, 0, 174, 6, 0, 8, 0, 6, 0, 175,
- 8, 0, 175, 6, 0, 178, 0, 225, 178, 0,
- 178, 177, 0, 225, 178, 177, 0, 179, 0, 177,
- 179, 0, 195, 0, 7, 0, 4, 0, 234, 0,
- 28, 83, 154, 104, 0, 28, 83, 223, 104, 0,
- 143, 0, 7, 0, 8, 0, 195, 0, 183, 0,
- 180, 51, 185, 0, 187, 0, 181, 51, 185, 0,
- 0, 115, 83, 167, 104, 0, 0, 172, 298, 182,
- 189, 53, 184, 193, 0, 172, 298, 182, 189, 0,
- 0, 172, 298, 182, 189, 53, 186, 193, 0, 172,
- 298, 182, 189, 0, 0, 231, 298, 182, 189, 53,
- 188, 193, 0, 231, 298, 182, 189, 0, 0, 32,
- 83, 83, 190, 104, 104, 0, 191, 0, 190, 51,
- 191, 0, 3, 0, 3, 83, 9, 104, 0, 3,
- 83, 3, 51, 9, 51, 9, 104, 0, 140, 0,
- 192, 51, 140, 0, 160, 0, 50, 106, 0, 50,
- 194, 106, 0, 50, 194, 51, 106, 0, 1, 0,
- 193, 0, 194, 51, 193, 0, 84, 160, 109, 193,
- 0, 194, 51, 20, 160, 55, 193, 0, 140, 55,
- 193, 0, 194, 51, 140, 55, 193, 0, 0, 13,
- 140, 50, 196, 221, 199, 106, 0, 13, 140, 50,
- 106, 0, 0, 13, 50, 197, 221, 199, 106, 0,
- 13, 50, 106, 0, 13, 140, 0, 207, 214, 215,
- 106, 0, 207, 0, 0, 51, 0, 0, 51, 0,
- 35, 0, 42, 35, 0, 42, 83, 167, 104, 35,
- 0, 200, 6, 0, 200, 7, 0, 200, 8, 0,
- 200, 35, 0, 200, 140, 0, 200, 144, 0, 200,
- 49, 0, 200, 144, 50, 0, 200, 144, 55, 0,
- 200, 141, 0, 0, 201, 204, 208, 0, 0, 202,
- 205, 208, 0, 200, 50, 0, 206, 0, 203, 0,
- 0, 55, 0, 55, 209, 0, 210, 0, 209, 51,
- 210, 0, 212, 0, 211, 0, 213, 212, 0, 213,
- 211, 0, 212, 5, 0, 144, 146, 151, 0, 140,
- 0, 36, 0, 6, 0, 213, 36, 0, 213, 6,
- 0, 50, 0, 0, 216, 0, 215, 36, 55, 216,
- 0, 215, 36, 55, 0, 217, 0, 216, 217, 0,
- 216, 105, 0, 173, 218, 105, 0, 173, 83, 291,
- 104, 105, 0, 173, 83, 291, 104, 106, 0, 173,
- 44, 105, 0, 173, 44, 106, 0, 175, 218, 105,
- 0, 175, 172, 105, 0, 175, 218, 106, 0, 175,
- 83, 291, 104, 105, 0, 175, 83, 291, 104, 106,
- 0, 175, 44, 105, 0, 175, 44, 106, 0, 55,
- 160, 105, 0, 55, 160, 106, 0, 1, 0, 133,
- 55, 0, 133, 50, 0, 231, 298, 105, 0, 231,
- 298, 106, 0, 0, 219, 0, 218, 51, 220, 0,
- 172, 298, 182, 189, 0, 172, 298, 182, 189, 53,
- 193, 0, 3, 55, 160, 189, 0, 49, 160, 189,
- 0, 55, 160, 0, 172, 298, 182, 189, 0, 172,
- 298, 182, 189, 53, 193, 0, 3, 55, 160, 189,
- 0, 49, 160, 189, 0, 55, 160, 0, 222, 0,
- 221, 51, 222, 0, 140, 0, 140, 53, 160, 0,
- 176, 224, 0, 225, 224, 0, 0, 235, 0, 47,
- 235, 0, 8, 0, 225, 8, 0, 0, 226, 8,
- 0, 0, 228, 154, 0, 229, 83, 156, 104, 226,
- 0, 229, 83, 291, 104, 226, 0, 229, 44, 226,
- 0, 229, 83, 1, 104, 226, 0, 229, 84, 227,
- 109, 0, 229, 84, 109, 0, 83, 230, 104, 0,
- 83, 71, 226, 229, 104, 0, 78, 0, 237, 0,
- 83, 61, 226, 229, 104, 0, 71, 226, 229, 0,
- 61, 226, 229, 0, 4, 0, 230, 83, 156, 104,
- 226, 0, 230, 83, 291, 104, 226, 0, 230, 44,
- 226, 0, 230, 83, 1, 104, 226, 0, 230, 84,
- 227, 109, 0, 230, 84, 109, 0, 83, 230, 104,
- 0, 78, 0, 237, 0, 71, 226, 229, 0, 61,
- 226, 229, 0, 231, 83, 156, 104, 226, 0, 231,
- 83, 291, 104, 226, 0, 231, 44, 226, 0, 231,
- 83, 1, 104, 226, 0, 83, 231, 104, 0, 71,
- 226, 231, 0, 61, 226, 231, 0, 231, 84, 227,
- 109, 0, 231, 84, 109, 0, 3, 0, 303, 0,
- 107, 4, 0, 107, 3, 0, 107, 95, 0, 232,
- 295, 231, 0, 232, 295, 4, 0, 232, 295, 4,
- 83, 156, 104, 226, 0, 232, 295, 4, 83, 291,
- 104, 226, 0, 232, 295, 4, 44, 226, 0, 232,
- 295, 4, 83, 1, 104, 226, 0, 232, 295, 95,
- 0, 232, 295, 95, 83, 156, 104, 226, 0, 232,
- 295, 95, 83, 291, 104, 226, 0, 232, 295, 95,
- 44, 226, 0, 232, 295, 95, 83, 1, 104, 226,
- 0, 46, 295, 231, 0, 233, 0, 143, 46, 0,
- 4, 46, 0, 5, 0, 143, 5, 0, 83, 235,
- 104, 0, 71, 226, 235, 0, 71, 226, 0, 78,
- 0, 83, 236, 104, 0, 61, 226, 235, 0, 61,
- 226, 0, 235, 83, 291, 104, 226, 0, 235, 44,
- 226, 0, 235, 84, 227, 109, 0, 235, 84, 109,
- 0, 83, 291, 104, 226, 0, 44, 226, 0, 84,
- 227, 109, 0, 84, 109, 0, 232, 71, 226, 0,
- 232, 71, 226, 235, 0, 232, 61, 226, 0, 232,
- 61, 226, 235, 0, 232, 295, 71, 226, 229, 0,
- 232, 295, 61, 226, 229, 0, 250, 0, 239, 0,
- 238, 250, 0, 238, 239, 0, 1, 105, 0, 0,
- 0, 242, 0, 243, 0, 242, 243, 0, 34, 192,
- 105, 0, 245, 0, 1, 245, 0, 50, 106, 0,
- 50, 240, 241, 238, 106, 0, 50, 240, 241, 1,
- 106, 0, 0, 0, 14, 247, 155, 248, 249, 0,
- 245, 0, 240, 251, 0, 245, 0, 251, 0, 171,
- 0, 154, 105, 0, 0, 246, 15, 252, 249, 0,
- 246, 0, 0, 0, 16, 253, 155, 254, 249, 0,
- 0, 0, 17, 255, 249, 16, 256, 155, 105, 0,
- 0, 0, 0, 283, 257, 286, 105, 258, 286, 104,
- 259, 249, 0, 0, 0, 0, 284, 260, 286, 105,
- 261, 286, 104, 262, 249, 0, 0, 19, 83, 154,
- 104, 263, 249, 0, 0, 20, 154, 55, 264, 250,
- 0, 0, 20, 154, 56, 154, 55, 265, 250, 0,
- 0, 21, 55, 266, 250, 0, 22, 105, 0, 23,
- 105, 0, 24, 105, 0, 24, 154, 105, 0, 115,
- 285, 83, 167, 104, 105, 0, 115, 285, 83, 167,
- 55, 287, 104, 105, 0, 115, 285, 83, 167, 55,
- 287, 55, 287, 104, 105, 0, 115, 285, 83, 167,
- 55, 287, 55, 287, 55, 290, 104, 105, 0, 25,
- 71, 154, 105, 0, 25, 140, 105, 0, 270, 250,
- 0, 270, 106, 0, 105, 0, 93, 105, 0, 93,
- 154, 105, 0, 91, 299, 83, 156, 104, 105, 0,
- 91, 299, 44, 105, 0, 85, 299, 83, 156, 104,
- 105, 0, 85, 299, 44, 105, 0, 85, 140, 105,
- 0, 0, 269, 89, 140, 50, 267, 277, 106, 0,
- 269, 1, 0, 0, 273, 274, 274, 268, 281, 0,
- 269, 87, 301, 0, 269, 0, 271, 106, 0, 271,
- 238, 106, 0, 271, 1, 106, 0, 3, 55, 0,
- 95, 55, 0, 49, 0, 0, 88, 50, 272, 240,
- 0, 275, 106, 0, 275, 238, 106, 0, 275, 1,
- 106, 0, 0, 0, 92, 50, 276, 240, 0, 0,
- 0, 277, 299, 278, 245, 0, 0, 277, 21, 279,
- 245, 0, 0, 140, 0, 0, 0, 281, 90, 83,
- 223, 280, 104, 282, 245, 0, 18, 83, 105, 0,
- 18, 83, 154, 105, 0, 18, 83, 50, 106, 0,
- 18, 83, 171, 0, 18, 83, 1, 105, 0, 18,
- 83, 50, 240, 238, 106, 0, 18, 83, 50, 240,
- 1, 106, 0, 0, 8, 0, 0, 154, 0, 1,
- 0, 0, 288, 0, 289, 0, 288, 51, 289, 0,
- 10, 83, 154, 104, 0, 10, 0, 290, 51, 10,
- 0, 0, 292, 0, 292, 51, 11, 0, 292, 11,
- 0, 11, 0, 94, 0, 292, 94, 0, 292, 55,
- 0, 293, 0, 293, 53, 193, 0, 292, 51, 293,
- 0, 292, 51, 293, 53, 193, 0, 292, 51, 297,
- 0, 292, 51, 297, 53, 193, 0, 173, 296, 294,
- 0, 175, 296, 294, 0, 224, 0, 231, 0, 47,
- 231, 0, 226, 0, 0, 294, 0, 0, 86, 301,
- 0, 93, 83, 302, 104, 0, 98, 0, 3, 0,
- 4, 0, 46, 3, 0, 46, 4, 0, 232, 3,
- 0, 234, 0, 223, 0, 299, 0, 301, 51, 299,
- 0, 300, 0, 302, 51, 300, 0, 41, 71, 0,
- 41, 72, 0, 41, 73, 0, 41, 69, 0, 41,
- 70, 0, 41, 61, 0, 41, 59, 0, 41, 60,
- 0, 41, 107, 0, 41, 51, 0, 41, 64, 0,
- 41, 65, 0, 41, 66, 0, 41, 63, 0, 41,
- 52, 0, 41, 53, 0, 41, 67, 0, 41, 68,
- 0, 41, 75, 0, 41, 76, 0, 41, 58, 0,
- 41, 57, 0, 41, 108, 0, 41, 54, 55, 0,
- 41, 62, 0, 41, 79, 0, 41, 80, 0, 41,
- 43, 226, 0, 41, 44, 0, 41, 84, 109, 0,
- 41, 38, 0, 41, 37, 0, 41, 176, 224, 0,
- 41, 1, 0
-};
-
-#if YYDEBUG != 0
-static const short yyrline[] = { 0,
- 283, 284, 292, 294, 295, 299, 304, 308, 311, 314,
- 317, 319, 321, 322, 325, 327, 329, 332, 337, 342,
- 345, 349, 352, 356, 369, 376, 383, 386, 391, 393,
- 397, 403, 403, 406, 406, 409, 409, 422, 422, 427,
- 432, 447, 470, 479, 480, 483, 484, 485, 486, 487,
- 490, 496, 499, 504, 510, 517, 519, 537, 538, 539,
- 542, 556, 569, 572, 575, 578, 580, 582, 586, 592,
- 597, 602, 607, 612, 617, 622, 628, 638, 647, 654,
- 663, 672, 679, 688, 696, 698, 700, 702, 706, 715,
- 738, 741, 743, 744, 747, 754, 761, 765, 767, 769,
- 771, 773, 775, 779, 785, 787, 788, 791, 793, 794,
- 797, 799, 800, 804, 805, 808, 837, 840, 844, 848,
- 849, 853, 858, 861, 865, 868, 871, 903, 922, 925,
- 929, 932, 936, 938, 940, 942, 944, 948, 951, 954,
- 959, 963, 966, 968, 972, 979, 982, 985, 987, 989,
- 991, 997, 1002, 1022, 1024, 1057, 1060, 1062, 1064, 1066,
- 1068, 1070, 1072, 1074, 1082, 1092, 1095, 1097, 1099, 1101,
- 1104, 1106, 1109, 1137, 1156, 1181, 1183, 1186, 1201, 1203,
- 1205, 1216, 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1232,
- 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248, 1250, 1252,
- 1254, 1256, 1263, 1266, 1281, 1284, 1299, 1300, 1302, 1304,
- 1306, 1314, 1329, 1334, 1341, 1351, 1401, 1403, 1419, 1421,
- 1425, 1448, 1492, 1494, 1496, 1498, 1500, 1539, 1546, 1548,
- 1550, 1552, 1555, 1558, 1560, 1602, 1604, 1609, 1611, 1615,
- 1618, 1622, 1624, 1632, 1634, 1638, 1647, 1662, 1668, 1671,
- 1678, 1686, 1689, 1696, 1701, 1708, 1710, 1711, 1713, 1721,
- 1724, 1726, 1728, 1732, 1736, 1741, 1743, 1754, 1758, 1760,
- 1763, 1778, 1781, 1783, 1785, 1789, 1792, 1800, 1801, 1802,
- 1803, 1804, 1808, 1812, 1817, 1818, 1819, 1822, 1824, 1827,
- 1829, 1832, 1835, 1839, 1847, 1849, 1858, 1864, 1865, 1871,
- 1879, 1881, 1892, 1895, 1900, 1902, 1907, 1912, 1923, 1938,
- 1941, 1945, 1947, 1952, 1955, 1958, 1964, 1967, 1970, 1972,
- 1974, 1976, 1980, 1984, 1988, 1991, 1994, 1998, 2001, 2005,
- 2060, 2075, 2077, 2080, 2082, 2087, 2088, 2090, 2092, 2095,
- 2098, 2101, 2106, 2109, 2111, 2113, 2119, 2123, 2128, 2133,
- 2140, 2145, 2154, 2159, 2159, 2161, 2164, 2166, 2170, 2172,
- 2176, 2181, 2185, 2189, 2195, 2204, 2218, 2221, 2223, 2227,
- 2253, 2262, 2288, 2291, 2293, 2295, 2298, 2301, 2304, 2309,
- 2374, 2376, 2380, 2382, 2386, 2389, 2392, 2396, 2398, 2402,
- 2404, 2408, 2410, 2414, 2419, 2421, 2423, 2425, 2431, 2434,
- 2435, 2446, 2451, 2455, 2459, 2463, 2468, 2472, 2475, 2478,
- 2481, 2489, 2491, 2495, 2498, 2502, 2505, 2509, 2512, 2513,
- 2517, 2520, 2524, 2527, 2535, 2537, 2541, 2544, 2546, 2548,
- 2550, 2552, 2554, 2556, 2558, 2560, 2561, 2563, 2565, 2567,
- 2570, 2573, 2575, 2577, 2579, 2581, 2583, 2585, 2587, 2588,
- 2590, 2597, 2600, 2602, 2604, 2606, 2608, 2610, 2612, 2614,
- 2616, 2620, 2623, 2629, 2631, 2633, 2642, 2644, 2646, 2648,
- 2650, 2653, 2655, 2657, 2659, 2661, 2663, 2667, 2675, 2692,
- 2695, 2696, 2717, 2722, 2724, 2726, 2728, 2730, 2732, 2734,
- 2736, 2738, 2740, 2742, 2744, 2746, 2748, 2752, 2760, 2767,
- 2774, 2783, 2791, 2804, 2806, 2807, 2808, 2811, 2818, 2828,
- 2830, 2835, 2837, 2840, 2854, 2857, 2860, 2862, 2867, 2874,
- 2878, 2881, 2883, 2886, 2893, 2896, 2899, 2902, 2915, 2918,
- 2920, 2923, 2929, 2931, 2933, 2937, 2940, 2946, 2951, 2954,
- 2959, 2965, 2969, 2972, 2978, 2993, 3000, 3003, 3053, 3053,
- 3132, 3132, 3148, 3148, 3152, 3156, 3159, 3164, 3171, 3180,
- 3189, 3198, 3201, 3207, 3209, 3213, 3217, 3218, 3219, 3222,
- 3225, 3228, 3231, 3234, 3246, 3275, 3285, 3298, 3326, 3357,
- 3369, 3377, 3382, 3389, 3397, 3399, 3406, 3408, 3408, 3416,
- 3421, 3428, 3429, 3431, 3431, 3434, 3455, 3471, 3490, 3508,
- 3511, 3513, 3516, 3533, 3551, 3554, 3556, 3560, 3563, 3565,
- 3567, 3573, 3576, 3580, 3583, 3584, 3590, 3592, 3595, 3597,
- 3601, 3606, 3609, 3618, 3625, 3630, 3635, 3639, 3646, 3650,
- 3654, 3668, 3671, 3673, 3675, 3677, 3679, 3687, 3703, 3708,
- 3709, 3710, 3714, 3718, 3736, 3744, 3747, 3749, 3753, 3756,
- 3758, 3760, 3762, 3764, 3766, 3769, 3774, 3776, 3783, 3785,
- 3792, 3795, 3797, 3799, 3801, 3803, 3805, 3807, 3809, 3811,
- 3813, 3815, 3817, 3819, 3821, 3823, 3832, 3834, 3836, 3838,
- 3840, 3842, 3844, 3846, 3848, 3850, 3862, 3874, 3905, 3917,
- 3929, 3942, 3958, 3960
-};
-
-static const char * const yytname[] = { "$","error","$illegal.","IDENTIFIER",
-"TYPENAME","SCOPED_TYPENAME","SCSPEC","TYPESPEC","TYPE_QUAL","CONSTANT","STRING",
-"ELLIPSIS","SIZEOF","ENUM","IF","ELSE","WHILE","DO","FOR","SWITCH","CASE","DEFAULT",
-"BREAK","CONTINUE","RETURN","GOTO","ASM_KEYWORD","GCC_ASM_KEYWORD","TYPEOF",
-"ALIGNOF","HEADOF","CLASSOF","ATTRIBUTE","EXTENSION","LABEL","AGGR","VISSPEC",
-"DELETE","NEW","OVERLOAD","THIS","OPERATOR","DYNAMIC","POINTSAT_LEFT_RIGHT",
-"LEFT_RIGHT","TEMPLATE","SCOPE","START_DECLARATOR","EMPTY","TYPENAME_COLON",
-"'{'","','","ASSIGN","'='","'?'","':'","RANGE","OROR","ANDAND","'|'","'^'","'&'",
-"MIN_MAX","EQCOMPARE","ARITHCOMPARE","'<'","'>'","LSHIFT","RSHIFT","'+'","'-'",
-"'*'","'/'","'%'","UNARY","PLUSPLUS","MINUSMINUS","HYPERUNARY","PAREN_STAR_PAREN",
-"POINTSAT","POINTSAT_STAR","'.'","DOT_STAR","'('","'['","RAISE","RAISES","RERAISE",
-"TRY","EXCEPT","CATCH","THROW","ANSI_TRY","ANSI_THROW","TYPENAME_ELLIPSIS","PTYPENAME",
-"PRE_PARSED_FUNCTION_DECL","EXTERN_LANG_STRING","ALL","PRE_PARSED_CLASS_DECL",
-"TYPENAME_DEFN","IDENTIFIER_DEFN","PTYPENAME_DEFN","END_OF_SAVED_INPUT","')'",
-"';'","'}'","'~'","'!'","']'","program","extdefs","@1",".hush_warning",".warning_ok",
-"asm_keyword","extdef","extern_lang_string","template_header","@2","template_parm_list",
-"template_parm","overloaddef","ov_identifiers","template_def","@3","@4","@5",
-"@6","fn_tmpl_end","datadef","fndef","fn.def1","fn.def2","return_id","return_init",
-"base_init",".set_base_init","member_init_list","member_init","identifier","identifier_defn",
-"identifier_or_opname","template_type","template_type_name","tmpl.1","tmpl.2",
-"template_arg_list","template_arg","template_instantiate_once","@7","template_instantiation",
-"template_instantiate_some","unop","expr","paren_expr_or_null","nonnull_exprlist",
-"unary_expr","@8","cast_expr","expr_no_commas","primary","@9","@10","new",".scope",
-"delete","string","nodecls","object","object_star","decl","declarator","typed_declspecs",
-"reserved_declspecs","declmods","typed_typespecs","reserved_typespecquals","typespec",
-"typespecqual_reserved","initdecls","notype_initdecls","maybeasm","initdcl0",
-"@11","initdcl","@12","notype_initdcl0","@13","maybe_attribute","attribute_list",
-"attrib","identifiers_or_typenames","init","initlist","structsp","@14","@15",
-"maybecomma","maybecomma_warn","aggr","named_class_head_sans_basetype","named_class_head_sans_basetype_defn",
-"named_class_head","@16","@17","unnamed_class_head","class_head","maybe_base_class_list",
-"base_class_list","base_class","scoped_base_class","base_class.1","base_class_visibility_list",
-"left_curly","opt.component_decl_list","component_decl_list","component_decl",
-"components","component_declarator0","component_declarator","enumlist","enumerator",
-"typename","absdcl","nonempty_type_quals","type_quals","nonmomentary_expr","@18",
-"after_type_declarator","after_type_declarator_no_typename","notype_declarator",
-"scoped_id","typename_scope","scoped_typename","absdcl1","abs_member_declarator",
-"after_type_member_declarator","stmts","errstmt",".pushlevel","maybe_label_decls",
-"label_decls","label_decl","compstmt_or_error","compstmt","simple_if","@19",
-"@20","implicitly_scoped_stmt","stmt","simple_stmt","@21","@22","@23","@24",
-"@25","@26","@27","@28","@29","@30","@31","@32","@33","@34","@35","@36","@37",
-"try","label_colon","try_head","@38","ansi_try","ansi_dummy","ansi_try_head",
-"@39","except_stmts","@40","@41","optional_identifier","ansi_except_stmts","@42",
-"forhead.1","forhead.2","maybe_type_qual","xexpr","asm_operands","nonnull_asm_operands",
-"asm_operand","asm_clobbers","parmlist","parms","parm","abs_or_notype_decl",
-"see_typename","dont_see_typename","bad_parm","maybe_raises","raise_identifier",
-"ansi_raise_identifier","raise_identifiers","ansi_raise_identifiers","operator_name",
-""
-};
-#endif
-
-static const short yyr1[] = { 0,
- 110, 110, 112, 111, 111, 113, 114, 115, 115, 116,
- 116, 116, 116, 116, 116, 116, 116, 116, 117, 119,
- 118, 120, 120, 121, 121, 121, 121, 122, 123, 123,
- 125, 124, 126, 124, 127, 124, 128, 124, 124, 124,
- 124, 124, 124, 124, 124, 129, 129, 129, 129, 129,
- 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
- 131, 131, 131, 131, 131, 131, 131, 131, 132, 132,
- 132, 132, 132, 132, 132, 132, 133, 133, 133, 133,
- 133, 133, 133, 134, 135, 135, 135, 135, 136, 137,
- 138, 138, 138, 138, 139, 139, 139, 139, 139, 139,
- 139, 139, 139, 139, 140, 140, 140, 141, 141, 141,
- 142, 142, 142, 142, 142, 143, 144, 144, 145, 145,
- 145, 146, 147, 147, 148, 148, 150, 149, 151, 151,
- 152, 152, 153, 153, 153, 153, 153, 154, 154, 155,
- 155, 156, 156, 156, 157, 158, 157, 157, 157, 157,
- 157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
- 157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
- 157, 157, 157, 157, 157, 159, 159, 159, 159, 159,
- 159, 160, 160, 160, 160, 160, 160, 160, 160, 160,
- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
- 160, 160, 160, 160, 161, 161, 161, 161, 161, 161,
- 162, 161, 163, 161, 161, 161, 161, 161, 161, 161,
- 161, 161, 161, 161, 161, 161, 161, 161, 161, 161,
- 161, 161, 161, 161, 161, 164, 164, 164, 164, 165,
- 165, 166, 166, 167, 167, 168, 169, 169, 170, 171,
- 171, 171, 171, 171, 171, 172, 172, 172, 172, 173,
- 173, 173, 173, 174, 174, 174, 174, 175, 175, 175,
- 175, 176, 176, 176, 176, 177, 177, 178, 178, 178,
- 178, 178, 178, 178, 179, 179, 179, 180, 180, 181,
- 181, 182, 182, 184, 183, 183, 186, 185, 185, 188,
- 187, 187, 189, 189, 190, 190, 191, 191, 191, 192,
- 192, 193, 193, 193, 193, 193, 194, 194, 194, 194,
- 194, 194, 196, 195, 195, 197, 195, 195, 195, 195,
- 195, 198, 198, 199, 199, 200, 200, 200, 200, 200,
- 200, 200, 201, 201, 201, 201, 201, 202, 204, 203,
- 205, 203, 206, 207, 207, 208, 208, 208, 209, 209,
- 210, 210, 210, 210, 211, 212, 212, 213, 213, 213,
- 213, 214, 215, 215, 215, 215, 216, 216, 216, 217,
- 217, 217, 217, 217, 217, 217, 217, 217, 217, 217,
- 217, 217, 217, 217, 217, 217, 217, 217, 218, 218,
- 218, 219, 219, 219, 219, 219, 220, 220, 220, 220,
- 220, 221, 221, 222, 222, 223, 223, 224, 224, 224,
- 225, 225, 226, 226, 228, 227, 229, 229, 229, 229,
- 229, 229, 229, 229, 229, 229, 229, 229, 229, 229,
- 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
- 230, 231, 231, 231, 231, 231, 231, 231, 231, 231,
- 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
- 231, 231, 231, 231, 231, 231, 231, 232, 232, 233,
- 234, 234, 235, 235, 235, 235, 235, 235, 235, 235,
- 235, 235, 235, 235, 235, 235, 235, 236, 236, 236,
- 236, 237, 237, 238, 238, 238, 238, 239, 240, 241,
- 241, 242, 242, 243, 244, 244, 245, 245, 245, 247,
- 248, 246, 249, 249, 250, 250, 251, 251, 252, 251,
- 251, 253, 254, 251, 255, 256, 251, 257, 258, 259,
- 251, 260, 261, 262, 251, 263, 251, 264, 251, 265,
- 251, 266, 251, 251, 251, 251, 251, 251, 251, 251,
- 251, 251, 251, 251, 251, 251, 251, 251, 251, 251,
- 251, 251, 251, 267, 251, 251, 268, 251, 251, 251,
- 269, 269, 269, 270, 270, 270, 272, 271, 273, 273,
- 273, 274, 276, 275, 277, 278, 277, 279, 277, 280,
- 280, 281, 282, 281, 283, 283, 283, 284, 284, 284,
- 284, 285, 285, 286, 286, 286, 287, 287, 288, 288,
- 289, 290, 290, 291, 291, 291, 291, 291, 291, 291,
- 291, 292, 292, 292, 292, 292, 292, 293, 293, 294,
- 294, 294, 295, 296, 297, 298, 298, 298, 299, 299,
- 299, 299, 299, 299, 299, 300, 301, 301, 302, 302,
- 303, 303, 303, 303, 303, 303, 303, 303, 303, 303,
- 303, 303, 303, 303, 303, 303, 303, 303, 303, 303,
- 303, 303, 303, 303, 303, 303, 303, 303, 303, 303,
- 303, 303, 303, 303
-};
-
-static const short yyr2[] = { 0,
- 0, 1, 0, 2, 2, 0, 0, 1, 1, 1,
- 1, 1, 1, 5, 4, 3, 4, 4, 1, 0,
- 5, 1, 3, 2, 4, 3, 1, 3, 1, 3,
- 0, 5, 0, 5, 0, 5, 0, 5, 3, 3,
- 6, 7, 4, 3, 3, 1, 1, 1, 1, 1,
- 2, 3, 3, 3, 3, 2, 2, 2, 2, 1,
- 3, 4, 3, 5, 4, 3, 3, 2, 3, 3,
- 2, 6, 6, 4, 4, 1, 6, 4, 3, 6,
- 4, 3, 2, 2, 1, 3, 4, 2, 3, 0,
- 0, 1, 3, 2, 3, 1, 4, 2, 4, 2,
- 4, 2, 5, 3, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 1, 3, 4, 4, 1, 1,
- 0, 0, 1, 3, 1, 1, 0, 6, 0, 1,
- 0, 2, 1, 1, 1, 1, 1, 1, 1, 1,
- 3, 1, 3, 3, 1, 0, 3, 2, 2, 2,
- 2, 2, 2, 4, 2, 4, 3, 6, 6, 9,
- 4, 7, 5, 8, 9, 9, 6, 9, 6, 9,
- 3, 6, 2, 4, 5, 1, 4, 7, 4, 4,
- 4, 1, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 5,
- 3, 3, 3, 2, 1, 1, 1, 1, 3, 3,
- 0, 4, 0, 6, 2, 4, 2, 3, 2, 2,
- 1, 4, 4, 2, 5, 3, 2, 2, 2, 5,
- 3, 5, 3, 6, 4, 1, 4, 2, 5, 0,
- 1, 1, 2, 1, 2, 0, 2, 2, 2, 3,
- 3, 3, 3, 2, 2, 1, 1, 2, 2, 1,
- 2, 2, 3, 1, 1, 2, 2, 1, 1, 2,
- 2, 1, 2, 2, 3, 1, 2, 1, 1, 1,
- 1, 4, 4, 1, 1, 1, 1, 1, 3, 1,
- 3, 0, 4, 0, 7, 4, 0, 7, 4, 0,
- 7, 4, 0, 6, 1, 3, 1, 4, 8, 1,
- 3, 1, 2, 3, 4, 1, 1, 3, 4, 6,
- 3, 5, 0, 7, 4, 0, 6, 3, 2, 4,
- 1, 0, 1, 0, 1, 1, 2, 5, 2, 2,
- 2, 2, 2, 2, 2, 3, 3, 2, 0, 3,
- 0, 3, 2, 1, 1, 0, 1, 2, 1, 3,
- 1, 1, 2, 2, 2, 3, 1, 1, 1, 2,
- 2, 1, 0, 1, 4, 3, 1, 2, 2, 3,
- 5, 5, 3, 3, 3, 3, 3, 5, 5, 3,
- 3, 3, 3, 1, 2, 2, 3, 3, 0, 1,
- 3, 4, 6, 4, 3, 2, 4, 6, 4, 3,
- 2, 1, 3, 1, 3, 2, 2, 0, 1, 2,
- 1, 2, 0, 2, 0, 2, 5, 5, 3, 5,
- 4, 3, 3, 5, 1, 1, 5, 3, 3, 1,
- 5, 5, 3, 5, 4, 3, 3, 1, 1, 3,
- 3, 5, 5, 3, 5, 3, 3, 3, 4, 3,
- 1, 1, 2, 2, 2, 3, 3, 7, 7, 5,
- 7, 3, 7, 7, 5, 7, 3, 1, 2, 2,
- 1, 2, 3, 3, 2, 1, 3, 3, 2, 5,
- 3, 4, 3, 4, 2, 3, 2, 3, 4, 3,
- 4, 5, 5, 1, 1, 2, 2, 2, 0, 0,
- 1, 1, 2, 3, 1, 2, 2, 5, 5, 0,
- 0, 5, 1, 2, 1, 1, 1, 2, 0, 4,
- 1, 0, 0, 5, 0, 0, 7, 0, 0, 0,
- 9, 0, 0, 0, 9, 0, 6, 0, 5, 0,
- 7, 0, 4, 2, 2, 2, 3, 6, 8, 10,
- 12, 4, 3, 2, 2, 1, 2, 3, 6, 4,
- 6, 4, 3, 0, 7, 2, 0, 5, 3, 1,
- 2, 3, 3, 2, 2, 1, 0, 4, 2, 3,
- 3, 0, 0, 4, 0, 0, 4, 0, 4, 0,
- 1, 0, 0, 8, 3, 4, 4, 3, 4, 6,
- 6, 0, 1, 0, 1, 1, 0, 1, 1, 3,
- 4, 1, 3, 0, 1, 3, 2, 1, 1, 2,
- 2, 1, 3, 3, 5, 3, 5, 3, 3, 1,
- 1, 2, 1, 0, 1, 0, 2, 4, 1, 1,
- 1, 2, 2, 2, 1, 1, 1, 3, 1, 3,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 3, 2, 2, 2, 3, 2, 3,
- 2, 2, 3, 2
-};
-
-static const short yydefact[] = { 3,
- 0, 0, 0, 461, 280, 481, 269, 279, 268, 0,
- 8, 9, 0, 336, 0, 0, 0, 0, 423, 423,
- 423, 0, 0, 76, 19, 60, 0, 0, 5, 6,
- 0, 13, 12, 11, 10, 246, 284, 121, 0, 0,
- 260, 0, 290, 278, 0, 349, 351, 355, 354, 331,
- 0, 423, 478, 281, 462, 4, 58, 59, 423, 480,
- 240, 624, 105, 106, 326, 107, 329, 240, 29, 0,
- 694, 280, 421, 692, 691, 423, 689, 670, 675, 676,
- 0, 682, 681, 667, 668, 666, 685, 674, 671, 672,
- 673, 677, 678, 664, 665, 661, 662, 663, 679, 680,
- 686, 687, 0, 669, 683, 284, 418, 272, 0, 281,
- 337, 0, 20, 643, 0, 0, 0, 0, 0, 0,
- 240, 464, 463, 465, 0, 3, 0, 0, 280, 0,
- 0, 349, 351, 646, 0, 90, 85, 246, 0, 0,
- 482, 479, 119, 120, 129, 440, 0, 423, 423, 435,
- 0, 57, 0, 0, 288, 256, 257, 423, 436, 280,
- 271, 270, 56, 0, 261, 0, 0, 265, 285, 286,
- 262, 264, 287, 0, 51, 106, 339, 340, 341, 342,
- 345, 353, 107, 109, 108, 110, 343, 348, 344, 356,
- 356, 372, 0, 68, 423, 0, 425, 0, 0, 71,
- 0, 423, 624, 646, 205, 421, 207, 244, 240, 240,
- 0, 0, 146, 242, 221, 241, 0, 240, 134, 133,
- 240, 135, 136, 0, 240, 137, 0, 123, 240, 176,
- 182, 126, 145, 0, 240, 208, 0, 240, 418, 272,
- 125, 418, 0, 206, 628, 629, 644, 644, 0, 625,
- 632, 328, 0, 323, 0, 138, 139, 0, 0, 28,
- 688, 684, 690, 423, 0, 423, 423, 486, 624, 425,
- 693, 419, 274, 276, 422, 273, 0, 0, 424, 477,
- 458, 457, 456, 0, 0, 16, 0, 7, 7, 45,
- 44, 646, 0, 31, 35, 39, 33, 37, 40, 292,
- 84, 91, 88, 0, 240, 246, 0, 0, 0, 509,
- 61, 515, 63, 356, 130, 116, 258, 259, 0, 0,
- 423, 423, 448, 0, 0, 449, 66, 55, 69, 0,
- 54, 423, 0, 425, 0, 53, 263, 52, 67, 70,
- 267, 266, 646, 291, 346, 347, 357, 350, 352, 394,
- 240, 0, 399, 399, 0, 0, 377, 646, 454, 0,
- 268, 0, 142, 260, 0, 460, 0, 240, 650, 651,
- 0, 649, 0, 0, 655, 657, 647, 0, 0, 303,
- 467, 472, 466, 646, 0, 74, 240, 0, 0, 153,
- 145, 0, 0, 155, 240, 240, 240, 227, 0, 243,
- 0, 228, 152, 149, 148, 0, 0, 0, 0, 150,
- 240, 118, 151, 240, 240, 0, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 215, 219, 220, 248, 249, 247, 240,
- 240, 240, 236, 0, 240, 173, 245, 111, 112, 113,
- 0, 217, 0, 115, 204, 416, 224, 240, 417, 112,
- 113, 229, 418, 418, 423, 627, 418, 631, 630, 0,
- 414, 334, 412, 325, 0, 282, 0, 283, 30, 495,
- 420, 489, 485, 0, 0, 0, 0, 497, 0, 423,
- 624, 425, 277, 275, 0, 0, 22, 0, 27, 117,
- 0, 15, 18, 17, 292, 50, 46, 49, 47, 48,
- 43, 0, 0, 0, 0, 303, 106, 96, 240, 0,
- 92, 0, 121, 0, 0, 316, 0, 312, 86, 0,
- 0, 62, 65, 516, 517, 510, 127, 439, 438, 0,
- 0, 423, 423, 0, 423, 0, 425, 433, 303, 289,
- 429, 0, 0, 0, 432, 0, 423, 423, 292, 369,
- 368, 367, 122, 358, 359, 362, 361, 0, 0, 396,
- 395, 461, 423, 240, 240, 624, 646, 0, 400, 423,
- 624, 646, 0, 0, 330, 379, 378, 83, 423, 423,
- 423, 459, 426, 652, 653, 654, 0, 656, 659, 0,
- 0, 0, 302, 423, 0, 423, 0, 75, 423, 0,
- 0, 0, 0, 280, 0, 147, 226, 240, 210, 209,
- 0, 240, 124, 202, 201, 616, 615, 0, 199, 198,
- 196, 197, 195, 194, 193, 190, 191, 192, 188, 189,
- 183, 184, 185, 186, 187, 203, 0, 0, 238, 240,
- 171, 240, 272, 157, 240, 0, 114, 233, 240, 218,
- 0, 231, 240, 0, 423, 423, 624, 640, 641, 638,
- 639, 646, 626, 634, 645, 636, 633, 240, 335, 0,
- 334, 144, 143, 488, 484, 423, 423, 483, 487, 423,
- 496, 491, 0, 493, 0, 338, 0, 21, 345, 343,
- 348, 14, 303, 32, 36, 34, 38, 0, 0, 94,
- 0, 98, 240, 100, 240, 0, 102, 240, 205, 280,
- 240, 313, 0, 317, 0, 87, 64, 0, 0, 511,
- 512, 0, 0, 0, 0, 0, 447, 443, 0, 0,
- 0, 446, 0, 296, 423, 423, 423, 431, 0, 0,
- 303, 129, 0, 365, 371, 370, 364, 363, 392, 393,
- 240, 383, 384, 646, 303, 406, 0, 292, 0, 380,
- 390, 391, 646, 0, 386, 292, 385, 387, 0, 397,
- 398, 455, 452, 453, 658, 0, 648, 0, 0, 300,
- 470, 0, 0, 0, 475, 0, 0, 0, 646, 222,
- 154, 156, 179, 181, 180, 0, 212, 0, 177, 240,
- 213, 216, 0, 0, 0, 418, 418, 161, 240, 0,
- 174, 240, 0, 235, 240, 223, 0, 642, 489, 485,
- 423, 72, 0, 0, 415, 413, 327, 0, 500, 498,
- 494, 423, 492, 23, 26, 0, 0, 41, 95, 93,
- 0, 0, 104, 240, 0, 0, 0, 0, 314, 310,
- 0, 0, 205, 520, 532, 535, 0, 0, 240, 0,
- 0, 0, 240, 0, 586, 0, 0, 0, 0, 240,
- 0, 566, 612, 0, 527, 0, 0, 0, 505, 525,
- 531, 504, 526, 0, 240, 0, 592, 0, 538, 542,
- 513, 0, 437, 434, 451, 450, 423, 423, 423, 445,
- 294, 430, 427, 428, 503, 502, 299, 366, 360, 303,
- 78, 405, 423, 303, 461, 240, 240, 646, 401, 81,
- 423, 0, 660, 293, 0, 0, 423, 423, 423, 423,
- 423, 423, 73, 225, 332, 200, 131, 0, 237, 0,
- 0, 0, 0, 163, 175, 232, 0, 230, 635, 637,
- 324, 501, 499, 490, 25, 42, 97, 99, 0, 101,
- 0, 321, 240, 315, 0, 318, 0, 514, 508, 519,
- 584, 0, 0, 509, 0, 240, 0, 552, 554, 555,
- 556, 0, 240, 0, 650, 651, 0, 0, 587, 0,
- 593, 567, 0, 585, 613, 0, 528, 254, 646, 0,
- 255, 0, 0, 646, 0, 518, 507, 506, 529, 576,
- 0, 0, 565, 564, 0, 581, 0, 592, 0, 589,
- 0, 0, 0, 0, 444, 441, 442, 0, 297, 404,
- 381, 382, 646, 402, 240, 303, 411, 292, 388, 389,
- 646, 307, 0, 305, 301, 471, 468, 469, 476, 473,
- 474, 0, 0, 131, 214, 239, 172, 0, 272, 158,
- 167, 169, 159, 234, 103, 319, 0, 0, 311, 140,
- 240, 521, 533, 240, 523, 0, 0, 509, 605, 0,
- 608, 0, 548, 240, 240, 557, 0, 563, 573, 0,
- 240, 509, 0, 240, 509, 568, 0, 251, 292, 250,
- 253, 252, 292, 509, 579, 0, 583, 582, 577, 591,
- 590, 0, 0, 128, 295, 0, 77, 0, 303, 410,
- 303, 80, 0, 0, 0, 178, 132, 418, 418, 162,
- 240, 0, 425, 425, 0, 322, 0, 509, 509, 524,
- 536, 609, 607, 0, 606, 546, 240, 0, 553, 562,
- 572, 0, 588, 570, 0, 594, 0, 530, 574, 602,
- 539, 543, 298, 403, 409, 407, 0, 0, 306, 304,
- 0, 0, 0, 164, 0, 0, 320, 141, 522, 534,
- 0, 0, 0, 509, 549, 550, 0, 0, 617, 0,
- 595, 578, 0, 0, 0, 0, 308, 168, 170, 160,
- 165, 166, 0, 611, 610, 547, 240, 571, 569, 0,
- 0, 618, 619, 558, 0, 0, 0, 0, 408, 0,
- 537, 551, 240, 617, 0, 0, 598, 575, 596, 0,
- 540, 544, 0, 0, 0, 559, 620, 0, 0, 600,
- 509, 509, 0, 621, 0, 0, 599, 597, 601, 0,
- 541, 545, 309, 622, 0, 560, 603, 0, 0, 0,
- 623, 561, 604, 0, 0, 0
-};
-
-static const short yydefgoto[] = { 1274,
- 1, 2, 127, 503, 883, 29, 30, 31, 278, 496,
- 497, 32, 70, 33, 512, 514, 513, 515, 511, 34,
- 35, 36, 352, 137, 138, 139, 302, 520, 521, 562,
- 188, 452, 37, 38, 145, 752, 227, 228, 315, 732,
- 316, 1065, 229, 884, 1082, 256, 230, 397, 231, 257,
- 233, 408, 947, 444, 234, 235, 236, 140, 237, 238,
- 885, 343, 247, 171, 248, 239, 273, 392, 274, 154,
- 42, 380, 155, 1038, 344, 1126, 43, 936, 603, 1053,
- 1054, 861, 724, 725, 44, 475, 253, 1063, 680, 45,
- 46, 47, 48, 190, 191, 49, 50, 348, 564, 565,
- 566, 567, 568, 193, 355, 356, 357, 578, 579, 929,
- 472, 473, 241, 668, 242, 114, 367, 368, 156, 325,
- 157, 243, 53, 110, 272, 486, 159, 888, 889, 1084,
- 729, 730, 731, 311, 890, 891, 982, 1148, 1086, 892,
- 893, 1114, 983, 1149, 984, 1191, 1032, 1203, 1251, 1033,
- 1204, 1252, 1194, 1157, 1217, 1095, 1201, 1170, 894, 895,
- 896, 1102, 897, 1028, 898, 1105, 1225, 1249, 1248, 1260,
- 1202, 1270, 899, 900, 1006, 628, 1221, 1222, 1223, 1265,
- 487, 250, 251, 670, 201, 463, 676, 200, 376, 599,
- 377, 600, 244
-};
-
-static const short yypact[] = { 85,
- 1781, 1492, 152,-32768, 749,-32768,-32768,-32768,-32768, 321,
--32768,-32768, 16,-32768, 116, 2019, 74, 82,-32768,-32768,
--32768, 1140, 151,-32768,-32768,-32768, 84, 177,-32768, 285,
- 559,-32768,-32768,-32768,-32768, 62, 108, 182, 723, 839,
- 997, 92,-32768,-32768, 1078,-32768,-32768,-32768,-32768, 301,
- 1615,-32768,-32768, 39,-32768,-32768,-32768,-32768,-32768,-32768,
- 5696, 5379,-32768,-32768, 202,-32768, 310, 5696,-32768, 189,
--32768, 312,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
- 325,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768, 316,-32768,-32768, 389, 1204, 1494, 1248,-32768,
--32768, 427,-32768, 510, 1140, 500, 500, 51, 523, 49,
- 5696,-32768,-32768,-32768, 427, 450, 4946, 437, 51, 2378,
- 1433, 60, 194, 651, 574,-32768, 536, 160, 411, 411,
--32768,-32768,-32768,-32768, 503, 51, 2063,-32768,-32768,-32768,
- 3444,-32768, 1265, 212,-32768, 675, 677,-32768,-32768, 2129,
--32768,-32768,-32768, 508, 997, 238, 1746,-32768,-32768,-32768,
- 1665,-32768,-32768, 2378,-32768, 312,-32768,-32768,-32768,-32768,
--32768,-32768, 151,-32768,-32768,-32768,-32768,-32768, 473, 566,
- 566,-32768, 4861,-32768,-32768, 3380, 506, 103, 540, 494,
- 2391,-32768, 5379, 240,-32768, 543,-32768,-32768, 5902, 5979,
- 562, 600,-32768,-32768,-32768, 5413, 123, 5777,-32768,-32768,
- 5777,-32768,-32768, 4331, 5777,-32768, 195,-32768, 5777,-32768,
--32768, 6505, 1349, 605, 5369, 683, 266, 5777, 1204, 546,
--32768, 6305, 272,-32768,-32768,-32768,-32768, 3429, 606, 303,
- 660,-32768, 123, 611, 627, 653, 6439, 637, 742,-32768,
- 510,-32768,-32768,-32768, 887,-32768,-32768,-32768, 6261, 641,
--32768, 695, 1494,-32768,-32768, 1494, 48, 3537,-32768,-32768,
- 677, 677,-32768, 354, 64,-32768, 1886,-32768,-32768,-32768,
--32768, 341, 70,-32768,-32768,-32768,-32768,-32768,-32768, 591,
--32768, 179,-32768, 4412, 5777,-32768, 411, 411, 704, 681,
--32768,-32768,-32768, 566,-32768,-32768, 675, 677, 1539, 1539,
--32768,-32768,-32768, 3552, 318,-32768,-32768,-32768, 494, 2378,
--32768,-32768, 3488, 657, 3660,-32768, 1665,-32768,-32768, 494,
--32768,-32768, 341,-32768,-32768,-32768, 338,-32768,-32768,-32768,
- 5777, 548, 1894, 6023, 42, 1648,-32768, 651, 510, 692,
- 543, 175, 6483, 967, 708,-32768, 690, 5777,-32768, 51,
- 644,-32768, 108, 805,-32768,-32768, 772, 2568, 748, 809,
- 51, 151,-32768, 240, 735,-32768, 5777, 543, 4331,-32768,
- 1530, 190, 4331,-32768, 5777, 5858, 5777,-32768, 54,-32768,
- 409,-32768,-32768,-32768,-32768, 745, 747, 704, 759,-32768,
- 5696,-32768,-32768, 5777, 5777, 4493, 5777, 5777, 5777, 5777,
- 5777, 5777, 5777, 5777, 5777, 5777, 5777, 5777, 5777, 5777,
- 5777, 5777, 5777,-32768,-32768,-32768,-32768,-32768,-32768, 5777,
- 5777, 5777, 465, 1367, 4817,-32768,-32768,-32768, 51, 151,
- 123, 541, 272,-32768,-32768,-32768,-32768, 5777,-32768,-32768,
--32768, 646, 702, 702,-32768,-32768, 6085,-32768,-32768, 4412,
- 830, 843,-32768,-32768, 123,-32768, 4736,-32768,-32768, 510,
- 695, 1298, 1298, 50, 355, 792, 799,-32768, 810,-32768,
- 5379, 816,-32768, 1494, 874, 446,-32768, 1102,-32768,-32768,
- 824,-32768,-32768,-32768, 591,-32768,-32768,-32768,-32768,-32768,
--32768, 834, 840, 842, 849, 809, 51,-32768, 5777, 448,
--32768, 679, 806, 123, 684,-32768, 3920, 6483,-32768, 178,
- 411,-32768,-32768,-32768,-32768, 880,-32768, 675, 675, 1539,
- 1539,-32768,-32768, 362,-32768, 3596, 855,-32768, 809,-32768,
- 510, 868, 216, 872,-32768, 875,-32768,-32768, 591,-32768,
--32768,-32768,-32768, 926,-32768,-32768, 976, 383, 6366,-32768,
--32768, 931, 602, 5777, 5777, 6192, 341, 258,-32768, 619,
- 6192, 731, -1, 932,-32768,-32768,-32768, 669,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768, 103,-32768,-32768, 314,
- 427, 906, 939,-32768, 3704,-32768, 3812,-32768,-32768, 317,
- 890, 891, 892, 33, 893,-32768,-32768, 5777,-32768,-32768,
- 902, 5453,-32768, 6483, 6483,-32768,-32768, 952, 6541, 6556,
- 3766, 3333, 3872, 1802, 1790, 1891, 1891, 1891, 1118, 1118,
- 800, 800,-32768,-32768,-32768,-32768, 353, 907, 940, 5777,
--32768, 5696, 1089, 962, 5777, 913,-32768,-32768, 5777, 698,
- 356,-32768, 5777, 2362,-32768,-32768, 6130,-32768, 677,-32768,
--32768, 240,-32768, 971,-32768, 972,-32768, 5777, 123, 921,
- 843,-32768, 6483, 695, 695,-32768,-32768,-32768,-32768,-32768,
--32768, 510, 927,-32768, 924,-32768, 3537,-32768, 947, 468,
- 980,-32768, 809,-32768,-32768,-32768,-32768, 70, 372,-32768,
- 179,-32768, 5777,-32768, 5777, 709,-32768, 5777, 989, 814,
- 5777,-32768, 993,-32768, 89,-32768,-32768, 123, 3164, 880,
--32768, 301, 492, 592, 1539, 1539,-32768, 510, 950, 375,
- 956,-32768, 942, 1003,-32768,-32768,-32768,-32768, 1539, 1539,
- 809, 503, 338,-32768,-32768,-32768,-32768, 976,-32768,-32768,
- 5777,-32768,-32768, 240, 6416, 6483, 957, 807, 1122,-32768,
--32768,-32768, 240, 960,-32768, 964,-32768,-32768, 4930,-32768,
--32768, 510, 510, 510,-32768, 2568,-32768, 65, 982,-32768,
- 510, 965, 418, 968, 510, 970, 431, 973, 240,-32768,
--32768,-32768,-32768,-32768,-32768, 478,-32768, 4247,-32768, 5777,
--32768,-32768, 427, 99, 482, 1204, 6305,-32768, 5777, 4412,
--32768, 5777, 487,-32768, 5777,-32768, 489, 677, 2208, 2208,
- 50,-32768, 4412, 4412, 6483,-32768,-32768, 974, 1298, 1298,
- 510,-32768,-32768,-32768,-32768, 252, 70,-32768,-32768,-32768,
- 555, 560,-32768, 5777, 563, 6344, 4412, 4004,-32768,-32768,
- 283, 697, 1011,-32768,-32768,-32768, 996, 1000, 5777, 1034,
- 985, 986, 5534, 281,-32768, 300, 1043, 103, 1044, 5615,
- 284,-32768, 1087, 994,-32768, 2397, 6236, 2516,-32768,-32768,
- 1085,-32768,-32768, 2322, 5051, 2624,-32768, 2732,-32768,-32768,
--32768, 4861,-32768,-32768, 675, 675,-32768,-32768,-32768,-32768,
--32768, 510, 510, 510, 675, 675, 1054,-32768,-32768, 6416,
--32768,-32768, 787, 809, 1056, 5777, 5777, 341,-32768,-32768,
- 822, 2195,-32768,-32768, 1111, 4412,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768, 1064, 6525, 503, 67,-32768, 3324,
- 1015, 1018, 577,-32768,-32768,-32768, 580,-32768,-32768,-32768,
--32768, 695, 695, 510,-32768,-32768,-32768,-32768, 581,-32768,
- 4412,-32768, 5777,-32768, 1075,-32768, 123,-32768,-32768,-32768,
--32768, 721, 721, 704, 4085, 5777, 856,-32768,-32768,-32768,
--32768, 1029, 5777, 1030, 1031, 24, 1033, 727,-32768, 744,
--32768,-32768, 1035,-32768,-32768, 1058,-32768,-32768, 782, 286,
--32768, 1042, 324, 388, 1045,-32768,-32768,-32768,-32768,-32768,
- 103, 123,-32768,-32768, 827,-32768, 2840,-32768, 831,-32768,
- 2948, 4574, 4574, 124, 510, 510, 510, 4412,-32768,-32768,
--32768,-32768, 240, 1095, 5777, 6416, 6483, 591,-32768,-32768,
- 240, 1066, 588,-32768,-32768, 510, 510, 510, 510, 510,
- 510, 4166, 1047, 503,-32768,-32768,-32768, 2568, 1407, 1101,
- 1071, 1074,-32768,-32768,-32768,-32768, 6461, 4412,-32768,-32768,
- 5777,-32768,-32768, 5263,-32768, 1143, 1059, 1055,-32768, 1060,
--32768, 1063,-32768, 5777, 5157,-32768, 1065,-32768,-32768, 1070,
- 5777,-32768, 1079, 5777,-32768,-32768, 427,-32768, 591,-32768,
--32768,-32768, 591, 704, 772, 1126,-32768,-32768,-32768,-32768,
--32768, 1090, 1093,-32768,-32768, 4412,-32768, 4412, 6416,-32768,
- 809,-32768, 502, 1111, 1103,-32768,-32768, 1204, 6305,-32768,
- 5777, 4412,-32768,-32768, 4412,-32768, 1104, 704, 704,-32768,
--32768,-32768,-32768, 3272,-32768,-32768, 5157, 1139,-32768,-32768,
--32768, 590,-32768,-32768, 598,-32768, 47,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768, 1153, 1158, 1106,-32768,-32768,
- 1110, 1112, 636,-32768, 1113, 1115,-32768,-32768,-32768,-32768,
- 721, 846, 3056, 704,-32768,-32768, 1114, 1120, 1216, 1123,
--32768, 1137, 4655, 4655, 4412, 1221,-32768,-32768,-32768,-32768,
--32768,-32768, 1128,-32768,-32768,-32768, 5157,-32768,-32768, 1148,
- 360, 1183,-32768,-32768, 527, 1154, 1132, 1138,-32768, 1198,
--32768,-32768, 5777, 1216, 1145, 1216,-32768,-32768,-32768, 2568,
--32768,-32768, 1249, 1156, 380,-32768,-32768, 704, 704, 123,
- 704, 704, 1159,-32768, 1247, 1157,-32768,-32768,-32768, 1160,
--32768,-32768,-32768,-32768, 652,-32768,-32768, 1257, 1164, 704,
--32768,-32768,-32768, 1277, 1279,-32768
-};
-
-static const short yypgoto[] = {-32768,
- 1146,-32768,-32768, 991, 53, 1284,-32768,-32768,-32768,-32768,
- 584,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -662, 1166,
- 1169,-32768,-32768,-32768,-32768, 1161,-32768,-32768, 587, -10,
- 802, -220, 535, -31,-32768,-32768, 1180, 894, -900,-32768,
- 550, 243,-32768, 35, -955, -163, 752,-32768, -145, 908,
- -169,-32768,-32768,-32768,-32768, -177, -99, -93,-32768,-32768,
- 323, 56, 28, 1144, 61, -15, 1037, 3, -9, 424,
- -29, -293,-32768,-32768, 981,-32768,-32768,-32768, -468,-32768,
- 180,-32768, -160, 509, -26,-32768,-32768,-32768, 643, -261,
- 1313, 1314,-32768,-32768,-32768,-32768,-32768, -140,-32768, 593,
- 779, -496,-32768, 618, 451, 575, -340, 1001,-32768,-32768,
- 881, 678, -66, -101, -6, 1574, -267,-32768, -78, 1036,
- 1272, 171,-32768, 19, -151,-32768, -133, -854, -864, -283,
--32768,-32768, 631, -118, -131,-32768,-32768,-32768, -1013, -827,
- 289,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768, 339,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768, -995, 134,-32768, 141,-32768,
- -37,-32768, -247, -336, 34, 1131,-32768, 27, -585, 604,
- 363,-32768, 1361
-};
-
-
-#define YYLAST 6629
-
-
-static const short yytable[] = { 67,
- 107, 258, 489, 41, 41, 271, 516, 312, 312, 109,
- 166, 785, 277, 189, 173, 587, 498, 326, 108, 54,
- 54, 313, 462, 1017, 249, 285, 536, 1083, 39, 39,
- 499, 172, 362, 41, 187, 549, 1122, 1123, 400, 391,
- 391, 1027, 165, 1031, 308, 848, 1064, 708, 391, 769,
- 349, 391, 115, 28, 28, 391, 447, 447, 130, 391,
- 1018, 40, 40, 240, 41, 391, 556, 1024, 317, 60,
- 240, 758, 404, 447, 447, 405, 447, 584, 60, 410,
- 744, 173, 202, 413, -1, 135, 122, 123, 61, 446,
- 214, 131, 195, 506, 153, 164, 60, 61, 68, 399,
- 1168, 1199, 255, 777, 778, 369, 370, 6, 111, 294,
- 686, 276, 141, 481, 295, 61, 136, 485, 69, 507,
- 687, 203, 508, 240, 509, 63, 64, 671, -106, 41,
- 675, 196, 197, 165, 1189, 1190, 804, 456, 173, 858,
- 459, 530, 174, 529, 173, 54, 113, 585, 371, 477,
- 1200, 495, 283, 142, 39, 172, 112, 409, 365, 584,
- 300, 342, 1017, 1064, 296, 385, 1017, 501, 934, 553,
- 1066, 52, 52, 537, 510, 312, 312, 534, 124, 329,
- 1216, 63, 517, 6, 966, 292, 293, 40, 532, 533,
- 326, 335, 52, 340, 859, 41, 175, 23, 364, 1018,
- 372, 52, 845, 1018, 949, 41, 403, 1227, 1228, 158,
- 158, 703, 531, 173, 136, 121, 375, 66, 401, 674,
- 353, 400, 518, 610, 695, 477, 240, 391, 477, 1124,
- 386, 143, 660, 457, 847, 1213, 144, 1261, 1262, 259,
- 538, 539, 471, 297, 276, 411, 173, 279, 298, 173,
- 165, 616, 379, 354, 63, 176, 57, 58, 407, 125,
- 412, 519, 330, 493, 306, 751, 477, 1159, 448, 449,
- 523, 41, 458, 183, 448, 460, 621, 647, 590, 743,
- 41, 726, 917, 63, 64, 52, 52, 52, 174, 41,
- 998, 522, 1000, 260, 661, 554, 922, 52, 299, 1193,
- 158, 158, 995, 996, 6, 54, 16, 252, 769, 677,
- 173, 598, 16, 466, 39, 563, 331, 158, 505, 746,
- 525, 158, 611, 63, 64, 198, 612, 342, 1017, 1195,
- 684, 685, 199, 977, 126, 364, 330, 173, 1004, 28,
- 63, 176, 338, 560, 158, 371, 183, 40, 121, 965,
- 192, 993, 379, 467, 172, 709, 165, 468, 41, 254,
- 450, 545, 770, 52, 786, 1018, 461, 477, 374, 559,
- 65, 52, 451, 561, 174, 66, 61, 654, 451, 262,
- 108, 379, 740, 353, 588, 63, 176, 978, 755, 1232,
- 1110, 240, 379, 141, 183, 240, 469, 372, 490, 312,
- 546, 547, 593, 477, 411, 545, 477, 453, 577, 582,
- 608, 309, 727, 240, 1234, 66, 354, 787, 756, 500,
- 800, 548, 477, 407, 263, 477, 198, 407, 1112, 613,
- 615, 195, 183, 199, 1255, 498, 208, 491, 492, 484,
- 657, 793, 326, 797, 546, 547, 653, 326, 710, 499,
- 627, 1040, 617, 693, 806, 1044, 811, 52, 688, 826,
- 310, 733, 734, 1235, 471, 737, 189, 173, 477, 41,
- 196, 197, 524, 198, 924, 849, 648, 183, 908, 656,
- 199, 477, 924, 1256, 493, 391, 814, 700, 815, 158,
- 158, 618, -257, 41, 158, 823, 697, -89, 711, 827,
- 158, 788, 4, 118, 1177, 52, 649, 279, 741, 821,
- 1178, 698, 481, 716, 650, 485, 723, 279, -24, 11,
- 12, 938, 345, 158, 158, -292, 52, 346, 477, 369,
- 370, 6, 477, -24, 941, 332, 563, 477, 767, 477,
- 16, 290, 291, 774, -292, 19, -292, 1237, 364, 851,
- 106, 852, 169, 170, 855, 286, 119, 379, 10, 128,
- 20, 4, 129, 6, 7, 8, 9, 794, 142, 798,
- 21, 10, 371, 119, 333, 334, 301, 1130, 41, 303,
- 14, 944, 22, 41, 658, 950, 13, 17, 304, 457,
- 956, 587, 958, 14, 23, 903, 106, 570, -292, 16,
- 17, 314, 571, 768, 19, 477, 27, 364, 776, 364,
- 477, 379, 336, 477, 366, 375, 11, 12, 305, 20,
- 347, 23, 378, 659, 372, 387, 173, 477, 458, 21,
- 477, 477, 1238, 52, 52, 332, 816, 52, 1134, 1239,
- 477, 22, 443, 106, 395, 817, 594, 595, 477, 119,
- 119, 119, 391, 23, 240, 953, 905, 906, 967, 954,
- 1175, 957, 1176, 968, 119, 27, 970, 563, 471, 41,
- 915, 916, 959, 960, 333, 334, 955, 684, 685, 523,
- 1073, 119, 396, 1074, 1075, 119, 477, 962, 963, 662,
- 969, 1135, 447, 1197, 195, 904, 972, 976, 832, 41,
- 522, 1198, 1268, 477, 4, 118, 762, 763, 119, 465,
- 158, 158, 470, 948, 951, 952, 474, 860, 332, 598,
- 195, 563, 712, 771, 772, 4, 146, 717, 663, 525,
- 476, 364, 373, 196, 197, 119, 198, 106, 490, 1210,
- 478, 824, 16, 199, 479, 264, 158, 19, 664, 488,
- 106, 158, 853, 310, 1131, 1269, 886, 333, 334, 196,
- 197, 713, 665, 16, 1080, 555, 718, 374, 19, 147,
- 1100, 119, 666, 780, 781, 1055, 106, 491, 492, 268,
- 825, 41, 106, 148, 667, 270, 535, 1103, 108, 887,
- 921, 854, 59, 149, 60, 589, 23, 723, 592, 930,
- 150, 979, 980, 1081, 1154, 151, 353, 596, 27, 1101,
- 1076, 591, 106, 61, 563, 549, 198, 23, 1163, 276,
- 379, 1166, 597, 199, 928, 943, 1104, 152, 379, 27,
- 601, 62, 11, 12, 52, 775, 373, 831, 609, 354,
- 602, 4, 160, 6, 161, 8, 162, 975, 619, 714,
- 620, 10, 1085, 119, 119, 143, -79, 1013, 119, 60,
- 144, -79, 622, 994, 119, 997, 13, 198, -106, 119,
- 431, 432, 433, 14, 199, 1185, 1186, 1125, 61, 16,
- 17, 524, 678, 1070, 19, 147, 1108, 119, 715, 165,
- 364, 1041, 1042, 679, 375, 689, 375, 364, 364, 148,
- 364, 976, 690, 987, 41, 158, 158, 992, 696, 149,
- 1093, 1094, 106, 728, 1003, 886, 150, 1146, 691, 158,
- 158, 151, 886, 886, 694, 886, 1049, 1050, 702, 353,
- 264, 979, 1117, 23, 41, 979, 1120, 1162, 704, 158,
- 1165, 1009, 1012, 163, 705, 27, 706, 266, 887, 52,
- 979, 1214, 1069, 707, 1048, 887, 887, 267, 887, 353,
- 390, 394, 354, 742, 268, 1173, 1079, 1174, 232, 269,
- 270, 745, 168, 169, 170, 747, 753, 1183, 106, 10,
- 754, 1184, 1085, 748, 1187, 761, 779, 364, 789, 11,
- 12, 790, 354, 801, 802, 803, 805, 119, 119, 52,
- 52, 14, 168, 169, 170, 807, 810, 1167, 17, 10,
- 457, 1116, 886, -82, 820, 812, 1085, 1085, -82, 1090,
- 1092, 822, 813, 833, 834, 106, 837, 1097, 232, 364,
- 842, 14, 843, 364, 846, 1109, 1181, 1182, 17, 375,
- 1113, 183, 173, -105, 1229, 887, 374, 857, 374, 458,
- 910, 975, 1138, 907, 886, 911, 158, 158, 886, 909,
- 923, 1139, 1085, 931, 935, 981, 627, 627, 937, 1127,
- 108, 939, 52, 940, 119, 119, 942, 1132, 985, 961,
- 63, 176, 986, 177, 178, 179, 364, 887, 988, 989,
- 990, 887, 999, 1001, 1005, 169, 170, 364, 1007, 1019,
- 379, 10, 52, 363, 63, 176, 1039, 177, 178, 179,
- 1045, 886, 180, 1052, 1062, 1147, 1257, 1258, 1071, 1085,
- 1085, 1072, 886, 14, 925, 146, 181, 182, 1158, 1078,
- 17, 373, 818, 1096, 1098, -105, 180, 1099, 1273, 1106,
- 1107, 276, 4, 118, 887, 455, 1111, 1128, 1133, 979,
- 699, 182, 1136, 1142, 1143, 887, 364, 1144, 1151, 364,
- 1153, 379, 16, 1152, 1155, 379, 1156, 19, 147, 1160,
- 926, 819, 183, 1250, 1161, 1169, 927, 184, 185, 186,
- 16, 886, 148, 1164, 886, 19, 429, 430, 431, 432,
- 433, 374, 149, 1196, 1171, 364, 183, 1172, 119, 150,
- 20, 184, 185, 186, 151, 1205, 1180, 1188, 1206, 1207,
- 21, 528, 363, 1208, 887, 1209, 23, 887, 1218, 364,
- 886, 1211, 22, 1212, 1219, 1220, 1226, 1224, 27, 1230,
- 1233, 106, 1231, 1236, 23, 1241, 1240, 627, 627, 1259,
- 363, 1242, 108, 375, 886, 373, 27, 264, 1243, 1246,
- 265, 72, 6, 887, 8, 275, 1264, 1253, 569, 1254,
- 10, 1266, 1263, 1267, 266, 327, 1271, 1244, 1272, 119,
- 119, 287, 51, 51, 267, 13, 1275, 887, 1276, 504,
- 844, 268, 14, 119, 119, 56, 269, 270, -646, 17,
- -646, -646, 288, 120, 363, 289, -646, 850, 307, 701,
- 284, 918, 134, 119, 623, 279, 1137, 1091, 337, 1010,
- 550, 167, 494, 1179, -646, -646, 945, -646, 232, -646,
- 106, 624, 625, 838, 629, 630, 631, 632, 633, 634,
- 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
- 645, 264, 23, 132, 133, 919, 757, 646, 363, 902,
- 198, 106, 1034, 932, 583, 681, 836, 199, 266, 544,
- 901, 55, 55, 119, 119, 363, 1119, 1245, 267, 328,
- 72, 6, 1150, 8, 73, 268, 1247, 528, 464, 10,
- 269, 270, 55, 1115, 683, 0, 280, 281, 282, 933,
- 0, 55, 434, 0, 13, 374, 0, 0, 51, 55,
- 55, 14, 0, 0, 0, 0, 0, 0, 17, 0,
- 373, 0, 373, 169, 170, 651, 0, 0, 318, 10,
- 119, 0, 120, 435, 436, 0, 363, 437, 438, 439,
- 440, 441, 442, 0, 528, 4, 160, 6, 161, 8,
- 162, 14, 0, 0, 0, 10, 0, 0, 17, 652,
- 1140, 0, 0, 363, 0, 0, 0, 0, 0, 0,
- 13, 23, 0, 0, 358, 0, 0, 14, 0, 0,
- 0, 0, 383, 16, 17, 55, 55, 55, 19, 147,
- 0, 765, 766, 0, 106, 0, 0, 55, 0, 1141,
- 55, 55, 3, 148, 4, 5, 6, 7, 8, 9,
- 169, 170, 0, 149, 10, 0, 10, 55, 0, 0,
- 150, 55, 363, 0, 363, 151, 0, 11, 12, 13,
- 0, 0, 0, 0, 0, 363, 14, 23, 14, 809,
- 15, 0, 16, 17, 55, 17, 18, 19, 0, 27,
- 0, 4, 146, 0, 0, 0, 279, 0, 0, 0,
- 0, 0, 20, 55, 0, 373, 0, 363, 51, 363,
- 0, 55, 21, 0, 0, 0, 363, 0, 0, 0,
- 363, 0, 0, 434, 22, 0, 402, 0, 0, 16,
- 0, 0, 0, 0, 19, 835, 23, 24, 25, 0,
- 281, 282, 0, 116, 117, 120, 26, 454, 27, 148,
- 0, 0, 106, 454, 435, 436, 383, 0, 437, 149,
- 439, 0, 441, 442, 0, 194, 150, 0, 0, 0,
- 363, 151, 363, 0, 0, 363, 0, 358, 856, 0,
- 0, 0, 204, 23, 0, 0, 0, 0, -646, 0,
- -646, -646, 0, 0, 0, 27, -646, 55, 350, 261,
- 4, 129, 6, 7, 8, 9, 0, 0, 195, 0,
- 10, 0, 0, 0, -646, -646, 0, -646, 920, -646,
- 341, 169, 170, 106, 0, 13, 0, 10, 0, 55,
- 55, 0, 14, -374, 55, 0, 0, 0, 16, 17,
- 55, 0, 0, 19, 0, 55, 0, 196, 197, 14,
- 198, 0, 351, 0, 0, 0, 17, 199, 20, 0,
- 0, 0, 0, 55, 55, 528, 55, 946, 21, -646,
- 0, 319, 320, 0, 0, 0, 363, 528, 0, 0,
- 22, 0, 363, 0, 669, 669, 0, 0, 669, 0,
- 528, 528, 23, 0, 0, 0, 339, 0, 0, 0,
- 0, 0, 586, -374, 27, 0, 0, 0, 0, 373,
- 0, 363, 0, 0, 528, 528, 0, 0, 359, -646,
- 0, -646, -646, 0, 106, 384, 0, -646, 0, 0,
- -2, 3, 0, 4, 5, 6, 7, 8, 9, 195,
- 0, 0, 0, 10, 0, -646, -646, 0, -646, 0,
- -646, 0, 0, 0, 0, 0, 11, 12, 13, 0,
- 0, 281, 282, 454, 0, 14, 0, 0, 0, 15,
- 0, 16, 17, 55, 55, 18, 19, 55, 196, 197,
- 0, 198, 0, 1046, 1047, 0, 0, 480, 199, 482,
- 483, 20, 0, 528, 0, 0, 0, 120, 0, 0,
- -257, 21, 120, 424, 425, 426, 427, 428, 429, 430,
- 431, 432, 433, 22, 423, 424, 425, 426, 427, 428,
- 429, 430, 431, 432, 433, 23, 24, 25, 528, 0,
- 1077, 0, 0, 0, 0, 26, 3, 27, 4, 5,
- 6, 7, 8, 9, 540, 541, 572, 146, 10, 0,
- 55, 55, 0, 0, 0, 551, 0, 0, 0, 0,
- 0, 11, 12, 13, 0, 0, 0, 0, 0, 0,
- 14, 0, 0, 0, 15, 0, 16, 17, 0, 0,
- 18, 19, 0, 0, 16, 828, 55, 573, 120, 19,
- 147, 55, 574, 0, 0, 528, 20, 0, 575, 0,
- 0, 0, 1129, 0, 148, 0, 21, 427, 428, 429,
- 430, 431, 432, 433, 149, 0, 0, 0, 22, 528,
- 0, 150, 0, 0, 0, 0, 576, 0, 0, 0,
- 23, 24, 25, 0, 0, 528, 0, 0, 23, 0,
- 26, 502, 27, 0, 0, 0, 0, 0, 0, 0,
- 27, 0, 0, 0, 0, 0, 281, 282, 363, 0,
- 0, 363, 0, 0, 0, 0, 0, 0, 0, 71,
- 281, 282, 72, 6, 55, 8, 73, 55, 0, 0,
- 0, 10, 0, 528, 0, 528, 0, 0, 672, 0,
- 0, 0, 0, 0, 0, 0, 13, 0, 363, 528,
- 358, 0, 528, 14, 0, 74, 75, 0, 0, 0,
- 17, 76, 77, 692, 0, 4, 146, 0, 0, 78,
- 79, 80, 81, 0, 0, 82, 83, 84, 85, 86,
- 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
- 97, 98, 0, 99, 100, 55, 55, 101, 102, 0,
- 281, 282, 103, 16, 0, 0, 0, 0, 19, 55,
- 55, 0, 528, 23, 0, 735, 736, 0, 738, 0,
- 0, 0, 0, 148, 0, 104, 105, 0, 0, 55,
- 749, 750, 0, 149, 0, 0, 0, 0, 0, 55,
- 150, 0, 0, 0, 0, 151, 764, 0, 0, 0,
- 0, 0, -440, 773, -440, -440, 0, 23, 1014, 0,
- -440, 0, 782, 783, 784, 0, 0, 0, 0, 27,
- 0, 0, 0, 358, 60, 0, 0, 791, -440, 795,
- 0, -440, 799, 0, 0, 0, 0, 0, 0, 55,
- 55, 0, 0, 61, 0, 350, 0, 4, 129, 6,
- 7, 8, 9, 358, 0, 0, 0, 10, 0, 0,
- 4, 118, -440, 0, -440, 279, 0, 0, 0, 0,
- 0, -440, 13, 0, 0, 0, 0, 0, 0, 14,
- -375, 0, 0, 0, -440, 16, 17, 0, 829, 830,
- 19, 0, 0, 0, 0, 0, 55, 55, 16, 351,
- 0, 264, 0, 19, 0, 20, 0, 0, 0, 839,
- 840, 0, 55, 841, 0, 21, 0, 0, 665, 0,
- 0, 0, 0, 0, 0, 0, 0, 22, 666, 0,
- 0, 0, 0, 0, 0, 268, 0, 0, 0, 23,
- 667, 270, 55, 0, 0, 0, 0, 0, 0, 586,
- -375, 27, 23, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 0, 912, 913,
- 914, 0, 1020, 0, -580, -580, -580, -580, -580, -580,
- -580, -580, 0, -580, -580, -580, -580, -580, -580, -580,
- -580, -580, -580, -580, -580, -580, -580, -580, -580, -580,
- -580, -580, -580, 0, -580, 0, -580, 0, -580, -580,
- 0, -580, -580, -580, 4, 118, 0, -580, 0, 0,
- -580, -580, 0, 0, 0, 0, 0, 0, 0, -580,
- 4, 146, -580, 0, 0, 0, 0, 0, 0, 0,
- -580, -580, -580, 4, 381, 0, -580, -580, 0, 4,
- 146, 0, 16, 0, -580, 264, -580, 19, 1021, -580,
- 1022, 0, -580, -580, -580, 964, -580, 0, 16, 0,
- 0, 0, 665, 19, 147, 0, -580, -580, -580, -580,
- 0, 16, 666, 0, 0, 0, 19, 16, 148, 268,
- 0, 0, 19, 147, 667, 270, 0, 0, 149, 0,
- 0, 20, 0, 0, 0, 150, 23, 148, 0, 0,
- 151, 21, 0, 0, 0, 0, 0, 149, 27, 0,
- 0, 0, 23, 22, 150, 0, 0, 0, 0, 151,
- 1035, 1036, 1037, 0, 27, 382, 0, 0, 0, 0,
- 0, 23, 0, 0, 0, 0, 1043, 27, 0, 0,
- 0, 1008, 0, 27, 1051, 0, 0, 0, 0, 0,
- 1056, 1057, 1058, 1059, 1060, 1061, 1015, 0, 863, 129,
- 6, 7, 8, 361, 207, 208, 0, 209, 10, 864,
- 0, 865, 866, 867, 868, 869, 870, 871, 872, 873,
- 874, 11, 12, 13, 210, 211, 212, 0, 213, 0,
- 14, 0, 214, -240, 0, 215, 16, 17, 0, 0,
- 0, 216, 0, 0, 875, 310, 0, 0, 0, 0,
- 0, 72, 6, 217, 8, 73, 218, 0, 0, 0,
- 10, 0, 0, 0, 219, 220, 221, 0, 0, 0,
- 222, 223, 0, 0, 0, 13, 0, 0, 224, 0,
- 876, 0, 14, 877, 0, 0, 878, 879, 880, 17,
- 881, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 882, 1016, 225, 226, 1025, 0, 863, 129, 6, 7,
- 8, 361, 207, 208, 0, 209, 10, 864, 0, 865,
- 866, 867, 868, 869, 870, 871, 872, 873, 874, 11,
- 12, 13, 210, 211, 212, 0, 213, 0, 14, 0,
- 214, -240, 23, 215, 16, 17, 0, 0, 0, 216,
- 0, 0, 875, 310, 0, 0, 0, 0, 0, 0,
- 0, 217, 0, 0, 218, 0, 0, 0, 0, 0,
- 0, 0, 219, 220, 221, 0, 0, 0, 222, 223,
- 0, 0, 0, 0, 0, 0, 224, 0, 876, 0,
- 0, 877, 0, 0, 878, 879, 880, 0, 881, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 882, 1026,
- 225, 226, 1029, 0, 863, 129, 6, 7, 8, 361,
- 207, 208, 0, 209, 10, 864, 0, 865, 866, 867,
- 868, 869, 870, 871, 872, 873, 874, 11, 12, 13,
- 210, 211, 212, 0, 213, 0, 14, 0, 214, -240,
- 0, 215, 16, 17, 0, 0, 0, 216, 0, 0,
- 875, 310, 0, 0, 0, 0, 0, 0, 0, 217,
- 0, 0, 218, 0, 0, 0, 0, 0, 0, 0,
- 219, 220, 221, 0, 0, 0, 222, 223, 0, 0,
- 0, 0, 0, 0, 224, 0, 876, 0, 0, 877,
- 0, 0, 878, 879, 880, 0, 881, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 882, 1030, 225, 226,
- 1015, 0, 863, 129, 6, 7, 8, 361, 207, 208,
- 0, 209, 10, 864, 0, 865, 866, 867, 868, 869,
- 870, 871, 872, 873, 874, 11, 12, 13, 210, 211,
- 212, 0, 213, 0, 14, 0, 214, -240, 0, 215,
- 16, 17, 0, 0, 0, 216, 0, 0, 875, 310,
- 0, 0, 0, 0, 0, 0, 0, 217, 0, 0,
- 218, 0, 0, 0, 0, 0, 0, 0, 219, 220,
- 221, 0, 0, 0, 222, 223, 0, 0, 0, 0,
- 0, 0, 224, 0, 876, 0, 0, 877, 0, 0,
- 878, 879, 880, 0, 881, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 882, 1118, 225, 226, 1015, 0,
- 863, 129, 6, 7, 8, 361, 207, 208, 0, 209,
- 10, 864, 0, 865, 866, 867, 868, 869, 870, 871,
- 872, 873, 874, 11, 12, 13, 210, 211, 212, 0,
- 213, 0, 14, 0, 214, -240, 0, 215, 16, 17,
- 0, 0, 0, 216, 0, 0, 875, 310, 0, 0,
- 0, 0, 0, 0, 0, 217, 0, 0, 218, 0,
- 0, 0, 0, 0, 0, 0, 219, 220, 221, 0,
- 0, 0, 222, 223, 0, 0, 0, 0, 0, 0,
- 224, 0, 876, 0, 0, 877, 0, 0, 878, 879,
- 880, 0, 881, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 882, 1121, 225, 226, 1015, 0, 863, 129,
- 6, 7, 8, 361, 207, 208, 0, 209, 10, 864,
- 0, 865, 866, 867, 868, 869, 870, 871, 872, 873,
- 874, 11, 12, 13, 210, 211, 212, 0, 213, 0,
- 14, 0, 214, -240, 0, 215, 16, 17, 0, 0,
- 0, 216, 0, 0, 875, 310, 0, 0, 0, 0,
- 0, 0, 0, 217, 0, 0, 218, 0, 0, 0,
- 0, 0, 0, 0, 219, 220, 221, 0, 0, 0,
- 222, 223, 0, 0, 0, 0, 0, 0, 224, 0,
- 876, 0, 0, 877, 0, 0, 878, 879, 880, 0,
- 881, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 882, 1215, 225, 226, 862, 0, 863, 129, 6, 7,
- 8, 361, 207, 208, 0, 209, 10, 864, 0, 865,
- 866, 867, 868, 869, 870, 871, 872, 873, 874, 11,
- 12, 13, 210, 211, 212, 0, 213, 0, 14, 0,
- 214, -240, 0, 215, 16, 17, 0, 0, 0, 216,
- 0, 0, 875, 310, 0, 0, 0, 0, 0, 0,
- 0, 217, 0, 0, 218, 0, 0, 0, 0, 0,
- 0, 0, 219, 220, 221, 0, 0, 0, 222, 223,
- 0, 0, 0, 0, 0, 0, 224, 0, 876, 0,
- 0, 877, 0, 0, 878, 879, 880, 0, 881, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 882, 0,
- 225, 226, 1192, 0, 863, 129, 6, 7, 8, 361,
- 207, 208, 0, 209, 10, 864, 0, 865, 866, 867,
- 868, 869, 870, 871, 872, 873, 874, 11, 12, 13,
- 210, 211, 212, 0, 213, 0, 14, 0, 214, -240,
- 0, 215, 16, 17, 0, 0, 0, 216, 0, 0,
- 875, 310, 0, 0, 0, 0, 0, 72, 6, 217,
- 8, 73, 218, 0, 0, 0, 10, 0, 0, 0,
- 219, 220, 221, 0, 0, 0, 222, 223, 0, 0,
- 0, 13, 0, 0, 224, 0, 876, 0, 14, 877,
- 0, 0, 878, 879, 880, 17, 881, 0, 0, 0,
- 0, 0, 1067, 0, 0, 0, 882, 0, 225, 226,
- 360, 0, 205, 129, 6, 7, 8, 361, 207, 208,
- 245, 209, 10, 421, 422, 423, 424, 425, 426, 427,
- 428, 429, 430, 431, 432, 433, 1068, 13, 210, 211,
- 212, 0, 213, 0, 14, 0, 214, -240, 23, 215,
- 16, 17, 0, 0, 0, 216, 0, 0, 0, 0,
- 0, 0, 72, 6, 161, 8, 162, 217, 0, 0,
- 218, 10, 0, 0, 0, 0, 4, 118, 219, 220,
- 221, 0, 0, 0, 222, 223, 13, 0, 0, 0,
- 0, 0, 224, 14, 0, 0, 0, 0, 0, 0,
- 17, 0, 0, 246, 23, 0, 0, 0, 0, 0,
- 0, 0, 0, -624, 16, 0, 225, 226, 552, 19,
- 205, 129, 6, 7, 8, 361, 207, 208, 245, 209,
- 10, 0, 0, 0, 321, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 322, 13, 210, 211, 212, 0,
- 213, 323, 14, 23, 214, -240, 324, 215, 16, 17,
- 0, 0, 0, 216, 0, 0, 0, 0, 23, 0,
- 72, 6, 7, 8, 9, 217, 0, 0, 218, 10,
- 27, 0, 0, 0, 4, 118, 219, 220, 221, 0,
- 0, 0, 222, 223, 13, 0, 0, 0, 0, 0,
- 224, 14, 0, 0, 0, 0, 0, 0, 17, 0,
- 0, 246, 23, 0, 0, 0, 0, 0, 0, 0,
- 0, -624, 16, 0, 225, 226, 739, 19, 205, 129,
- 6, 7, 8, 361, 207, 208, 245, 209, 10, 0,
- 0, 0, 542, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 543, 13, 210, 211, 212, 0, 213, 323,
- 14, 23, 214, -240, 324, 215, 16, 17, 0, 0,
- 0, 216, 0, 0, 0, 0, 23, 0, 0, 0,
- 0, 0, 0, 217, 0, 0, 218, 0, 27, 0,
- 0, 0, 4, 381, 219, 220, 221, 0, 0, 0,
- 222, 223, 0, 0, 0, 0, 0, 0, 224, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 246,
- 23, 0, 0, 0, 0, 0, 0, 0, 0, -624,
- 16, 0, 225, 226, 792, 19, 205, 129, 6, 7,
- 8, 361, 207, 208, 245, 209, 10, 0, 0, 0,
- 557, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 558, 13, 210, 211, 212, 0, 213, 0, 14, 0,
- 214, -240, 22, 215, 16, 17, 0, 0, 0, 216,
- 0, 0, 0, 0, 382, 0, 0, 0, 0, 0,
- 0, 217, 0, 0, 218, 0, 27, 0, 0, 0,
- 0, 0, 219, 220, 221, 0, 0, 0, 222, 223,
- 0, 0, 0, 0, 0, 0, 224, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 246, 23, 0,
- 0, 0, 0, 0, 0, 0, 0, -624, 0, 0,
- 225, 226, 796, 0, 205, 129, 6, 7, 8, 361,
- 207, 208, 245, 209, 10, 420, 421, 422, 423, 424,
- 425, 426, 427, 428, 429, 430, 431, 432, 433, 13,
- 210, 211, 212, 0, 213, 0, 14, 0, 214, -240,
- 0, 215, 16, 17, 0, 0, 0, 216, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 217,
- 0, 0, 218, 0, 0, 0, 0, 0, 0, 0,
- 219, 220, 221, 0, 0, 0, 222, 223, 0, 0,
- 0, 0, 0, 0, 224, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 246, 23, 0, 0, 0,
- 0, 0, 0, 0, 0, -624, 0, 0, 225, 226,
- 526, 0, 719, 720, 6, 0, 8, 388, 207, 208,
- 0, 209, 10, 422, 423, 424, 425, 426, 427, 428,
- 429, 430, 431, 432, 433, 0, 0, 13, 210, 211,
- 212, 0, 213, 0, 14, 0, 214, -240, 0, 215,
- 16, 17, 0, 0, 0, 216, 0, 0, 0, 527,
- 0, 0, 0, 0, 0, 0, 0, 217, 0, 0,
- 218, 0, 0, 0, 0, 0, 0, 0, 219, 220,
- 221, 0, 0, 0, 222, 223, 0, 0, 0, 0,
- 0, 0, 224, 721, 526, 0, 719, 720, 6, 0,
- 8, 388, 207, 208, 183, 209, 10, 0, 0, 0,
- 0, 0, 0, 973, 0, 722, 225, 226, 0, 0,
- 0, 13, 210, 211, 212, 0, 213, 0, 14, 0,
- 214, -240, 0, 215, 16, 17, 0, 0, 0, 216,
- 0, 0, 0, 527, 0, 0, 0, 0, 0, 0,
- 0, 217, 0, 0, 218, 0, 0, 0, 0, 0,
- 0, 0, 219, 220, 221, 0, 0, 0, 222, 223,
- 0, 0, 0, 0, 0, 1087, 224, 205, 129, 6,
- 7, 8, 361, 207, 208, 0, 209, 10, 183, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 974,
- 225, 226, 13, 210, 211, 212, 0, 213, 0, 14,
- 0, 214, -240, 0, 215, 16, 17, 0, 0, 0,
- 216, 0, 0, 0, 1088, 0, 0, 0, 0, 0,
- 0, 0, 217, 0, 0, 218, 0, 0, 0, 0,
- 0, 0, 0, 219, 220, 221, 0, 0, 0, 222,
- 223, 0, 0, 0, 0, 0, 526, 224, 719, 720,
- 6, 0, 8, 388, 207, 208, 0, 209, 10, 23,
- 0, 0, 0, 0, 0, 973, 0, 0, 0, 1089,
- 0, 225, 226, 13, 210, 211, 212, 0, 213, 0,
- 14, 0, 214, -240, 0, 215, 16, 17, 0, 0,
- 0, 216, 0, 0, 0, 527, 0, 0, 0, 0,
- 0, 0, 0, 217, 0, 0, 218, 0, 0, 0,
- 0, 0, 0, 0, 219, 220, 221, 0, 0, 0,
- 222, 223, 0, 0, 0, 0, 0, 526, 224, 719,
- 720, 6, 0, 8, 388, 207, 208, 0, 209, 10,
- 183, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, -333, 225, 226, 13, 210, 211, 212, 0, 213,
- 0, 14, 0, 214, -240, 0, 215, 16, 17, 0,
- 0, 0, 216, 0, 0, 0, 527, 0, 0, 0,
- 0, 0, 0, 0, 217, 0, 0, 218, 0, 0,
- 0, 0, 0, 0, 0, 219, 220, 221, 0, 0,
- 0, 222, 223, 0, 0, 0, 0, 0, 0, 224,
- 721, 406, 0, 205, 129, 6, 0, 8, 206, 207,
- 208, 183, 209, 10, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 225, 226, 0, 0, 0, 13, 210,
- 211, 212, 0, 213, 0, 14, 0, 214, -240, 0,
- 215, 16, 17, 0, 0, 0, 216, 0, 0, 0,
- -211, 0, 0, 0, 0, 0, 0, 0, 217, 0,
- 0, 218, 0, 0, 0, 0, 0, 0, 0, 219,
- 220, 221, 0, 0, 0, 222, 223, 0, 0, 0,
- 0, 0, 526, 224, 205, 129, 6, 0, 8, 388,
- 207, 208, 0, 209, 10, 23, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 225, 226, 13,
- 210, 211, 212, 0, 213, 0, 14, 0, 214, -240,
- 0, 215, 16, 17, 0, 0, 0, 216, 0, 0,
- 0, 527, 0, 0, 0, 0, 0, 0, 0, 217,
- 0, 0, 218, 0, 0, 0, 0, 0, 0, 0,
- 219, 220, 221, 0, 0, 0, 222, 223, 0, 0,
- 0, 0, 0, 626, 224, 205, 129, 6, 0, 8,
- 388, 207, 208, 0, 209, 10, 23, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 225, 226,
- 13, 210, 211, 212, 0, 213, 0, 14, 0, 214,
- -240, 0, 215, 16, 17, 0, 0, 0, 216, 0,
- 0, 0, 0, 0, 0, 0, 0, -614, 0, 0,
- 217, 0, 0, 218, 0, 0, 0, 0, 0, 0,
- 0, 219, 220, 221, 0, 0, 0, 222, 223, 0,
- 0, 0, 0, 0, 626, 224, 205, 129, 6, 0,
- 8, 388, 207, 208, 0, 209, 10, 23, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 225,
- 226, 13, 210, 211, 212, 0, 213, 0, 14, 0,
- 214, -240, 0, 215, 16, 17, 0, 0, 0, 216,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 217, 0, 0, 218, 0, 0, 0, 0, 0,
- 0, 0, 219, 220, 221, 0, 0, 0, 222, 223,
- 0, 0, 0, 0, 0, 626, 224, 205, 129, 6,
- 0, 8, 388, 207, 208, 0, 209, 10, 23, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, -614, 0,
- 225, 226, 13, 210, 211, 212, 0, 213, 0, 14,
- 0, 214, -240, 0, 215, 16, 17, 0, 0, 0,
- 216, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 217, 0, 0, 218, 0, 0, 0, 0,
- 0, 0, 0, 219, 220, 221, 0, 0, 0, 222,
- 223, 0, 0, 0, 0, 0, 682, 224, 205, 129,
- 6, 0, 8, 388, 207, 208, 0, 209, 10, 23,
- 0, 0, 0, 0, 0, 0, 0, 0, -614, 0,
- 0, 225, 226, 13, 210, 211, 212, 0, 213, 0,
- 14, 0, 214, -240, 0, 215, 16, 17, 0, 0,
- 0, 216, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 217, 0, 0, 218, 0, 0, 0,
- 0, 0, 0, 0, 219, 220, 221, 0, 0, 0,
- 222, 223, 0, 0, 0, 0, 0, 0, 224, 205,
- 129, 6, 0, 8, 388, 207, 208, 0, 209, 10,
- 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 225, 226, 13, 210, 211, 212, 0, 213,
- 0, 14, 0, 214, 0, 0, 215, 16, 17, 0,
- 0, 350, 216, 4, 129, 6, 7, 8, 9, 0,
- 0, 0, 0, 10, 217, 0, 0, 218, 0, 0,
- 0, 0, 0, 0, 0, 219, 220, 221, 13, 0,
- 0, 222, 223, 0, 0, 14, -373, 0, 0, 224,
- 0, 16, 17, 0, 0, 0, 19, 0, 0, 0,
- 0, 23, 0, 0, 0, 351, 0, 0, 0, 0,
- 0, 20, 0, 225, 226, 655, 0, 0, 0, 0,
- 350, 21, 4, 129, 6, 7, 8, 9, 0, 0,
- 0, 0, 10, 22, 0, 0, 3, 0, 4, 5,
- 6, 7, 8, 9, 0, 23, 0, 13, 10, 0,
- 0, 0, 0, 0, 14, -376, -373, 27, 0, 0,
- 16, 17, 0, 13, 0, 19, 0, 0, 0, 0,
- 14, 0, 0, 0, 351, 0, 16, 17, 0, 0,
- 20, 19, 0, 0, 0, 0, 0, 0, 0, 0,
- 21, 0, 0, 0, 0, 0, 20, 0, 0, 0,
- 0, 0, 22, 0, 0, 0, 21, 0, 0, 0,
- 0, 0, 0, 0, 23, 0, 0, 0, 22, 0,
- 0, 0, 0, 0, 0, -376, 27, 0, 0, 0,
- 23, 24, 0, 0, 0, 0, 0, 0, 0, 0,
- 26, 0, 27, 863, 129, 6, 7, 8, 361, 207,
- 208, 0, 209, 10, 864, 0, 865, 866, 867, 868,
- 869, 870, 871, 872, 873, 874, 11, 12, 13, 210,
- 211, 212, 0, 213, 0, 14, 0, 214, 0, 0,
- 215, 16, 17, 0, 0, 0, 216, 0, 0, 875,
- 310, 0, 0, 0, 0, 0, 0, 0, 217, 0,
- 0, 218, 0, 0, 0, 0, 0, 0, 0, 219,
- 220, 221, 0, 0, 0, 222, 223, 0, 0, 0,
- 0, 0, 0, 224, 0, 876, 0, 0, 877, 0,
- 0, 878, 879, 880, 0, 881, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 882, 1023, 225, 226, 863,
- 129, 6, 7, 8, 361, 207, 208, 0, 209, 10,
- 864, 0, 865, 866, 867, 868, 869, 870, 871, 872,
- 873, 874, 11, 12, 13, 210, 211, 212, 0, 213,
- 0, 14, 0, 214, 0, 0, 215, 16, 17, 0,
- 0, 0, 216, 0, 0, 875, 310, 0, 0, 0,
- 0, 0, 0, 0, 217, 0, 0, 218, 0, 0,
- 0, 0, 0, 0, 0, 219, 220, 221, 0, 0,
- 0, 222, 223, 0, 0, 0, 0, 0, 0, 224,
- 0, 876, 0, 0, 877, 0, 0, 878, 879, 880,
- 0, 881, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 882, 0, 225, 226, 863, 129, 6, 7, 8,
- 361, 207, 208, 0, 209, 10, 864, 0, 865, 866,
- 867, 868, 869, 870, 871, 872, 873, 874, 11, 12,
- 13, 210, 211, 212, 0, 213, 0, 14, 0, 214,
- 0, 0, 215, 16, 17, 0, 0, 0, 216, 0,
- 0, 875, 0, 0, 0, 0, 0, 0, 0, 0,
- 217, 0, 0, 218, 0, 0, 0, 0, 0, 0,
- 0, 219, 220, 221, 0, 0, 0, 222, 223, 0,
- 0, 0, 0, 0, 0, 224, 0, 876, 0, 0,
- 877, 0, 0, 878, 879, 880, 0, 881, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 882, 0, 225,
- 226, 205, 129, 6, 0, 8, 388, 207, 208, 0,
- 209, 10, 72, 6, 7, 8, 9, 0, 0, 245,
- 0, 10, 0, 0, 0, 0, 13, 210, 211, 212,
- 0, 213, 0, 14, 0, 214, 13, 0, 215, 16,
- 17, 0, 0, 14, 216, 398, 72, 6, 0, 8,
- 17, 0, 0, 0, 0, 10, 217, 0, 0, 218,
- 0, 0, 0, 0, 0, 0, 0, 219, 220, 221,
- 13, 0, 0, 222, 223, 0, 0, 14, 0, 214,
- 0, 224, 445, 16, 17, 205, 129, 6, 399, 8,
- 388, 207, 208, 23, 209, 10, 0, 0, 0, 0,
- 0, 0, 246, 23, 0, 225, 226, 0, 0, 0,
- 13, 210, 211, 212, 0, 213, 0, 14, 0, 214,
- 0, 0, 215, 16, 17, 0, 0, 0, 216, 0,
- 0, 0, 808, 0, 0, 0, 0, 23, 0, 0,
- 217, 0, 0, 218, 0, 0, 0, 0, 0, 0,
- 0, 219, 220, 221, 0, 0, 0, 222, 223, 0,
- 0, 0, 0, 0, 0, 224, 205, 129, 6, 0,
- 8, 388, 207, 208, 0, 209, 10, 23, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 225,
- 226, 13, 210, 211, 212, 0, 213, 0, 14, 0,
- 214, 0, 0, 215, 16, 17, 0, 0, 0, 216,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 217, 0, 0, 218, 0, 0, 0, 0, 0,
- 0, 0, 219, 220, 221, 0, 0, 0, 222, 223,
- 0, 0, 0, 0, 0, 0, 224, 205, 129, 6,
- 0, 8, 388, 207, 208, 0, 209, 10, 23, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 991, 0,
- 225, 226, 13, 210, 211, 212, 0, 213, 0, 14,
- 0, 214, 0, 0, 215, 16, 17, 0, 0, 0,
- 216, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 217, 0, 0, 218, 0, 0, 0, 0,
- 0, 0, 0, 219, 220, 221, 0, 0, 0, 222,
- 223, 0, 0, 0, 0, 0, 0, 224, 205, 129,
- 6, 0, 8, 206, 207, 208, 0, 209, 10, 23,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1002,
- 0, 225, 226, 13, 210, 211, 212, 0, 213, 0,
- 14, 0, 214, 0, 0, 215, 16, 17, 0, 0,
- 0, 216, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 217, 0, 0, 218, 0, 0, 0,
- 0, 0, 0, 0, 219, 220, 221, 0, 0, 0,
- 222, 223, 0, 0, 0, 0, 0, 0, 224, 205,
- 129, 6, 0, 8, 388, 207, 208, 0, 209, 10,
- 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 225, 226, 13, 210, 211, 212, 0, 213,
- 0, 14, 0, 214, 0, 0, 215, 16, 17, 0,
- 0, 0, 216, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 217, 0, 0, 218, 0, 0,
- 0, 0, 0, 0, 0, 219, 220, 221, 0, 0,
- 0, 222, 223, 0, 0, 0, 0, 0, 0, 224,
- 205, 614, 6, 0, 8, 388, 207, 208, 0, 209,
- 10, 23, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 225, 226, 13, 210, 211, 212, 0,
- 213, 0, 14, 0, 214, 0, 0, 215, 16, 17,
- 0, 0, 0, 216, 205, 129, 6, 0, 8, 388,
- 207, 208, 0, 209, 10, 217, 0, 0, 218, 0,
- 0, 0, 0, 0, 0, 0, 219, 220, 221, 13,
- 210, 0, 222, 223, 213, 0, 14, 0, 214, 0,
- 224, 215, 16, 17, 0, 0, 0, 216, 0, 0,
- 0, 0, 23, 0, 0, 0, 0, 0, 0, 217,
- 0, 0, 218, 0, 225, 226, 0, 0, 0, 0,
- 219, 220, 221, 0, 0, 0, 222, 223, 0, 0,
- 0, 205, 129, 6, 389, 8, 388, 207, 208, 0,
- 209, 10, 0, 0, 0, 0, 23, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 13, 210, 225, 226,
- 0, 213, 0, 14, 0, 214, 0, 0, 215, 16,
- 17, 0, 0, 0, 216, 572, 160, 6, 161, 8,
- 162, 0, 0, 0, 0, 10, 217, 0, 0, 218,
- 0, 0, 0, 0, 0, 0, 0, 219, 220, 221,
- 13, 0, 0, 222, 223, 0, 0, 14, 0, 0,
- 0, 393, 0, 16, 17, 0, 580, 0, 19, 147,
- 0, 574, 0, 23, 0, 0, 0, 575, 0, 0,
- 0, 0, 0, 148, 0, 225, 226, 4, 129, 6,
- 7, 8, 9, 149, 0, 673, 0, 10, 0, 0,
- 150, 0, 0, 0, 0, 581, 0, 0, 0, 0,
- 0, 0, 13, 0, 0, 0, 0, 23, 0, 14,
- 0, 0, 0, 0, 0, 16, 17, 0, 264, 27,
- 19, 664, 4, 129, 6, 7, 8, 9, 0, 0,
- 245, 0, 10, 0, 0, 665, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 666, 0, 13, 0, 0,
- 0, 0, 268, 0, 14, 0, 0, 667, 270, 0,
- 16, 17, 0, 264, 0, 19, 0, 0, 0, 23,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 665, 27, 0, 0, 4, 129, 6, 7, 8, 9,
- 666, 0, 245, 0, 10, 0, 0, 268, 0, 0,
- 0, 0, 667, 270, 0, 0, 0, 0, 0, 13,
- 0, 0, 0, 246, 23, 0, 14, 0, 0, 0,
- 0, 0, 16, 17, 0, 0, 27, 19, 4, 160,
- 6, 161, 8, 162, 0, 0, 0, 0, 10, 0,
- 0, 0, 321, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 322, 13, 129, 6, 7, 8, 9, 323,
- 14, 245, 0, 10, 324, 0, 16, 17, 0, 0,
- 0, 19, 147, 0, 0, 246, 23, 0, 13, 0,
- 0, 0, 0, 0, 0, 14, 148, 0, 27, 0,
- 0, 0, 17, 0, 264, 0, 149, 0, 72, 6,
- 0, 8, 275, 150, 0, 0, 0, 10, 151, 0,
- 0, 266, 0, 0, 0, 0, 0, 0, 0, 0,
- 23, 267, 13, 0, 0, 0, 0, 0, 268, 14,
- 1011, 0, 27, 269, 270, 0, 17, 0, 264, 0,
- 0, 265, 0, 0, 246, 23, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 266, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 267, 0, 0, 0, 0,
- 0, 0, 268, 0, 0, 0, 0, 269, 270, 0,
- 0, 0, 0, 0, 0, 414, 415, 416, 0, 23,
- 417, 418, 419, 420, 421, 422, 423, 424, 425, 426,
- 427, 428, 429, 430, 431, 432, 433, 414, 415, 416,
- 0, 0, 417, 418, 419, 420, 421, 422, 423, 424,
- 425, 426, 427, 428, 429, 430, 431, 432, 433, 0,
- 0, 0, 0, 0, 0, 0, 0, 602, 0, 0,
- 0, 0, 971, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 414, 415, 416,
- 759, 760, 417, 418, 419, 420, 421, 422, 423, 424,
- 425, 426, 427, 428, 429, 430, 431, 432, 433, -142,
- 414, 415, 416, 0, 0, 417, 418, 419, 420, 421,
- 422, 423, 424, 425, 426, 427, 428, 429, 430, 431,
- 432, 433, 414, 415, 416, 1145, 0, 417, 418, 419,
- 420, 421, 422, 423, 424, 425, 426, 427, 428, 429,
- 430, 431, 432, 433, 414, 415, 416, 0, 0, 417,
- 418, 419, 420, 421, 422, 423, 424, 425, 426, 427,
- 428, 429, 430, 431, 432, 433, 414, 415, 416, 0,
- 0, 417, 418, 419, 420, 421, 422, 423, 424, 425,
- 0, 427, 428, 429, 430, 431, 432, 433, 416, 0,
- 0, 417, 418, 419, 420, 421, 422, 423, 424, 425,
- 426, 427, 428, 429, 430, 431, 432, 433, 418, 419,
- 420, 421, 422, 423, 424, 425, 426, 427, 428, 429,
- 430, 431, 432, 433, 419, 420, 421, 422, 423, 424,
- 425, 426, 427, 428, 429, 430, 431, 432, 433
-};
-
-static const short yycheck[] = { 10,
- 16, 68, 270, 1, 2, 107, 300, 139, 140, 16,
- 40, 597, 112, 45, 41, 356, 278, 151, 16, 1,
- 2, 140, 243, 888, 62, 125, 310, 983, 1, 2,
- 278, 41, 196, 31, 45, 329, 1032, 1033, 216, 209,
- 210, 896, 40, 898, 138, 708, 947, 516, 218, 51,
- 191, 221, 19, 1, 2, 225, 10, 10, 31, 229,
- 888, 1, 2, 61, 62, 235, 334, 895, 147, 46,
- 68, 568, 218, 10, 10, 221, 10, 36, 46, 225,
- 549, 108, 44, 229, 0, 24, 3, 4, 65, 235,
- 37, 31, 44, 24, 39, 40, 46, 65, 83, 46,
- 1114, 55, 68, 105, 106, 3, 4, 5, 35, 50,
- 61, 109, 5, 265, 55, 65, 55, 269, 3, 50,
- 71, 83, 53, 121, 55, 3, 4, 464, 105, 127,
- 467, 83, 84, 131, 1148, 1149, 104, 239, 165, 51,
- 242, 305, 51, 304, 171, 127, 65, 106, 46, 51,
- 104, 104, 104, 46, 127, 165, 83, 224, 196, 36,
- 134, 171, 1027, 1064, 105, 203, 1031, 104, 104, 333,
- 104, 1, 2, 314, 105, 307, 308, 309, 95, 153,
- 1194, 3, 4, 5, 847, 130, 131, 127, 307, 308,
- 324, 158, 22, 167, 106, 193, 105, 95, 196, 1027,
- 98, 31, 699, 1031, 106, 203, 217, 1203, 1204, 39,
- 40, 505, 306, 240, 55, 65, 198, 95, 216, 467,
- 193, 399, 44, 387, 492, 51, 224, 397, 51, 106,
- 204, 50, 453, 44, 703, 1191, 55, 1251, 1252, 51,
- 319, 320, 253, 50, 242, 51, 273, 8, 55, 276,
- 248, 397, 200, 193, 3, 4, 105, 106, 224, 83,
- 66, 83, 51, 273, 105, 559, 51, 1095, 3, 4,
- 302, 269, 83, 95, 3, 4, 408, 441, 104, 547,
- 278, 104, 751, 3, 4, 115, 116, 117, 51, 287,
- 876, 302, 878, 105, 458, 333, 765, 127, 105, 1154,
- 130, 131, 3, 4, 5, 287, 41, 106, 51, 470,
- 337, 378, 41, 11, 287, 347, 105, 147, 292, 104,
- 302, 151, 389, 3, 4, 86, 393, 337, 1193, 1157,
- 482, 483, 93, 51, 50, 333, 51, 364, 55, 287,
- 3, 4, 105, 6, 174, 46, 95, 287, 65, 846,
- 50, 71, 300, 51, 364, 519, 354, 55, 356, 50,
- 95, 44, 105, 193, 51, 1193, 95, 51, 198, 343,
- 50, 201, 107, 36, 51, 95, 65, 444, 107, 55,
- 378, 329, 546, 356, 358, 3, 4, 105, 6, 1217,
- 105, 389, 340, 5, 95, 393, 94, 98, 44, 531,
- 83, 84, 368, 51, 51, 44, 51, 237, 353, 354,
- 384, 1, 531, 411, 55, 95, 356, 104, 36, 66,
- 104, 104, 51, 389, 109, 51, 86, 393, 105, 395,
- 396, 44, 95, 93, 55, 697, 10, 83, 84, 269,
- 451, 605, 576, 607, 83, 84, 444, 581, 1, 697,
- 416, 920, 44, 491, 618, 924, 104, 287, 104, 104,
- 50, 540, 541, 104, 475, 104, 498, 494, 51, 467,
- 83, 84, 302, 86, 768, 104, 442, 95, 104, 445,
- 93, 51, 776, 104, 494, 655, 650, 498, 652, 319,
- 320, 83, 105, 491, 324, 659, 51, 50, 51, 663,
- 330, 601, 3, 4, 3, 335, 42, 8, 546, 655,
- 9, 66, 664, 524, 50, 667, 527, 8, 51, 26,
- 27, 104, 50, 353, 354, 32, 356, 55, 51, 3,
- 4, 5, 51, 66, 104, 44, 568, 51, 576, 51,
- 41, 105, 106, 581, 51, 46, 53, 21, 546, 713,
- 16, 715, 7, 8, 718, 106, 22, 505, 13, 1,
- 61, 3, 4, 5, 6, 7, 8, 605, 46, 607,
- 71, 13, 46, 39, 83, 84, 3, 1046, 576, 44,
- 35, 104, 83, 581, 44, 104, 28, 42, 53, 44,
- 104, 932, 104, 35, 95, 104, 62, 50, 105, 41,
- 42, 99, 55, 577, 46, 51, 107, 605, 582, 607,
- 51, 559, 105, 51, 109, 597, 26, 27, 83, 61,
- 55, 95, 83, 83, 98, 83, 653, 51, 83, 71,
- 51, 51, 106, 463, 464, 44, 652, 467, 51, 1225,
- 51, 83, 38, 109, 83, 652, 3, 4, 51, 115,
- 116, 117, 822, 95, 652, 819, 735, 736, 104, 820,
- 1129, 825, 1131, 104, 130, 107, 104, 699, 679, 667,
- 749, 750, 833, 834, 83, 84, 822, 829, 830, 711,
- 104, 147, 83, 104, 104, 151, 51, 839, 840, 44,
- 854, 104, 10, 104, 44, 104, 857, 858, 672, 697,
- 711, 104, 51, 51, 3, 4, 105, 106, 174, 104,
- 540, 541, 53, 813, 816, 817, 106, 728, 44, 786,
- 44, 753, 44, 105, 106, 3, 4, 44, 83, 711,
- 104, 729, 198, 83, 84, 201, 86, 203, 44, 104,
- 104, 44, 41, 93, 3, 44, 576, 46, 47, 109,
- 216, 581, 44, 50, 1048, 104, 729, 83, 84, 83,
- 84, 83, 61, 41, 44, 109, 83, 597, 46, 47,
- 44, 237, 71, 105, 106, 936, 242, 83, 84, 78,
- 83, 779, 248, 61, 83, 84, 106, 44, 786, 729,
- 764, 83, 44, 71, 46, 104, 95, 808, 109, 773,
- 78, 105, 106, 83, 1088, 83, 779, 3, 107, 83,
- 971, 104, 278, 65, 846, 1109, 86, 95, 1102, 817,
- 768, 1105, 51, 93, 769, 799, 83, 105, 776, 107,
- 83, 83, 26, 27, 664, 105, 302, 667, 104, 779,
- 32, 3, 4, 5, 6, 7, 8, 858, 104, 44,
- 104, 13, 984, 319, 320, 50, 50, 887, 324, 46,
- 55, 55, 104, 874, 330, 876, 28, 86, 55, 335,
- 71, 72, 73, 35, 93, 1143, 1144, 1038, 65, 41,
- 42, 711, 53, 950, 46, 47, 105, 353, 83, 887,
- 888, 105, 106, 51, 876, 104, 878, 895, 896, 61,
- 898, 1062, 104, 869, 902, 735, 736, 873, 35, 71,
- 55, 56, 378, 34, 880, 888, 78, 1078, 109, 749,
- 750, 83, 895, 896, 109, 898, 105, 106, 105, 902,
- 44, 105, 106, 95, 932, 105, 106, 1101, 105, 769,
- 1104, 886, 887, 105, 105, 107, 105, 61, 888, 779,
- 105, 106, 950, 105, 928, 895, 896, 71, 898, 932,
- 209, 210, 902, 109, 78, 1126, 977, 1128, 61, 83,
- 84, 104, 6, 7, 8, 104, 51, 1141, 444, 13,
- 5, 1142, 1114, 109, 1145, 55, 55, 985, 83, 26,
- 27, 53, 932, 104, 104, 104, 104, 463, 464, 829,
- 830, 35, 6, 7, 8, 104, 55, 1107, 42, 13,
- 44, 1022, 985, 50, 53, 109, 1148, 1149, 55, 985,
- 986, 109, 83, 53, 53, 491, 106, 993, 121, 1027,
- 104, 35, 109, 1031, 55, 1009, 1138, 1139, 42, 1021,
- 1014, 95, 1069, 55, 1205, 985, 876, 55, 878, 83,
- 109, 1062, 1068, 104, 1027, 53, 886, 887, 1031, 104,
- 104, 1068, 1194, 104, 83, 55, 1032, 1033, 104, 1043,
- 1068, 104, 902, 104, 540, 541, 104, 1051, 83, 106,
- 3, 4, 83, 6, 7, 8, 1084, 1027, 55, 105,
- 105, 1031, 50, 50, 8, 7, 8, 1095, 105, 15,
- 1048, 13, 932, 196, 3, 4, 53, 6, 7, 8,
- 55, 1084, 35, 3, 51, 1081, 1248, 1249, 104, 1251,
- 1252, 104, 1095, 35, 3, 4, 49, 50, 1094, 55,
- 42, 597, 44, 105, 105, 105, 35, 105, 1270, 105,
- 83, 1139, 3, 4, 1084, 238, 105, 53, 83, 105,
- 49, 50, 106, 53, 84, 1095, 1154, 84, 16, 1157,
- 106, 1109, 41, 105, 105, 1113, 104, 46, 47, 105,
- 49, 83, 95, 1240, 105, 50, 55, 100, 101, 102,
- 41, 1154, 61, 105, 1157, 46, 69, 70, 71, 72,
- 73, 1021, 71, 55, 105, 1193, 95, 105, 664, 78,
- 61, 100, 101, 102, 83, 53, 104, 104, 51, 104,
- 71, 304, 305, 104, 1154, 104, 95, 1157, 105, 1217,
- 1193, 109, 83, 109, 105, 10, 90, 105, 107, 9,
- 83, 697, 105, 51, 95, 104, 83, 1203, 1204, 1250,
- 333, 104, 1240, 1225, 1217, 711, 107, 44, 51, 105,
- 47, 4, 5, 1193, 7, 8, 10, 9, 351, 104,
- 13, 105, 104, 104, 61, 1, 10, 1233, 105, 735,
- 736, 126, 1, 2, 71, 28, 0, 1217, 0, 289,
- 697, 78, 35, 749, 750, 2, 83, 84, 24, 42,
- 26, 27, 127, 22, 387, 127, 32, 711, 138, 498,
- 121, 752, 31, 769, 411, 8, 1064, 985, 165, 886,
- 330, 40, 276, 1134, 50, 51, 808, 53, 411, 55,
- 786, 414, 415, 681, 417, 418, 419, 420, 421, 422,
- 423, 424, 425, 426, 427, 428, 429, 430, 431, 432,
- 433, 44, 95, 31, 31, 753, 568, 440, 441, 732,
- 86, 817, 902, 779, 354, 475, 679, 93, 61, 324,
- 730, 1, 2, 829, 830, 458, 1028, 1234, 71, 105,
- 4, 5, 1084, 7, 8, 78, 1236, 470, 248, 13,
- 83, 84, 22, 1021, 477, -1, 115, 116, 117, 786,
- -1, 31, 44, -1, 28, 1225, -1, -1, 127, 39,
- 40, 35, -1, -1, -1, -1, -1, -1, 42, -1,
- 876, -1, 878, 7, 8, 49, -1, -1, 147, 13,
- 886, -1, 151, 75, 76, -1, 519, 79, 80, 81,
- 82, 83, 84, -1, 527, 3, 4, 5, 6, 7,
- 8, 35, -1, -1, -1, 13, -1, -1, 42, 83,
- 44, -1, -1, 546, -1, -1, -1, -1, -1, -1,
- 28, 95, -1, -1, 193, -1, -1, 35, -1, -1,
- -1, -1, 201, 41, 42, 115, 116, 117, 46, 47,
- -1, 574, 575, -1, 950, -1, -1, 127, -1, 83,
- 130, 131, 1, 61, 3, 4, 5, 6, 7, 8,
- 7, 8, -1, 71, 13, -1, 13, 147, -1, -1,
- 78, 151, 605, -1, 607, 83, -1, 26, 27, 28,
- -1, -1, -1, -1, -1, 618, 35, 95, 35, 622,
- 39, -1, 41, 42, 174, 42, 45, 46, -1, 107,
- -1, 3, 4, -1, -1, -1, 8, -1, -1, -1,
- -1, -1, 61, 193, -1, 1021, -1, 650, 287, 652,
- -1, 201, 71, -1, -1, -1, 659, -1, -1, -1,
- 663, -1, -1, 44, 83, -1, 216, -1, -1, 41,
- -1, -1, -1, -1, 46, 678, 95, 96, 97, -1,
- 319, 320, -1, 20, 21, 324, 105, 237, 107, 61,
- -1, -1, 1068, 243, 75, 76, 335, -1, 79, 71,
- 81, -1, 83, 84, -1, 1, 78, -1, -1, -1,
- 713, 83, 715, -1, -1, 718, -1, 356, 721, -1,
- -1, -1, 59, 95, -1, -1, -1, -1, 24, -1,
- 26, 27, -1, -1, -1, 107, 32, 287, 1, 76,
- 3, 4, 5, 6, 7, 8, -1, -1, 44, -1,
- 13, -1, -1, -1, 50, 51, -1, 53, 761, 55,
- 6, 7, 8, 1139, -1, 28, -1, 13, -1, 319,
- 320, -1, 35, 36, 324, -1, -1, -1, 41, 42,
- 330, -1, -1, 46, -1, 335, -1, 83, 84, 35,
- 86, -1, 55, -1, -1, -1, 42, 93, 61, -1,
- -1, -1, -1, 353, 354, 808, 356, 810, 71, 105,
- -1, 148, 149, -1, -1, -1, 819, 820, -1, -1,
- 83, -1, 825, -1, 463, 464, -1, -1, 467, -1,
- 833, 834, 95, -1, -1, -1, 1, -1, -1, -1,
- -1, -1, 105, 106, 107, -1, -1, -1, -1, 1225,
- -1, 854, -1, -1, 857, 858, -1, -1, 195, 24,
- -1, 26, 27, -1, 1240, 202, -1, 32, -1, -1,
- 0, 1, -1, 3, 4, 5, 6, 7, 8, 44,
- -1, -1, -1, 13, -1, 50, 51, -1, 53, -1,
- 55, -1, -1, -1, -1, -1, 26, 27, 28, -1,
- -1, 540, 541, 453, -1, 35, -1, -1, -1, 39,
- -1, 41, 42, 463, 464, 45, 46, 467, 83, 84,
- -1, 86, -1, 926, 927, -1, -1, 264, 93, 266,
- 267, 61, -1, 936, -1, -1, -1, 576, -1, -1,
- 105, 71, 581, 64, 65, 66, 67, 68, 69, 70,
- 71, 72, 73, 83, 63, 64, 65, 66, 67, 68,
- 69, 70, 71, 72, 73, 95, 96, 97, 971, -1,
- 973, -1, -1, -1, -1, 105, 1, 107, 3, 4,
- 5, 6, 7, 8, 321, 322, 3, 4, 13, -1,
- 540, 541, -1, -1, -1, 332, -1, -1, -1, -1,
- -1, 26, 27, 28, -1, -1, -1, -1, -1, -1,
- 35, -1, -1, -1, 39, -1, 41, 42, -1, -1,
- 45, 46, -1, -1, 41, 664, 576, 44, 667, 46,
- 47, 581, 49, -1, -1, 1038, 61, -1, 55, -1,
- -1, -1, 1045, -1, 61, -1, 71, 67, 68, 69,
- 70, 71, 72, 73, 71, -1, -1, -1, 83, 1062,
- -1, 78, -1, -1, -1, -1, 83, -1, -1, -1,
- 95, 96, 97, -1, -1, 1078, -1, -1, 95, -1,
- 105, 106, 107, -1, -1, -1, -1, -1, -1, -1,
- 107, -1, -1, -1, -1, -1, 735, 736, 1101, -1,
- -1, 1104, -1, -1, -1, -1, -1, -1, -1, 1,
- 749, 750, 4, 5, 664, 7, 8, 667, -1, -1,
- -1, 13, -1, 1126, -1, 1128, -1, -1, 465, -1,
- -1, -1, -1, -1, -1, -1, 28, -1, 1141, 1142,
- 779, -1, 1145, 35, -1, 37, 38, -1, -1, -1,
- 42, 43, 44, 490, -1, 3, 4, -1, -1, 51,
- 52, 53, 54, -1, -1, 57, 58, 59, 60, 61,
- 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, -1, 75, 76, 735, 736, 79, 80, -1,
- 829, 830, 84, 41, -1, -1, -1, -1, 46, 749,
- 750, -1, 1205, 95, -1, 542, 543, -1, 545, -1,
- -1, -1, -1, 61, -1, 107, 108, -1, -1, 769,
- 557, 558, -1, 71, -1, -1, -1, -1, -1, 779,
- 78, -1, -1, -1, -1, 83, 573, -1, -1, -1,
- -1, -1, 24, 580, 26, 27, -1, 95, 887, -1,
- 32, -1, 589, 590, 591, -1, -1, -1, -1, 107,
- -1, -1, -1, 902, 46, -1, -1, 604, 50, 606,
- -1, 53, 609, -1, -1, -1, -1, -1, -1, 829,
- 830, -1, -1, 65, -1, 1, -1, 3, 4, 5,
- 6, 7, 8, 932, -1, -1, -1, 13, -1, -1,
- 3, 4, 84, -1, 86, 8, -1, -1, -1, -1,
- -1, 93, 28, -1, -1, -1, -1, -1, -1, 35,
- 36, -1, -1, -1, 106, 41, 42, -1, 665, 666,
- 46, -1, -1, -1, -1, -1, 886, 887, 41, 55,
- -1, 44, -1, 46, -1, 61, -1, -1, -1, 686,
- 687, -1, 902, 690, -1, 71, -1, -1, 61, -1,
- -1, -1, -1, -1, -1, -1, -1, 83, 71, -1,
- -1, -1, -1, -1, -1, 78, -1, -1, -1, 95,
- 83, 84, 932, -1, -1, -1, -1, -1, -1, 105,
- 106, 107, 95, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 107, -1, -1, -1, 745, 746,
- 747, -1, 1, -1, 3, 4, 5, 6, 7, 8,
- 9, 10, -1, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, -1, 33, -1, 35, -1, 37, 38,
- -1, 40, 41, 42, 3, 4, -1, 46, -1, -1,
- 49, 50, -1, -1, -1, -1, -1, -1, -1, 58,
- 3, 4, 61, -1, -1, -1, -1, -1, -1, -1,
- 69, 70, 71, 3, 4, -1, 75, 76, -1, 3,
- 4, -1, 41, -1, 83, 44, 85, 46, 87, 88,
- 89, -1, 91, 92, 93, 842, 95, -1, 41, -1,
- -1, -1, 61, 46, 47, -1, 105, 106, 107, 108,
- -1, 41, 71, -1, -1, -1, 46, 41, 61, 78,
- -1, -1, 46, 47, 83, 84, -1, -1, 71, -1,
- -1, 61, -1, -1, -1, 78, 95, 61, -1, -1,
- 83, 71, -1, -1, -1, -1, -1, 71, 107, -1,
- -1, -1, 95, 83, 78, -1, -1, -1, -1, 83,
- 907, 908, 909, -1, 107, 95, -1, -1, -1, -1,
- -1, 95, -1, -1, -1, -1, 923, 107, -1, -1,
- -1, 105, -1, 107, 931, -1, -1, -1, -1, -1,
- 937, 938, 939, 940, 941, 942, 1, -1, 3, 4,
- 5, 6, 7, 8, 9, 10, -1, 12, 13, 14,
- -1, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, -1, 33, -1,
- 35, -1, 37, 38, -1, 40, 41, 42, -1, -1,
- -1, 46, -1, -1, 49, 50, -1, -1, -1, -1,
- -1, 4, 5, 58, 7, 8, 61, -1, -1, -1,
- 13, -1, -1, -1, 69, 70, 71, -1, -1, -1,
- 75, 76, -1, -1, -1, 28, -1, -1, 83, -1,
- 85, -1, 35, 88, -1, -1, 91, 92, 93, 42,
- 95, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 105, 106, 107, 108, 1, -1, 3, 4, 5, 6,
- 7, 8, 9, 10, -1, 12, 13, 14, -1, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, -1, 33, -1, 35, -1,
- 37, 38, 95, 40, 41, 42, -1, -1, -1, 46,
- -1, -1, 49, 50, -1, -1, -1, -1, -1, -1,
- -1, 58, -1, -1, 61, -1, -1, -1, -1, -1,
- -1, -1, 69, 70, 71, -1, -1, -1, 75, 76,
- -1, -1, -1, -1, -1, -1, 83, -1, 85, -1,
- -1, 88, -1, -1, 91, 92, 93, -1, 95, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 105, 106,
- 107, 108, 1, -1, 3, 4, 5, 6, 7, 8,
- 9, 10, -1, 12, 13, 14, -1, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, -1, 33, -1, 35, -1, 37, 38,
- -1, 40, 41, 42, -1, -1, -1, 46, -1, -1,
- 49, 50, -1, -1, -1, -1, -1, -1, -1, 58,
- -1, -1, 61, -1, -1, -1, -1, -1, -1, -1,
- 69, 70, 71, -1, -1, -1, 75, 76, -1, -1,
- -1, -1, -1, -1, 83, -1, 85, -1, -1, 88,
- -1, -1, 91, 92, 93, -1, 95, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 105, 106, 107, 108,
- 1, -1, 3, 4, 5, 6, 7, 8, 9, 10,
- -1, 12, 13, 14, -1, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 31, -1, 33, -1, 35, -1, 37, 38, -1, 40,
- 41, 42, -1, -1, -1, 46, -1, -1, 49, 50,
- -1, -1, -1, -1, -1, -1, -1, 58, -1, -1,
- 61, -1, -1, -1, -1, -1, -1, -1, 69, 70,
- 71, -1, -1, -1, 75, 76, -1, -1, -1, -1,
- -1, -1, 83, -1, 85, -1, -1, 88, -1, -1,
- 91, 92, 93, -1, 95, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 105, 106, 107, 108, 1, -1,
- 3, 4, 5, 6, 7, 8, 9, 10, -1, 12,
- 13, 14, -1, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 27, 28, 29, 30, 31, -1,
- 33, -1, 35, -1, 37, 38, -1, 40, 41, 42,
- -1, -1, -1, 46, -1, -1, 49, 50, -1, -1,
- -1, -1, -1, -1, -1, 58, -1, -1, 61, -1,
- -1, -1, -1, -1, -1, -1, 69, 70, 71, -1,
- -1, -1, 75, 76, -1, -1, -1, -1, -1, -1,
- 83, -1, 85, -1, -1, 88, -1, -1, 91, 92,
- 93, -1, 95, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 105, 106, 107, 108, 1, -1, 3, 4,
- 5, 6, 7, 8, 9, 10, -1, 12, 13, 14,
- -1, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, -1, 33, -1,
- 35, -1, 37, 38, -1, 40, 41, 42, -1, -1,
- -1, 46, -1, -1, 49, 50, -1, -1, -1, -1,
- -1, -1, -1, 58, -1, -1, 61, -1, -1, -1,
- -1, -1, -1, -1, 69, 70, 71, -1, -1, -1,
- 75, 76, -1, -1, -1, -1, -1, -1, 83, -1,
- 85, -1, -1, 88, -1, -1, 91, 92, 93, -1,
- 95, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 105, 106, 107, 108, 1, -1, 3, 4, 5, 6,
- 7, 8, 9, 10, -1, 12, 13, 14, -1, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, -1, 33, -1, 35, -1,
- 37, 38, -1, 40, 41, 42, -1, -1, -1, 46,
- -1, -1, 49, 50, -1, -1, -1, -1, -1, -1,
- -1, 58, -1, -1, 61, -1, -1, -1, -1, -1,
- -1, -1, 69, 70, 71, -1, -1, -1, 75, 76,
- -1, -1, -1, -1, -1, -1, 83, -1, 85, -1,
- -1, 88, -1, -1, 91, 92, 93, -1, 95, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 105, -1,
- 107, 108, 1, -1, 3, 4, 5, 6, 7, 8,
- 9, 10, -1, 12, 13, 14, -1, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, -1, 33, -1, 35, -1, 37, 38,
- -1, 40, 41, 42, -1, -1, -1, 46, -1, -1,
- 49, 50, -1, -1, -1, -1, -1, 4, 5, 58,
- 7, 8, 61, -1, -1, -1, 13, -1, -1, -1,
- 69, 70, 71, -1, -1, -1, 75, 76, -1, -1,
- -1, 28, -1, -1, 83, -1, 85, -1, 35, 88,
- -1, -1, 91, 92, 93, 42, 95, -1, -1, -1,
- -1, -1, 49, -1, -1, -1, 105, -1, 107, 108,
- 1, -1, 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 61, 62, 63, 64, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 83, 28, 29, 30,
- 31, -1, 33, -1, 35, -1, 37, 38, 95, 40,
- 41, 42, -1, -1, -1, 46, -1, -1, -1, -1,
- -1, -1, 4, 5, 6, 7, 8, 58, -1, -1,
- 61, 13, -1, -1, -1, -1, 3, 4, 69, 70,
- 71, -1, -1, -1, 75, 76, 28, -1, -1, -1,
- -1, -1, 83, 35, -1, -1, -1, -1, -1, -1,
- 42, -1, -1, 94, 95, -1, -1, -1, -1, -1,
- -1, -1, -1, 104, 41, -1, 107, 108, 1, 46,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, -1, -1, -1, 61, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 71, 28, 29, 30, 31, -1,
- 33, 78, 35, 95, 37, 38, 83, 40, 41, 42,
- -1, -1, -1, 46, -1, -1, -1, -1, 95, -1,
- 4, 5, 6, 7, 8, 58, -1, -1, 61, 13,
- 107, -1, -1, -1, 3, 4, 69, 70, 71, -1,
- -1, -1, 75, 76, 28, -1, -1, -1, -1, -1,
- 83, 35, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 94, 95, -1, -1, -1, -1, -1, -1, -1,
- -1, 104, 41, -1, 107, 108, 1, 46, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, -1,
- -1, -1, 61, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 71, 28, 29, 30, 31, -1, 33, 78,
- 35, 95, 37, 38, 83, 40, 41, 42, -1, -1,
- -1, 46, -1, -1, -1, -1, 95, -1, -1, -1,
- -1, -1, -1, 58, -1, -1, 61, -1, 107, -1,
- -1, -1, 3, 4, 69, 70, 71, -1, -1, -1,
- 75, 76, -1, -1, -1, -1, -1, -1, 83, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 94,
- 95, -1, -1, -1, -1, -1, -1, -1, -1, 104,
- 41, -1, 107, 108, 1, 46, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, -1, -1, -1,
- 61, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 71, 28, 29, 30, 31, -1, 33, -1, 35, -1,
- 37, 38, 83, 40, 41, 42, -1, -1, -1, 46,
- -1, -1, -1, -1, 95, -1, -1, -1, -1, -1,
- -1, 58, -1, -1, 61, -1, 107, -1, -1, -1,
- -1, -1, 69, 70, 71, -1, -1, -1, 75, 76,
- -1, -1, -1, -1, -1, -1, 83, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 94, 95, -1,
- -1, -1, -1, -1, -1, -1, -1, 104, -1, -1,
- 107, 108, 1, -1, 3, 4, 5, 6, 7, 8,
- 9, 10, 11, 12, 13, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 70, 71, 72, 73, 28,
- 29, 30, 31, -1, 33, -1, 35, -1, 37, 38,
- -1, 40, 41, 42, -1, -1, -1, 46, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 58,
- -1, -1, 61, -1, -1, -1, -1, -1, -1, -1,
- 69, 70, 71, -1, -1, -1, 75, 76, -1, -1,
- -1, -1, -1, -1, 83, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 94, 95, -1, -1, -1,
- -1, -1, -1, -1, -1, 104, -1, -1, 107, 108,
- 1, -1, 3, 4, 5, -1, 7, 8, 9, 10,
- -1, 12, 13, 62, 63, 64, 65, 66, 67, 68,
- 69, 70, 71, 72, 73, -1, -1, 28, 29, 30,
- 31, -1, 33, -1, 35, -1, 37, 38, -1, 40,
- 41, 42, -1, -1, -1, 46, -1, -1, -1, 50,
- -1, -1, -1, -1, -1, -1, -1, 58, -1, -1,
- 61, -1, -1, -1, -1, -1, -1, -1, 69, 70,
- 71, -1, -1, -1, 75, 76, -1, -1, -1, -1,
- -1, -1, 83, 84, 1, -1, 3, 4, 5, -1,
- 7, 8, 9, 10, 95, 12, 13, -1, -1, -1,
- -1, -1, -1, 20, -1, 106, 107, 108, -1, -1,
- -1, 28, 29, 30, 31, -1, 33, -1, 35, -1,
- 37, 38, -1, 40, 41, 42, -1, -1, -1, 46,
- -1, -1, -1, 50, -1, -1, -1, -1, -1, -1,
- -1, 58, -1, -1, 61, -1, -1, -1, -1, -1,
- -1, -1, 69, 70, 71, -1, -1, -1, 75, 76,
- -1, -1, -1, -1, -1, 1, 83, 3, 4, 5,
- 6, 7, 8, 9, 10, -1, 12, 13, 95, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 106,
- 107, 108, 28, 29, 30, 31, -1, 33, -1, 35,
- -1, 37, 38, -1, 40, 41, 42, -1, -1, -1,
- 46, -1, -1, -1, 50, -1, -1, -1, -1, -1,
- -1, -1, 58, -1, -1, 61, -1, -1, -1, -1,
- -1, -1, -1, 69, 70, 71, -1, -1, -1, 75,
- 76, -1, -1, -1, -1, -1, 1, 83, 3, 4,
- 5, -1, 7, 8, 9, 10, -1, 12, 13, 95,
- -1, -1, -1, -1, -1, 20, -1, -1, -1, 105,
- -1, 107, 108, 28, 29, 30, 31, -1, 33, -1,
- 35, -1, 37, 38, -1, 40, 41, 42, -1, -1,
- -1, 46, -1, -1, -1, 50, -1, -1, -1, -1,
- -1, -1, -1, 58, -1, -1, 61, -1, -1, -1,
- -1, -1, -1, -1, 69, 70, 71, -1, -1, -1,
- 75, 76, -1, -1, -1, -1, -1, 1, 83, 3,
- 4, 5, -1, 7, 8, 9, 10, -1, 12, 13,
- 95, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 106, 107, 108, 28, 29, 30, 31, -1, 33,
- -1, 35, -1, 37, 38, -1, 40, 41, 42, -1,
- -1, -1, 46, -1, -1, -1, 50, -1, -1, -1,
- -1, -1, -1, -1, 58, -1, -1, 61, -1, -1,
- -1, -1, -1, -1, -1, 69, 70, 71, -1, -1,
- -1, 75, 76, -1, -1, -1, -1, -1, -1, 83,
- 84, 1, -1, 3, 4, 5, -1, 7, 8, 9,
- 10, 95, 12, 13, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 107, 108, -1, -1, -1, 28, 29,
- 30, 31, -1, 33, -1, 35, -1, 37, 38, -1,
- 40, 41, 42, -1, -1, -1, 46, -1, -1, -1,
- 50, -1, -1, -1, -1, -1, -1, -1, 58, -1,
- -1, 61, -1, -1, -1, -1, -1, -1, -1, 69,
- 70, 71, -1, -1, -1, 75, 76, -1, -1, -1,
- -1, -1, 1, 83, 3, 4, 5, -1, 7, 8,
- 9, 10, -1, 12, 13, 95, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 107, 108, 28,
- 29, 30, 31, -1, 33, -1, 35, -1, 37, 38,
- -1, 40, 41, 42, -1, -1, -1, 46, -1, -1,
- -1, 50, -1, -1, -1, -1, -1, -1, -1, 58,
- -1, -1, 61, -1, -1, -1, -1, -1, -1, -1,
- 69, 70, 71, -1, -1, -1, 75, 76, -1, -1,
- -1, -1, -1, 1, 83, 3, 4, 5, -1, 7,
- 8, 9, 10, -1, 12, 13, 95, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 107, 108,
- 28, 29, 30, 31, -1, 33, -1, 35, -1, 37,
- 38, -1, 40, 41, 42, -1, -1, -1, 46, -1,
- -1, -1, -1, -1, -1, -1, -1, 55, -1, -1,
- 58, -1, -1, 61, -1, -1, -1, -1, -1, -1,
- -1, 69, 70, 71, -1, -1, -1, 75, 76, -1,
- -1, -1, -1, -1, 1, 83, 3, 4, 5, -1,
- 7, 8, 9, 10, -1, 12, 13, 95, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 107,
- 108, 28, 29, 30, 31, -1, 33, -1, 35, -1,
- 37, 38, -1, 40, 41, 42, -1, -1, -1, 46,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 58, -1, -1, 61, -1, -1, -1, -1, -1,
- -1, -1, 69, 70, 71, -1, -1, -1, 75, 76,
- -1, -1, -1, -1, -1, 1, 83, 3, 4, 5,
- -1, 7, 8, 9, 10, -1, 12, 13, 95, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 105, -1,
- 107, 108, 28, 29, 30, 31, -1, 33, -1, 35,
- -1, 37, 38, -1, 40, 41, 42, -1, -1, -1,
- 46, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 58, -1, -1, 61, -1, -1, -1, -1,
- -1, -1, -1, 69, 70, 71, -1, -1, -1, 75,
- 76, -1, -1, -1, -1, -1, 1, 83, 3, 4,
- 5, -1, 7, 8, 9, 10, -1, 12, 13, 95,
- -1, -1, -1, -1, -1, -1, -1, -1, 104, -1,
- -1, 107, 108, 28, 29, 30, 31, -1, 33, -1,
- 35, -1, 37, 38, -1, 40, 41, 42, -1, -1,
- -1, 46, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 58, -1, -1, 61, -1, -1, -1,
- -1, -1, -1, -1, 69, 70, 71, -1, -1, -1,
- 75, 76, -1, -1, -1, -1, -1, -1, 83, 3,
- 4, 5, -1, 7, 8, 9, 10, -1, 12, 13,
- 95, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 107, 108, 28, 29, 30, 31, -1, 33,
- -1, 35, -1, 37, -1, -1, 40, 41, 42, -1,
- -1, 1, 46, 3, 4, 5, 6, 7, 8, -1,
- -1, -1, -1, 13, 58, -1, -1, 61, -1, -1,
- -1, -1, -1, -1, -1, 69, 70, 71, 28, -1,
- -1, 75, 76, -1, -1, 35, 36, -1, -1, 83,
- -1, 41, 42, -1, -1, -1, 46, -1, -1, -1,
- -1, 95, -1, -1, -1, 55, -1, -1, -1, -1,
- -1, 61, -1, 107, 108, 109, -1, -1, -1, -1,
- 1, 71, 3, 4, 5, 6, 7, 8, -1, -1,
- -1, -1, 13, 83, -1, -1, 1, -1, 3, 4,
- 5, 6, 7, 8, -1, 95, -1, 28, 13, -1,
- -1, -1, -1, -1, 35, 36, 106, 107, -1, -1,
- 41, 42, -1, 28, -1, 46, -1, -1, -1, -1,
- 35, -1, -1, -1, 55, -1, 41, 42, -1, -1,
- 61, 46, -1, -1, -1, -1, -1, -1, -1, -1,
- 71, -1, -1, -1, -1, -1, 61, -1, -1, -1,
- -1, -1, 83, -1, -1, -1, 71, -1, -1, -1,
- -1, -1, -1, -1, 95, -1, -1, -1, 83, -1,
- -1, -1, -1, -1, -1, 106, 107, -1, -1, -1,
- 95, 96, -1, -1, -1, -1, -1, -1, -1, -1,
- 105, -1, 107, 3, 4, 5, 6, 7, 8, 9,
- 10, -1, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, -1, 33, -1, 35, -1, 37, -1, -1,
- 40, 41, 42, -1, -1, -1, 46, -1, -1, 49,
- 50, -1, -1, -1, -1, -1, -1, -1, 58, -1,
- -1, 61, -1, -1, -1, -1, -1, -1, -1, 69,
- 70, 71, -1, -1, -1, 75, 76, -1, -1, -1,
- -1, -1, -1, 83, -1, 85, -1, -1, 88, -1,
- -1, 91, 92, 93, -1, 95, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 105, 106, 107, 108, 3,
- 4, 5, 6, 7, 8, 9, 10, -1, 12, 13,
- 14, -1, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, -1, 33,
- -1, 35, -1, 37, -1, -1, 40, 41, 42, -1,
- -1, -1, 46, -1, -1, 49, 50, -1, -1, -1,
- -1, -1, -1, -1, 58, -1, -1, 61, -1, -1,
- -1, -1, -1, -1, -1, 69, 70, 71, -1, -1,
- -1, 75, 76, -1, -1, -1, -1, -1, -1, 83,
- -1, 85, -1, -1, 88, -1, -1, 91, 92, 93,
- -1, 95, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 105, -1, 107, 108, 3, 4, 5, 6, 7,
- 8, 9, 10, -1, 12, 13, 14, -1, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, -1, 33, -1, 35, -1, 37,
- -1, -1, 40, 41, 42, -1, -1, -1, 46, -1,
- -1, 49, -1, -1, -1, -1, -1, -1, -1, -1,
- 58, -1, -1, 61, -1, -1, -1, -1, -1, -1,
- -1, 69, 70, 71, -1, -1, -1, 75, 76, -1,
- -1, -1, -1, -1, -1, 83, -1, 85, -1, -1,
- 88, -1, -1, 91, 92, 93, -1, 95, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 105, -1, 107,
- 108, 3, 4, 5, -1, 7, 8, 9, 10, -1,
- 12, 13, 4, 5, 6, 7, 8, -1, -1, 11,
- -1, 13, -1, -1, -1, -1, 28, 29, 30, 31,
- -1, 33, -1, 35, -1, 37, 28, -1, 40, 41,
- 42, -1, -1, 35, 46, 3, 4, 5, -1, 7,
- 42, -1, -1, -1, -1, 13, 58, -1, -1, 61,
- -1, -1, -1, -1, -1, -1, -1, 69, 70, 71,
- 28, -1, -1, 75, 76, -1, -1, 35, -1, 37,
- -1, 83, 84, 41, 42, 3, 4, 5, 46, 7,
- 8, 9, 10, 95, 12, 13, -1, -1, -1, -1,
- -1, -1, 94, 95, -1, 107, 108, -1, -1, -1,
- 28, 29, 30, 31, -1, 33, -1, 35, -1, 37,
- -1, -1, 40, 41, 42, -1, -1, -1, 46, -1,
- -1, -1, 50, -1, -1, -1, -1, 95, -1, -1,
- 58, -1, -1, 61, -1, -1, -1, -1, -1, -1,
- -1, 69, 70, 71, -1, -1, -1, 75, 76, -1,
- -1, -1, -1, -1, -1, 83, 3, 4, 5, -1,
- 7, 8, 9, 10, -1, 12, 13, 95, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 107,
- 108, 28, 29, 30, 31, -1, 33, -1, 35, -1,
- 37, -1, -1, 40, 41, 42, -1, -1, -1, 46,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 58, -1, -1, 61, -1, -1, -1, -1, -1,
- -1, -1, 69, 70, 71, -1, -1, -1, 75, 76,
- -1, -1, -1, -1, -1, -1, 83, 3, 4, 5,
- -1, 7, 8, 9, 10, -1, 12, 13, 95, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 105, -1,
- 107, 108, 28, 29, 30, 31, -1, 33, -1, 35,
- -1, 37, -1, -1, 40, 41, 42, -1, -1, -1,
- 46, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 58, -1, -1, 61, -1, -1, -1, -1,
- -1, -1, -1, 69, 70, 71, -1, -1, -1, 75,
- 76, -1, -1, -1, -1, -1, -1, 83, 3, 4,
- 5, -1, 7, 8, 9, 10, -1, 12, 13, 95,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 105,
- -1, 107, 108, 28, 29, 30, 31, -1, 33, -1,
- 35, -1, 37, -1, -1, 40, 41, 42, -1, -1,
- -1, 46, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 58, -1, -1, 61, -1, -1, -1,
- -1, -1, -1, -1, 69, 70, 71, -1, -1, -1,
- 75, 76, -1, -1, -1, -1, -1, -1, 83, 3,
- 4, 5, -1, 7, 8, 9, 10, -1, 12, 13,
- 95, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 107, 108, 28, 29, 30, 31, -1, 33,
- -1, 35, -1, 37, -1, -1, 40, 41, 42, -1,
- -1, -1, 46, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 58, -1, -1, 61, -1, -1,
- -1, -1, -1, -1, -1, 69, 70, 71, -1, -1,
- -1, 75, 76, -1, -1, -1, -1, -1, -1, 83,
- 3, 4, 5, -1, 7, 8, 9, 10, -1, 12,
- 13, 95, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 107, 108, 28, 29, 30, 31, -1,
- 33, -1, 35, -1, 37, -1, -1, 40, 41, 42,
- -1, -1, -1, 46, 3, 4, 5, -1, 7, 8,
- 9, 10, -1, 12, 13, 58, -1, -1, 61, -1,
- -1, -1, -1, -1, -1, -1, 69, 70, 71, 28,
- 29, -1, 75, 76, 33, -1, 35, -1, 37, -1,
- 83, 40, 41, 42, -1, -1, -1, 46, -1, -1,
- -1, -1, 95, -1, -1, -1, -1, -1, -1, 58,
- -1, -1, 61, -1, 107, 108, -1, -1, -1, -1,
- 69, 70, 71, -1, -1, -1, 75, 76, -1, -1,
- -1, 3, 4, 5, 83, 7, 8, 9, 10, -1,
- 12, 13, -1, -1, -1, -1, 95, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 28, 29, 107, 108,
- -1, 33, -1, 35, -1, 37, -1, -1, 40, 41,
- 42, -1, -1, -1, 46, 3, 4, 5, 6, 7,
- 8, -1, -1, -1, -1, 13, 58, -1, -1, 61,
- -1, -1, -1, -1, -1, -1, -1, 69, 70, 71,
- 28, -1, -1, 75, 76, -1, -1, 35, -1, -1,
- -1, 83, -1, 41, 42, -1, 44, -1, 46, 47,
- -1, 49, -1, 95, -1, -1, -1, 55, -1, -1,
- -1, -1, -1, 61, -1, 107, 108, 3, 4, 5,
- 6, 7, 8, 71, -1, 11, -1, 13, -1, -1,
- 78, -1, -1, -1, -1, 83, -1, -1, -1, -1,
- -1, -1, 28, -1, -1, -1, -1, 95, -1, 35,
- -1, -1, -1, -1, -1, 41, 42, -1, 44, 107,
- 46, 47, 3, 4, 5, 6, 7, 8, -1, -1,
- 11, -1, 13, -1, -1, 61, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 71, -1, 28, -1, -1,
- -1, -1, 78, -1, 35, -1, -1, 83, 84, -1,
- 41, 42, -1, 44, -1, 46, -1, -1, -1, 95,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 61, 107, -1, -1, 3, 4, 5, 6, 7, 8,
- 71, -1, 11, -1, 13, -1, -1, 78, -1, -1,
- -1, -1, 83, 84, -1, -1, -1, -1, -1, 28,
- -1, -1, -1, 94, 95, -1, 35, -1, -1, -1,
- -1, -1, 41, 42, -1, -1, 107, 46, 3, 4,
- 5, 6, 7, 8, -1, -1, -1, -1, 13, -1,
- -1, -1, 61, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 71, 28, 4, 5, 6, 7, 8, 78,
- 35, 11, -1, 13, 83, -1, 41, 42, -1, -1,
- -1, 46, 47, -1, -1, 94, 95, -1, 28, -1,
- -1, -1, -1, -1, -1, 35, 61, -1, 107, -1,
- -1, -1, 42, -1, 44, -1, 71, -1, 4, 5,
- -1, 7, 8, 78, -1, -1, -1, 13, 83, -1,
- -1, 61, -1, -1, -1, -1, -1, -1, -1, -1,
- 95, 71, 28, -1, -1, -1, -1, -1, 78, 35,
- 105, -1, 107, 83, 84, -1, 42, -1, 44, -1,
- -1, 47, -1, -1, 94, 95, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 61, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 71, -1, -1, -1, -1,
- -1, -1, 78, -1, -1, -1, -1, 83, 84, -1,
- -1, -1, -1, -1, -1, 52, 53, 54, -1, 95,
- 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
- 67, 68, 69, 70, 71, 72, 73, 52, 53, 54,
- -1, -1, 57, 58, 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 70, 71, 72, 73, -1,
- -1, -1, -1, -1, -1, -1, -1, 32, -1, -1,
- -1, -1, 109, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 52, 53, 54,
- 105, 106, 57, 58, 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 70, 71, 72, 73, 51,
- 52, 53, 54, -1, -1, 57, 58, 59, 60, 61,
- 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 52, 53, 54, 55, -1, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- 70, 71, 72, 73, 52, 53, 54, -1, -1, 57,
- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 52, 53, 54, -1,
- -1, 57, 58, 59, 60, 61, 62, 63, 64, 65,
- -1, 67, 68, 69, 70, 71, 72, 73, 54, -1,
- -1, 57, 58, 59, 60, 61, 62, 63, 64, 65,
- 66, 67, 68, 69, 70, 71, 72, 73, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- 70, 71, 72, 73, 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 70, 71, 72, 73
-};
-/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
-#line 3 "bison.simple"
-
-/* Skeleton output parser for bison,
- Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
-
- This program 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 1, or (at your option)
- any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
-#ifndef alloca
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else /* not GNU C. */
-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
-#include <alloca.h>
-#else /* not sparc */
-#if defined (MSDOS) && !defined (__TURBOC__)
-#include <malloc.h>
-#else /* not MSDOS, or __TURBOC__ */
-#if defined(_AIX)
-#include <malloc.h>
- #pragma alloca
-#endif /* not _AIX */
-#endif /* not MSDOS, or __TURBOC__ */
-#endif /* not sparc. */
-#endif /* not GNU C. */
-#endif /* alloca not defined. */
-
-/* This is the parser code that is written into each bison parser
- when the %semantic_parser declaration is not specified in the grammar.
- It was written by Richard Stallman by simplifying the hairy parser
- used when %semantic_parser is specified. */
-
-/* Note: there must be only one dollar sign in this file.
- It is replaced by the list of actions, each action
- as one case of the switch. */
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY -2
-#define YYEOF 0
-#define YYACCEPT return(0)
-#define YYABORT return(1)
-#define YYERROR goto yyerrlab1
-/* Like YYERROR except do call yyerror.
- This remains here temporarily to ease the
- transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
-#define YYFAIL goto yyerrlab
-#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(token, value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { yychar = (token), yylval = (value); \
- yychar1 = YYTRANSLATE (yychar); \
- YYPOPSTACK; \
- goto yybackup; \
- } \
- else \
- { yyerror ("syntax error: cannot back up"); YYERROR; } \
-while (0)
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-#ifndef YYPURE
-#define YYLEX yylex()
-#endif
-
-#ifdef YYPURE
-#ifdef YYLSP_NEEDED
-#define YYLEX yylex(&yylval, &yylloc)
-#else
-#define YYLEX yylex(&yylval)
-#endif
-#endif
-
-/* If nonreentrant, generate the variables here */
-
-#ifndef YYPURE
-
-int yychar; /* the lookahead symbol */
-YYSTYPE yylval; /* the semantic value of the */
- /* lookahead symbol */
-
-#ifdef YYLSP_NEEDED
-YYLTYPE yylloc; /* location data for the lookahead */
- /* symbol */
-#endif
-
-int yynerrs; /* number of parse errors so far */
-#endif /* not YYPURE */
-
-#if YYDEBUG != 0
-int yydebug; /* nonzero means print parse trace */
-/* Since this is uninitialized, it does not stop multiple parsers
- from coexisting. */
-#endif
-
-/* YYINITDEPTH indicates the initial size of the parser's stacks */
-
-#ifndef YYINITDEPTH
-#define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH is the maximum size the stacks can grow to
- (effective only if the built-in stack extension method is used). */
-
-#if YYMAXDEPTH == 0
-#undef YYMAXDEPTH
-#endif
-
-#ifndef YYMAXDEPTH
-#define YYMAXDEPTH 10000
-#endif
-
-#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
-#define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
-#else /* not GNU C or C++ */
-#ifndef __cplusplus
-
-/* This is the most reliable way to avoid incompatibilities
- in available built-in functions on various systems. */
-static void
-__yy_bcopy (from, to, count)
- char *from;
- char *to;
- int count;
-{
- register char *f = from;
- register char *t = to;
- register int i = count;
-
- while (i-- > 0)
- *t++ = *f++;
-}
-
-#else /* __cplusplus */
-
-/* This is the most reliable way to avoid incompatibilities
- in available built-in functions on various systems. */
-static void
-__yy_bcopy (char *from, char *to, int count)
-{
- register char *f = from;
- register char *t = to;
- register int i = count;
-
- while (i-- > 0)
- *t++ = *f++;
-}
-
-#endif
-#endif
-
-#line 169 "bison.simple"
-int
-yyparse()
-{
- register int yystate;
- register int yyn;
- register short *yyssp;
- register YYSTYPE *yyvsp;
- int yyerrstatus; /* number of tokens to shift before error messages enabled */
- int yychar1; /* lookahead token as an internal (translated) token number */
-
- short yyssa[YYINITDEPTH]; /* the state stack */
- YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
-
- short *yyss = yyssa; /* refer to the stacks thru separate pointers */
- YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
-
-#ifdef YYLSP_NEEDED
- YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
- YYLTYPE *yyls = yylsa;
- YYLTYPE *yylsp;
-
-#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
-#else
-#define YYPOPSTACK (yyvsp--, yyssp--)
-#endif
-
- int yystacksize = YYINITDEPTH;
-
-#ifdef YYPURE
- int yychar;
- YYSTYPE yylval;
- int yynerrs;
-#ifdef YYLSP_NEEDED
- YYLTYPE yylloc;
-#endif
-#endif
-
- YYSTYPE yyval; /* the variable used to return */
- /* semantic values from the action */
- /* routines */
-
- int yylen;
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Starting parse\n");
-#endif
-
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack. */
-
- yyssp = yyss - 1;
- yyvsp = yyvs;
-#ifdef YYLSP_NEEDED
- yylsp = yyls;
-#endif
-
-/* Push a new state, which is found in yystate . */
-/* In all cases, when you get here, the value and location stacks
- have just been pushed. so pushing a state here evens the stacks. */
-yynewstate:
-
- *++yyssp = yystate;
-
- if (yyssp >= yyss + yystacksize - 1)
- {
- /* Give user a chance to reallocate the stack */
- /* Use copies of these so that the &'s don't force the real ones into memory. */
- YYSTYPE *yyvs1 = yyvs;
- short *yyss1 = yyss;
-#ifdef YYLSP_NEEDED
- YYLTYPE *yyls1 = yyls;
-#endif
-
- /* Get the current used size of the three stacks, in elements. */
- int size = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- /* Each stack pointer address is followed by the size of
- the data in use in that stack, in bytes. */
- yyoverflow("parser stack overflow",
- &yyss1, size * sizeof (*yyssp),
- &yyvs1, size * sizeof (*yyvsp),
-#ifdef YYLSP_NEEDED
- &yyls1, size * sizeof (*yylsp),
-#endif
- &yystacksize);
-
- yyss = yyss1; yyvs = yyvs1;
-#ifdef YYLSP_NEEDED
- yyls = yyls1;
-#endif
-#else /* no yyoverflow */
- /* Extend the stack our own way. */
- if (yystacksize >= YYMAXDEPTH)
- {
- yyerror("parser stack overflow");
- return 2;
- }
- yystacksize *= 2;
- if (yystacksize > YYMAXDEPTH)
- yystacksize = YYMAXDEPTH;
- yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
- __yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
- yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
- __yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
-#ifdef YYLSP_NEEDED
- yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
- __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
-#endif
-#endif /* no yyoverflow */
-
- yyssp = yyss + size - 1;
- yyvsp = yyvs + size - 1;
-#ifdef YYLSP_NEEDED
- yylsp = yyls + size - 1;
-#endif
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Stack size increased to %d\n", yystacksize);
-#endif
-
- if (yyssp >= yyss + yystacksize - 1)
- YYABORT;
- }
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Entering state %d\n", yystate);
-#endif
-
- yybackup:
-
-/* Do appropriate processing given the current state. */
-/* Read a lookahead token if we need one and don't already have one. */
-/* yyresume: */
-
- /* First try to decide what to do without reference to lookahead token. */
-
- yyn = yypact[yystate];
- if (yyn == YYFLAG)
- goto yydefault;
-
- /* Not known => get a lookahead token if don't already have one. */
-
- /* yychar is either YYEMPTY or YYEOF
- or a valid token in external form. */
-
- if (yychar == YYEMPTY)
- {
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Reading a token: ");
-#endif
- yychar = YYLEX;
- }
-
- /* Convert token to internal form (in yychar1) for indexing tables with */
-
- if (yychar <= 0) /* This means end of input. */
- {
- yychar1 = 0;
- yychar = YYEOF; /* Don't call YYLEX any more */
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Now at end of input.\n");
-#endif
- }
- else
- {
- yychar1 = YYTRANSLATE(yychar);
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
- /* Give the individual parser a way to print the precise meaning
- of a token, for further debugging info. */
-#ifdef YYPRINT
- YYPRINT (stderr, yychar, yylval);
-#endif
- fprintf (stderr, ")\n");
- }
-#endif
- }
-
- yyn += yychar1;
- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
- goto yydefault;
-
- yyn = yytable[yyn];
-
- /* yyn is what to do for this token type in this state.
- Negative => reduce, -yyn is rule number.
- Positive => shift, yyn is new state.
- New state is final state => don't bother to shift,
- just return success.
- 0, or most negative number => error. */
-
- if (yyn < 0)
- {
- if (yyn == YYFLAG)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
- else if (yyn == 0)
- goto yyerrlab;
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- /* Shift the lookahead token. */
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
-#endif
-
- /* Discard the token being shifted unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- *++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
- *++yylsp = yylloc;
-#endif
-
- /* count tokens shifted since error; after three, turn off error status. */
- if (yyerrstatus) yyerrstatus--;
-
- yystate = yyn;
- goto yynewstate;
-
-/* Do the default action for the current state. */
-yydefault:
-
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
-
-/* Do a reduction. yyn is the number of a rule to reduce with. */
-yyreduce:
- yylen = yyr2[yyn];
- yyval = yyvsp[1-yylen]; /* implement default value of the action */
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- int i;
-
- fprintf (stderr, "Reducing via rule %d (line %d), ",
- yyn, yyrline[yyn]);
-
- /* Print the symboles being reduced, and their result. */
- for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
- fprintf (stderr, "%s ", yytname[yyrhs[i]]);
- fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
- }
-#endif
-
-
- switch (yyn) {
-
-case 2:
-#line 285 "cp-parse.y"
-{ finish_file (); ;
- break;}
-case 3:
-#line 293 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 4:
-#line 294 "cp-parse.y"
-{yyval.ttype = NULL_TREE; ;
- break;}
-case 5:
-#line 296 "cp-parse.y"
-{yyval.ttype = NULL_TREE; ;
- break;}
-case 6:
-#line 300 "cp-parse.y"
-{ have_extern_spec = 1;
- used_extern_spec = 0;
- yyval.ttype = NULL_TREE; ;
- break;}
-case 7:
-#line 305 "cp-parse.y"
-{ have_extern_spec = 0; ;
- break;}
-case 8:
-#line 309 "cp-parse.y"
-{ if (pedantic)
- pedwarn ("ANSI C++ forbids use of `asm' keyword"); ;
- break;}
-case 10:
-#line 316 "cp-parse.y"
-{ if (pending_inlines) do_pending_inlines (); ;
- break;}
-case 11:
-#line 318 "cp-parse.y"
-{ if (pending_inlines) do_pending_inlines (); ;
- break;}
-case 12:
-#line 320 "cp-parse.y"
-{ if (pending_inlines) do_pending_inlines (); ;
- break;}
-case 14:
-#line 323 "cp-parse.y"
-{ if (TREE_CHAIN (yyvsp[-2].ttype)) yyvsp[-2].ttype = combine_strings (yyvsp[-2].ttype);
- assemble_asm (yyvsp[-2].ttype); ;
- break;}
-case 15:
-#line 326 "cp-parse.y"
-{ pop_lang_context (); ;
- break;}
-case 16:
-#line 328 "cp-parse.y"
-{ pop_lang_context (); ;
- break;}
-case 17:
-#line 330 "cp-parse.y"
-{ if (pending_inlines) do_pending_inlines ();
- pop_lang_context (); ;
- break;}
-case 18:
-#line 333 "cp-parse.y"
-{ if (pending_inlines) do_pending_inlines ();
- pop_lang_context (); ;
- break;}
-case 19:
-#line 339 "cp-parse.y"
-{ push_lang_context (yyvsp[0].ttype); ;
- break;}
-case 20:
-#line 344 "cp-parse.y"
-{ begin_template_parm_list (); ;
- break;}
-case 21:
-#line 346 "cp-parse.y"
-{ yyval.ttype = end_template_parm_list (yyvsp[-1].ttype); ;
- break;}
-case 22:
-#line 351 "cp-parse.y"
-{ yyval.ttype = process_template_parm (NULL_TREE, yyvsp[0].ttype); ;
- break;}
-case 23:
-#line 353 "cp-parse.y"
-{ yyval.ttype = process_template_parm (yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 24:
-#line 364 "cp-parse.y"
-{
- if (yyvsp[-1].ttype != class_type_node)
- error ("template type parameter must use keyword `class'");
- yyval.ttype = build_tree_list (yyvsp[0].ttype, NULL_TREE);
- ;
- break;}
-case 25:
-#line 370 "cp-parse.y"
-{
- if (yyvsp[-3].ttype != class_type_node)
- error ("template type parameter must use keyword `class'");
- warning ("restricted template type parameters not yet implemented");
- yyval.ttype = build_tree_list (yyvsp[-2].ttype, yyvsp[0].ttype);
- ;
- break;}
-case 26:
-#line 377 "cp-parse.y"
-{
- if (yyvsp[-2].ttype != class_type_node)
- error ("template type parameter must use keyword `class'");
- warning ("restricted template type parameters not yet implemented");
- yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype);
- ;
- break;}
-case 28:
-#line 388 "cp-parse.y"
-{ warning ("use of `overload' is an anachronism"); ;
- break;}
-case 29:
-#line 392 "cp-parse.y"
-{ declare_overloaded (yyvsp[0].ttype); ;
- break;}
-case 30:
-#line 394 "cp-parse.y"
-{ declare_overloaded (yyvsp[0].ttype); ;
- break;}
-case 31:
-#line 401 "cp-parse.y"
-{ yychar = '{'; goto template1; ;
- break;}
-case 33:
-#line 404 "cp-parse.y"
-{ yychar = '{'; goto template1; ;
- break;}
-case 35:
-#line 407 "cp-parse.y"
-{ yychar = ':'; goto template1; ;
- break;}
-case 37:
-#line 410 "cp-parse.y"
-{
- yychar = ':';
- template1:
- if (current_aggr == exception_type_node)
- error ("template type must define an aggregate or union");
- /* Maybe pedantic warning for union?
- How about an enum? :-) */
- end_template_decl (yyvsp[-2].ttype, yyvsp[-1].ttype, current_aggr);
- reinit_parse_for_template (yychar, yyvsp[-2].ttype, yyvsp[-1].ttype);
- yychar = YYEMPTY;
- ;
- break;}
-case 39:
-#line 423 "cp-parse.y"
-{
- end_template_decl (yyvsp[-2].ttype, yyvsp[-1].ttype, current_aggr);
- /* declare $2 as template name with $1 parm list */
- ;
- break;}
-case 40:
-#line 428 "cp-parse.y"
-{
- end_template_decl (yyvsp[-2].ttype, yyvsp[-1].ttype, current_aggr);
- /* declare $2 as template name with $1 parm list */
- ;
- break;}
-case 41:
-#line 435 "cp-parse.y"
-{
- tree d;
- int momentary;
- momentary = suspend_momentary ();
- d = start_decl (yyvsp[-4].ttype, /*current_declspecs*/NULL_TREE, 0, yyvsp[-3].ttype);
- cplus_decl_attributes (d, yyvsp[-1].ttype);
- finish_decl (d, NULL_TREE, yyvsp[-2].ttype, 0);
- end_template_decl (yyvsp[-5].ttype, d, 0);
- if (yyvsp[0].itype != ';')
- reinit_parse_for_template ((int) yyvsp[0].itype, yyvsp[-5].ttype, d);
- resume_momentary (momentary);
- ;
- break;}
-case 42:
-#line 450 "cp-parse.y"
-{
- tree d;
- int momentary;
-
- current_declspecs = yyvsp[-5].ttype;
- momentary = suspend_momentary ();
- d = start_decl (yyvsp[-4].ttype, current_declspecs,
- 0, yyvsp[-3].ttype);
- cplus_decl_attributes (d, yyvsp[-1].ttype);
- finish_decl (d, NULL_TREE, yyvsp[-2].ttype, 0);
- end_exception_decls ();
- end_template_decl (yyvsp[-6].ttype, d, 0);
- if (yyvsp[0].itype != ';')
- {
- reinit_parse_for_template ((int) yyvsp[0].itype, yyvsp[-6].ttype, d);
- yychar = YYEMPTY;
- }
- note_list_got_semicolon (yyvsp[-5].ttype);
- resume_momentary (momentary);
- ;
- break;}
-case 43:
-#line 471 "cp-parse.y"
-{
- tree d = start_decl (yyvsp[-1].ttype, yyvsp[-2].ttype, 0, NULL_TREE);
- finish_decl (d, NULL_TREE, NULL_TREE, 0);
- end_template_decl (yyvsp[-3].ttype, d, 0);
- if (yyvsp[0].itype != ';')
- reinit_parse_for_template ((int) yyvsp[0].itype, yyvsp[-3].ttype, d);
- ;
- break;}
-case 44:
-#line 479 "cp-parse.y"
-{ end_template_decl (yyvsp[-2].ttype, 0, 0); ;
- break;}
-case 45:
-#line 480 "cp-parse.y"
-{ end_template_decl (yyvsp[-2].ttype, 0, 0); ;
- break;}
-case 46:
-#line 483 "cp-parse.y"
-{ yyval.itype = '{'; ;
- break;}
-case 47:
-#line 484 "cp-parse.y"
-{ yyval.itype = ':'; ;
- break;}
-case 48:
-#line 485 "cp-parse.y"
-{ yyval.itype = ';'; ;
- break;}
-case 49:
-#line 486 "cp-parse.y"
-{ yyval.itype = '='; ;
- break;}
-case 50:
-#line 487 "cp-parse.y"
-{ yyval.itype = RETURN; ;
- break;}
-case 51:
-#line 492 "cp-parse.y"
-{ if (pedantic)
- pedwarn ("ANSI C++ forbids data definition with no type or storage class");
- else if (! flag_traditional && ! have_extern_spec)
- warning ("data definition has no type or storage class"); ;
- break;}
-case 52:
-#line 497 "cp-parse.y"
-{;
- break;}
-case 53:
-#line 500 "cp-parse.y"
-{ tree d;
- d = start_decl (yyvsp[-1].ttype, yyval.ttype, 0, NULL_TREE);
- finish_decl (d, NULL_TREE, NULL_TREE, 0);
- ;
- break;}
-case 54:
-#line 505 "cp-parse.y"
-{
- end_exception_decls ();
- note_list_got_semicolon (yyval.ttype);
- ;
- break;}
-case 55:
-#line 511 "cp-parse.y"
-{ tree d;
- d = start_decl (yyvsp[-1].ttype, yyval.ttype, 0, NULL_TREE);
- finish_decl (d, NULL_TREE, NULL_TREE, 0);
- end_exception_decls ();
- note_list_got_semicolon (yyval.ttype);
- ;
- break;}
-case 56:
-#line 518 "cp-parse.y"
-{ pedwarn ("empty declaration"); ;
- break;}
-case 57:
-#line 520 "cp-parse.y"
-{
- tree t = yyval.ttype;
- shadow_tag (t);
- if (TREE_CODE (t) == TREE_LIST
- && TREE_PURPOSE (t) == NULL_TREE)
- {
- t = TREE_VALUE (t);
- if (TREE_CODE (t) == RECORD_TYPE)
- {
- if (CLASSTYPE_USE_TEMPLATE (t) == 0)
- CLASSTYPE_USE_TEMPLATE (t) = 2;
- else if (CLASSTYPE_USE_TEMPLATE (t) == 1)
- error ("override declaration for already-expanded template");
- }
- }
- note_list_got_semicolon (yyval.ttype);
- ;
- break;}
-case 61:
-#line 544 "cp-parse.y"
-{
- finish_function (lineno, 1);
- /* finish_function performs these three statements:
-
- expand_end_bindings (getdecls (), 1, 0);
- poplevel (1, 1, 0);
-
- expand_end_bindings (0, 0, 0);
- poplevel (0, 0, 1);
- */
- if (yyval.ttype) process_next_inline (yyval.ttype);
- ;
- break;}
-case 62:
-#line 557 "cp-parse.y"
-{
- finish_function (lineno, 1);
- /* finish_function performs these three statements:
-
- expand_end_bindings (getdecls (), 1, 0);
- poplevel (1, 1, 0);
-
- expand_end_bindings (0, 0, 0);
- poplevel (0, 0, 1);
- */
- if (yyval.ttype) process_next_inline (yyval.ttype);
- ;
- break;}
-case 63:
-#line 570 "cp-parse.y"
-{ finish_function (lineno, 0);
- if (yyval.ttype) process_next_inline (yyval.ttype); ;
- break;}
-case 64:
-#line 573 "cp-parse.y"
-{ finish_function (lineno, 0);
- if (yyval.ttype) process_next_inline (yyval.ttype); ;
- break;}
-case 65:
-#line 576 "cp-parse.y"
-{ finish_function (lineno, 0);
- if (yyval.ttype) process_next_inline (yyval.ttype); ;
- break;}
-case 66:
-#line 579 "cp-parse.y"
-{;
- break;}
-case 67:
-#line 581 "cp-parse.y"
-{;
- break;}
-case 68:
-#line 583 "cp-parse.y"
-{;
- break;}
-case 69:
-#line 588 "cp-parse.y"
-{ if (! start_function (yyval.ttype, yyvsp[-1].ttype, yyvsp[0].ttype, 0))
- YYERROR1;
- reinit_parse_for_function ();
- yyval.ttype = NULL_TREE; ;
- break;}
-case 70:
-#line 593 "cp-parse.y"
-{ if (! start_function (yyval.ttype, yyvsp[-1].ttype, yyvsp[0].ttype, 0))
- YYERROR1;
- reinit_parse_for_function ();
- yyval.ttype = NULL_TREE; ;
- break;}
-case 71:
-#line 598 "cp-parse.y"
-{ if (! start_function (NULL_TREE, yyval.ttype, yyvsp[0].ttype, 0))
- YYERROR1;
- reinit_parse_for_function ();
- yyval.ttype = NULL_TREE; ;
- break;}
-case 72:
-#line 603 "cp-parse.y"
-{ if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, yyval.ttype, yyvsp[-3].ttype, yyvsp[-1].ttype), yyvsp[0].ttype, 0))
- YYERROR1;
- reinit_parse_for_function ();
- yyval.ttype = NULL_TREE; ;
- break;}
-case 73:
-#line 608 "cp-parse.y"
-{ if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, yyval.ttype, yyvsp[-3].ttype, yyvsp[-1].ttype), yyvsp[0].ttype, 0))
- YYERROR1;
- reinit_parse_for_function ();
- yyval.ttype = NULL_TREE; ;
- break;}
-case 74:
-#line 613 "cp-parse.y"
-{ if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, yyval.ttype, empty_parms (), yyvsp[-1].ttype), yyvsp[0].ttype, 0))
- YYERROR1;
- reinit_parse_for_function ();
- yyval.ttype = NULL_TREE; ;
- break;}
-case 75:
-#line 618 "cp-parse.y"
-{ if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, yyval.ttype, empty_parms (), yyvsp[-1].ttype), yyvsp[0].ttype, 0))
- YYERROR1;
- reinit_parse_for_function ();
- yyval.ttype = NULL_TREE; ;
- break;}
-case 76:
-#line 623 "cp-parse.y"
-{ start_function (NULL_TREE, TREE_VALUE (yyval.ttype), NULL_TREE, 1);
- reinit_parse_for_function (); ;
- break;}
-case 77:
-#line 630 "cp-parse.y"
-{
- tree decl = build_parse_node (CALL_EXPR, TREE_VALUE (yyval.ttype), yyvsp[-3].ttype, yyvsp[-1].ttype);
- yyval.ttype = start_method (TREE_CHAIN (yyval.ttype), decl, yyvsp[0].ttype);
- if (! yyval.ttype)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, yyval.ttype); ;
- break;}
-case 78:
-#line 639 "cp-parse.y"
-{
- tree decl = build_parse_node (CALL_EXPR, TREE_VALUE (yyval.ttype), empty_parms (), yyvsp[-1].ttype);
- yyval.ttype = start_method (TREE_CHAIN (yyval.ttype), decl, yyvsp[0].ttype);
- if (! yyval.ttype)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, yyval.ttype); ;
- break;}
-case 79:
-#line 648 "cp-parse.y"
-{ yyval.ttype = start_method (yyval.ttype, yyvsp[-1].ttype, yyvsp[0].ttype);
- if (! yyval.ttype)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, yyval.ttype); ;
- break;}
-case 80:
-#line 655 "cp-parse.y"
-{
- tree decl = build_parse_node (CALL_EXPR, TREE_VALUE (yyval.ttype), yyvsp[-3].ttype, yyvsp[-1].ttype);
- yyval.ttype = start_method (TREE_CHAIN (yyval.ttype), decl, yyvsp[0].ttype);
- if (! yyval.ttype)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, yyval.ttype); ;
- break;}
-case 81:
-#line 664 "cp-parse.y"
-{
- tree decl = build_parse_node (CALL_EXPR, TREE_VALUE (yyval.ttype), empty_parms (), yyvsp[-1].ttype);
- yyval.ttype = start_method (TREE_CHAIN (yyval.ttype), decl, yyvsp[0].ttype);
- if (! yyval.ttype)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, yyval.ttype); ;
- break;}
-case 82:
-#line 673 "cp-parse.y"
-{ yyval.ttype = start_method (yyval.ttype, yyvsp[-1].ttype, yyvsp[0].ttype);
- if (! yyval.ttype)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, yyval.ttype); ;
- break;}
-case 83:
-#line 680 "cp-parse.y"
-{ yyval.ttype = start_method (NULL_TREE, yyval.ttype, yyvsp[0].ttype);
- if (! yyval.ttype)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, yyval.ttype); ;
- break;}
-case 84:
-#line 689 "cp-parse.y"
-{
- if (! current_function_parms_stored)
- store_parm_decls ();
- yyval.ttype = yyvsp[0].ttype;
- ;
- break;}
-case 85:
-#line 697 "cp-parse.y"
-{ store_return_init (yyval.ttype, NULL_TREE); ;
- break;}
-case 86:
-#line 699 "cp-parse.y"
-{ store_return_init (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 87:
-#line 701 "cp-parse.y"
-{ store_return_init (yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 88:
-#line 703 "cp-parse.y"
-{ store_return_init (yyval.ttype, NULL_TREE); ;
- break;}
-case 89:
-#line 708 "cp-parse.y"
-{
- if (yyvsp[0].itype == 0)
- error ("no base initializers given following ':'");
- setup_vtbl_ptr ();
- ;
- break;}
-case 90:
-#line 717 "cp-parse.y"
-{
- if (! current_function_parms_stored)
- store_parm_decls ();
-
- /* Flag that we are processing base and member initializers. */
- current_vtable_decl = error_mark_node;
-
- if (DECL_CONSTRUCTOR_P (current_function_decl))
- {
- /* Make a contour for the initializer list. */
- pushlevel (0);
- clear_last_expr ();
- expand_start_bindings (0);
- }
- else if (current_class_type == NULL_TREE)
- error ("base initializers not allowed for non-member functions");
- else if (! DECL_CONSTRUCTOR_P (current_function_decl))
- error ("only constructors take base initializers");
- ;
- break;}
-case 91:
-#line 740 "cp-parse.y"
-{ yyval.itype = 0; ;
- break;}
-case 92:
-#line 742 "cp-parse.y"
-{ yyval.itype = 1; ;
- break;}
-case 95:
-#line 748 "cp-parse.y"
-{
- if (current_class_name && !flag_traditional)
- pedwarn ("ANSI C++ forbids old style base class initialization",
- IDENTIFIER_POINTER (current_class_name));
- expand_member_init (C_C_D, NULL_TREE, yyvsp[-1].ttype);
- ;
- break;}
-case 96:
-#line 755 "cp-parse.y"
-{
- if (current_class_name && !flag_traditional)
- pedwarn ("ANSI C++ forbids old style base class initialization",
- IDENTIFIER_POINTER (current_class_name));
- expand_member_init (C_C_D, NULL_TREE, void_type_node);
- ;
- break;}
-case 97:
-#line 762 "cp-parse.y"
-{
- expand_member_init (C_C_D, yyval.ttype, yyvsp[-1].ttype);
- ;
- break;}
-case 98:
-#line 766 "cp-parse.y"
-{ expand_member_init (C_C_D, yyval.ttype, void_type_node); ;
- break;}
-case 99:
-#line 768 "cp-parse.y"
-{ expand_member_init (C_C_D, yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 100:
-#line 770 "cp-parse.y"
-{ expand_member_init (C_C_D, yyval.ttype, void_type_node); ;
- break;}
-case 101:
-#line 772 "cp-parse.y"
-{ expand_member_init (C_C_D, yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 102:
-#line 774 "cp-parse.y"
-{ expand_member_init (C_C_D, yyval.ttype, void_type_node); ;
- break;}
-case 103:
-#line 776 "cp-parse.y"
-{
- do_member_init (yyval.ttype, yyvsp[-3].ttype, yyvsp[-1].ttype);
- ;
- break;}
-case 104:
-#line 780 "cp-parse.y"
-{
- do_member_init (yyval.ttype, yyvsp[-1].ttype, void_type_node);
- ;
- break;}
-case 114:
-#line 804 "cp-parse.y"
-{ yyval.ttype = build_parse_node (BIT_NOT_EXPR,yyvsp[0].ttype);;
- break;}
-case 116:
-#line 810 "cp-parse.y"
-{
- extern tree template_type_seen_before_scope;
-
- if (yyvsp[0].ttype)
- yyval.ttype = yyvsp[0].ttype;
- else if (yyval.ttype != error_mark_node)
- yyval.ttype = IDENTIFIER_TYPE_VALUE (yyval.ttype);
- /* This is a kludge: In order to detect nested types inside
- * template classes, we have to tell the lexer that it should
- * try to replace a following SCOPE token with the correct
- * SCOPED_TYPENAME for the nested type. This SCOPED_TYPENAME
- * token will be handled in the rule "scoped_typename".
- * - niklas@appli.se */
- if (yychar == SCOPE)
- {
- /* We set template_type_seen_before_scope to be
- an error_mark_node so we can avoid meaningless
- and unhelpful syntax errors later. */
- if (yyval.ttype != error_mark_node)
- template_type_seen_before_scope = TYPE_IDENTIFIER (yyval.ttype);
- else
- template_type_seen_before_scope = error_mark_node;
- yychar = YYLEX;
- }
- ;
- break;}
-case 117:
-#line 839 "cp-parse.y"
-{ yyval.ttype = lookup_template_class (yyval.ttype, yyvsp[-1].ttype, NULL_TREE); ;
- break;}
-case 118:
-#line 841 "cp-parse.y"
-{ yyval.ttype = lookup_template_class (yyval.ttype, yyvsp[-1].ttype, NULL_TREE); ;
- break;}
-case 119:
-#line 847 "cp-parse.y"
-{ yyungetc ('{', 1); yyval.ttype = 0; ;
- break;}
-case 120:
-#line 848 "cp-parse.y"
-{ yyungetc (':', 1); yyval.ttype = 0; ;
- break;}
-case 121:
-#line 850 "cp-parse.y"
-{ yyval.ttype = instantiate_class_template (yyvsp[0].ttype, 1); ;
- break;}
-case 122:
-#line 855 "cp-parse.y"
-{ yyval.ttype = instantiate_class_template (yyvsp[0].ttype, 1); ;
- break;}
-case 123:
-#line 860 "cp-parse.y"
-{ yyval.ttype = build_tree_list (NULL_TREE, yyval.ttype); ;
- break;}
-case 124:
-#line 862 "cp-parse.y"
-{ yyval.ttype = chainon (yyval.ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
- break;}
-case 125:
-#line 867 "cp-parse.y"
-{ yyval.ttype = groktypename (yyval.ttype); ;
- break;}
-case 127:
-#line 873 "cp-parse.y"
-{
- tree t, decl, id, tmpl;
-
- id = TREE_VALUE (yyvsp[-1].ttype);
- tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE (id));
- t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, id, yyvsp[0].ttype);
- set_current_level_tags_transparency (1);
- my_friendly_assert (TREE_CODE (t) == RECORD_TYPE, 257);
- yyval.ttype = t;
-
- /* Now, put a copy of the decl in global scope, to avoid
- recursive expansion. */
- decl = IDENTIFIER_LOCAL_VALUE (id);
- if (!decl)
- decl = IDENTIFIER_CLASS_VALUE (id);
- /* Now, put a copy of the decl in global scope, to avoid
- recursive expansion. */
- if (decl)
- {
- /* Need to copy it to clear the chain pointer,
- and need to get it into permanent storage. */
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 258);
- push_obstacks (&permanent_obstack, &permanent_obstack);
- decl = copy_node (decl);
- if (DECL_LANG_SPECIFIC (decl))
- copy_lang_decl (decl);
- pop_obstacks ();
- pushdecl_top_level (decl);
- }
- ;
- break;}
-case 128:
-#line 904 "cp-parse.y"
-{
- int old_interface = interface_unknown;
-
- interface_unknown = 1;
- yyval.ttype = finish_struct (yyvsp[-3].ttype, yyvsp[-1].ttype, 0);
-
- pop_obstacks ();
- end_template_instantiation (yyvsp[-5].ttype, yyvsp[-3].ttype);
-
- /* Now go after the methods & class data. */
- old_interface = interface_unknown;
- interface_unknown = 1;
- instantiate_member_templates (yyvsp[-5].ttype);
- interface_unknown = old_interface;
- CLASSTYPE_GOT_SEMICOLON (yyval.ttype) = 1;
- ;
- break;}
-case 129:
-#line 924 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 130:
-#line 926 "cp-parse.y"
-{ yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 131:
-#line 931 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; /* never used from here... */;
- break;}
-case 132:
-#line 933 "cp-parse.y"
-{ yyval.ttype = yyvsp[-1].ttype; /*???*/ ;
- break;}
-case 133:
-#line 937 "cp-parse.y"
-{ yyval.code = NEGATE_EXPR; ;
- break;}
-case 134:
-#line 939 "cp-parse.y"
-{ yyval.code = CONVERT_EXPR; ;
- break;}
-case 135:
-#line 941 "cp-parse.y"
-{ yyval.code = PREINCREMENT_EXPR; ;
- break;}
-case 136:
-#line 943 "cp-parse.y"
-{ yyval.code = PREDECREMENT_EXPR; ;
- break;}
-case 137:
-#line 945 "cp-parse.y"
-{ yyval.code = TRUTH_NOT_EXPR; ;
- break;}
-case 138:
-#line 949 "cp-parse.y"
-{ yyval.ttype = build_x_compound_expr (yyval.ttype); ;
- break;}
-case 140:
-#line 956 "cp-parse.y"
-{ error ("ANSI C++ forbids an empty condition for `%s'",
- cond_stmt_keyword);
- yyval.ttype = integer_zero_node; ;
- break;}
-case 141:
-#line 960 "cp-parse.y"
-{ yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 142:
-#line 965 "cp-parse.y"
-{ yyval.ttype = build_tree_list (NULL_TREE, yyval.ttype); ;
- break;}
-case 143:
-#line 967 "cp-parse.y"
-{ chainon (yyval.ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
- break;}
-case 144:
-#line 969 "cp-parse.y"
-{ chainon (yyval.ttype, build_tree_list (NULL_TREE, error_mark_node)); ;
- break;}
-case 145:
-#line 974 "cp-parse.y"
-{
- if (TREE_CODE (yyval.ttype) == TYPE_EXPR)
- yyval.ttype = build_component_type_expr (C_C_D, yyval.ttype, NULL_TREE, 1);
- ;
- break;}
-case 146:
-#line 980 "cp-parse.y"
-{ yyvsp[0].itype = pedantic;
- pedantic = 0; ;
- break;}
-case 147:
-#line 983 "cp-parse.y"
-{ yyval.ttype = yyvsp[0].ttype;
- pedantic = yyvsp[-2].itype; ;
- break;}
-case 148:
-#line 986 "cp-parse.y"
-{ yyval.ttype = build_x_indirect_ref (yyvsp[0].ttype, "unary *"); ;
- break;}
-case 149:
-#line 988 "cp-parse.y"
-{ yyval.ttype = build_x_unary_op (ADDR_EXPR, yyvsp[0].ttype); ;
- break;}
-case 150:
-#line 990 "cp-parse.y"
-{ yyval.ttype = build_x_unary_op (BIT_NOT_EXPR, yyvsp[0].ttype); ;
- break;}
-case 151:
-#line 992 "cp-parse.y"
-{ yyval.ttype = build_x_unary_op ((enum tree_code) yyval.ttype, yyvsp[0].ttype);
- if (yyvsp[-1].code == NEGATE_EXPR && TREE_CODE (yyvsp[0].ttype) == INTEGER_CST)
- TREE_NEGATED_INT (yyval.ttype) = 1;
- ;
- break;}
-case 152:
-#line 998 "cp-parse.y"
-{ tree label = lookup_label (yyvsp[0].ttype);
- TREE_USED (label) = 1;
- yyval.ttype = build1 (ADDR_EXPR, ptr_type_node, label);
- TREE_CONSTANT (yyval.ttype) = 1; ;
- break;}
-case 153:
-#line 1003 "cp-parse.y"
-{ if (TREE_CODE (yyvsp[0].ttype) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (yyvsp[0].ttype, 1)))
- error ("sizeof applied to a bit-field");
- /* ANSI says arrays and functions are converted inside comma.
- But we can't really convert them in build_compound_expr
- because that would break commas in lvalues.
- So do the conversion here if operand was a comma. */
- if (TREE_CODE (yyvsp[0].ttype) == COMPOUND_EXPR
- && (TREE_CODE (TREE_TYPE (yyvsp[0].ttype)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (yyvsp[0].ttype)) == FUNCTION_TYPE))
- yyvsp[0].ttype = default_conversion (yyvsp[0].ttype);
- else if (TREE_CODE (yyvsp[0].ttype) == TREE_LIST)
- {
- tree t = TREE_VALUE (yyvsp[0].ttype);
- if (t != NULL_TREE
- && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids using sizeof() on a function");
- }
- yyval.ttype = c_sizeof (TREE_TYPE (yyvsp[0].ttype)); ;
- break;}
-case 154:
-#line 1023 "cp-parse.y"
-{ yyval.ttype = c_sizeof (groktypename (yyvsp[-1].ttype)); ;
- break;}
-case 155:
-#line 1025 "cp-parse.y"
-{ if (TREE_CODE (yyvsp[0].ttype) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (yyvsp[0].ttype, 1)))
- error ("`__alignof' applied to a bit-field");
- if (TREE_CODE (yyvsp[0].ttype) == INDIRECT_REF)
- {
- tree t = TREE_OPERAND (yyvsp[0].ttype, 0);
- tree best = t;
- int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
- while (TREE_CODE (t) == NOP_EXPR
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
- {
- int thisalign;
- t = TREE_OPERAND (t, 0);
- thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
- if (thisalign > bestalign)
- best = t, bestalign = thisalign;
- }
- yyval.ttype = c_alignof (TREE_TYPE (TREE_TYPE (best)));
- }
- else
- {
- /* ANSI says arrays and fns are converted inside comma.
- But we can't convert them in build_compound_expr
- because that would break commas in lvalues.
- So do the conversion here if operand was a comma. */
- if (TREE_CODE (yyvsp[0].ttype) == COMPOUND_EXPR
- && (TREE_CODE (TREE_TYPE (yyvsp[0].ttype)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (yyvsp[0].ttype)) == FUNCTION_TYPE))
- yyvsp[0].ttype = default_conversion (yyvsp[0].ttype);
- yyval.ttype = c_alignof (TREE_TYPE (yyvsp[0].ttype));
- }
- ;
- break;}
-case 156:
-#line 1058 "cp-parse.y"
-{ yyval.ttype = c_alignof (groktypename (yyvsp[-1].ttype)); ;
- break;}
-case 157:
-#line 1061 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-1].ttype, yyvsp[0].ttype, NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 158:
-#line 1063 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 159:
-#line 1065 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-4].ttype, yyvsp[-3].ttype, yyvsp[-1].ttype, yyval.ttype != NULL_TREE); ;
- break;}
-case 160:
-#line 1067 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-5].ttype, yyvsp[-3].ttype, yyvsp[-1].ttype, yyval.ttype != NULL_TREE); ;
- break;}
-case 161:
-#line 1069 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-2].ttype, yyvsp[-1].ttype, NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 162:
-#line 1071 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-3].ttype, yyvsp[-1].ttype, NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 163:
-#line 1073 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-3].ttype, yyvsp[-2].ttype, yyvsp[0].ttype, yyval.ttype != NULL_TREE); ;
- break;}
-case 164:
-#line 1075 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-4].ttype, yyvsp[-2].ttype, yyvsp[0].ttype, yyval.ttype != NULL_TREE); ;
- break;}
-case 165:
-#line 1083 "cp-parse.y"
-{
- tree absdcl, typename;
-
- illegal_new_array:
- absdcl = build_parse_node (ARRAY_REF, yyvsp[-4].ttype, yyvsp[-1].ttype);
- typename = build_decl_list (yyvsp[-5].ttype, absdcl);
- pedwarn ("ANSI C++ forbids array dimensions with parenthesized type");
- yyval.ttype = build_new (yyvsp[-7].ttype, typename, NULL_TREE, yyval.ttype != NULL_TREE);
- ;
- break;}
-case 166:
-#line 1093 "cp-parse.y"
-{ goto illegal_new_array; ;
- break;}
-case 167:
-#line 1096 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-4].ttype, build_decl_list (yyvsp[-2].ttype, yyvsp[-1].ttype), NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 168:
-#line 1098 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-5].ttype, build_decl_list (yyvsp[-2].ttype, yyvsp[-1].ttype), NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 169:
-#line 1100 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-4].ttype, build_decl_list (yyvsp[-2].ttype, yyvsp[-1].ttype), NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 170:
-#line 1102 "cp-parse.y"
-{ yyval.ttype = build_new (yyvsp[-5].ttype, build_decl_list (yyvsp[-2].ttype, yyvsp[-1].ttype), NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 171:
-#line 1105 "cp-parse.y"
-{ yyungetc (':', 1); yyval.ttype = build_new (yyvsp[-1].ttype, yyvsp[0].ttype, NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 172:
-#line 1107 "cp-parse.y"
-{ yyungetc (':', 1); yyval.ttype = build_new (yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE, yyval.ttype != NULL_TREE); ;
- break;}
-case 173:
-#line 1110 "cp-parse.y"
-{ tree expr = stabilize_reference (convert_from_reference (yyvsp[0].ttype));
- tree type = TREE_TYPE (expr);
-
- if (TREE_CODE (type) != POINTER_TYPE)
- {
- error ("non-pointer type to `delete'");
- yyval.ttype = error_mark_node;
- break;
- }
- else if (integer_zerop (expr))
- {
- /* ANSI C++ June 5 1992 WP 5.3.4. Deleting a pointer
- with the value zero is legal and has no effect. */
- yyval.ttype = build1 (NOP_EXPR, void_type_node, expr);
- break;
- }
- else if (TREE_READONLY (TREE_TYPE (type)))
- {
- error ("`const *' cannot be deleted");
- yyval.ttype = error_mark_node;
- break;
- }
- yyval.ttype = build_delete (type, expr, integer_three_node,
- LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE,
- TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)),
- 0);
- ;
- break;}
-case 174:
-#line 1138 "cp-parse.y"
-{
- tree exp = stabilize_reference (convert_from_reference (yyvsp[0].ttype));
- tree type = TREE_TYPE (exp);
- tree elt_size = c_sizeof (type);
-
- if (yychar == YYEMPTY)
- yychar = YYLEX;
-
- if (TREE_CODE (type) == POINTER_TYPE
- && TREE_READONLY (TREE_TYPE (type)))
- {
- error ("`const *' cannot be deleted");
- yyval.ttype = error_mark_node;
- break;
- }
- yyval.ttype = build_vec_delete (exp, NULL_TREE, elt_size, NULL_TREE,
- integer_one_node, integer_two_node);
- ;
- break;}
-case 175:
-#line 1157 "cp-parse.y"
-{
- tree maxindex = build_binary_op (MINUS_EXPR, yyvsp[-2].ttype,
- integer_one_node, 1);
- tree exp = stabilize_reference (convert_from_reference (yyvsp[0].ttype));
- tree type = TREE_TYPE (exp);
- tree elt_size = c_sizeof (type);
-
- if (yychar == YYEMPTY)
- yychar = YYLEX;
-
- if (! flag_traditional)
- pedwarn ("ANSI C++ forbids array size in vector delete");
- if (TREE_CODE (type) == POINTER_TYPE
- && TREE_READONLY (TREE_TYPE (type)))
- {
- error ("`const *' cannot be deleted");
- yyval.ttype = error_mark_node;
- break;
- }
- yyval.ttype = build_vec_delete (exp, maxindex, elt_size, NULL_TREE,
- integer_one_node, integer_two_node);
- ;
- break;}
-case 177:
-#line 1184 "cp-parse.y"
-{ tree type = groktypename (yyvsp[-2].ttype);
- yyval.ttype = build_c_cast (type, yyvsp[0].ttype); ;
- break;}
-case 178:
-#line 1187 "cp-parse.y"
-{ tree type = groktypename (yyvsp[-5].ttype);
- tree init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (yyvsp[-2].ttype));
- if (pedantic)
- pedwarn ("ANSI C++ forbids constructor-expressions");
- /* Indicate that this was a GNU C constructor expression. */
- TREE_HAS_CONSTRUCTOR (init) = 1;
- yyval.ttype = digest_init (type, init, (tree *) 0);
- if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
- {
- int failure = complete_array_type (type, yyval.ttype, 1);
- if (failure)
- my_friendly_abort (78);
- }
- ;
- break;}
-case 179:
-#line 1202 "cp-parse.y"
-{ yyval.ttype = build_headof (yyvsp[-1].ttype); ;
- break;}
-case 180:
-#line 1204 "cp-parse.y"
-{ yyval.ttype = build_classof (yyvsp[-1].ttype); ;
- break;}
-case 181:
-#line 1206 "cp-parse.y"
-{ if (is_aggr_typedef (yyvsp[-1].ttype, 1))
- {
- tree type = IDENTIFIER_TYPE_VALUE (yyvsp[-1].ttype);
- yyval.ttype = CLASSTYPE_DOSSIER (type);
- }
- else
- yyval.ttype = error_mark_node;
- ;
- break;}
-case 183:
-#line 1219 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 184:
-#line 1221 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 185:
-#line 1223 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 186:
-#line 1225 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 187:
-#line 1227 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 188:
-#line 1229 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 189:
-#line 1231 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 190:
-#line 1233 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 191:
-#line 1235 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (LT_EXPR, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 192:
-#line 1237 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (GT_EXPR, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 193:
-#line 1239 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 194:
-#line 1241 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 195:
-#line 1243 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 196:
-#line 1245 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 197:
-#line 1247 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (yyvsp[-1].code, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 198:
-#line 1249 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (TRUTH_ANDIF_EXPR, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 199:
-#line 1251 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (TRUTH_ORIF_EXPR, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 200:
-#line 1253 "cp-parse.y"
-{ yyval.ttype = build_x_conditional_expr (yyval.ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 201:
-#line 1255 "cp-parse.y"
-{ yyval.ttype = build_modify_expr (yyval.ttype, NOP_EXPR, yyvsp[0].ttype); ;
- break;}
-case 202:
-#line 1257 "cp-parse.y"
-{ register tree rval;
- if (rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, yyval.ttype, yyvsp[0].ttype,
- make_node (yyvsp[-1].code)))
- yyval.ttype = rval;
- else
- yyval.ttype = build_modify_expr (yyval.ttype, yyvsp[-1].code, yyvsp[0].ttype); ;
- break;}
-case 203:
-#line 1264 "cp-parse.y"
-{ yyval.ttype = build_m_component_ref (yyval.ttype, build_indirect_ref (yyvsp[0].ttype, 0)); ;
- break;}
-case 204:
-#line 1267 "cp-parse.y"
-{ yyval.ttype = build_x_binary_op (MEMBER_REF, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 205:
-#line 1283 "cp-parse.y"
-{ yyval.ttype = do_identifier (yyval.ttype); ;
- break;}
-case 206:
-#line 1285 "cp-parse.y"
-{
- tree op = yyval.ttype;
- if (TREE_CODE (op) != IDENTIFIER_NODE)
- yyval.ttype = op;
- else
- {
- yyval.ttype = lookup_name (op, 0);
- if (yyval.ttype == NULL_TREE)
- {
- error ("operator %s not defined", operator_name_string (op));
- yyval.ttype = error_mark_node;
- }
- }
- ;
- break;}
-case 208:
-#line 1301 "cp-parse.y"
-{ yyval.ttype = combine_strings (yyval.ttype); ;
- break;}
-case 209:
-#line 1303 "cp-parse.y"
-{ yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 210:
-#line 1305 "cp-parse.y"
-{ yyval.ttype = error_mark_node; ;
- break;}
-case 211:
-#line 1307 "cp-parse.y"
-{ if (current_function_decl == 0)
- {
- error ("braced-group within expression allowed only inside a function");
- YYERROR;
- }
- keep_next_level ();
- yyval.ttype = expand_start_stmt_expr (); ;
- break;}
-case 212:
-#line 1315 "cp-parse.y"
-{ tree rtl_exp;
- if (pedantic)
- pedwarn ("ANSI C++ forbids braced-groups within expressions");
- rtl_exp = expand_end_stmt_expr (yyvsp[-2].ttype);
- /* The statements have side effects, so the group does. */
- TREE_SIDE_EFFECTS (rtl_exp) = 1;
- /* Make a BIND_EXPR for the BLOCK already made. */
- yyval.ttype = build (BIND_EXPR, TREE_TYPE (rtl_exp),
- NULL_TREE, rtl_exp, yyvsp[-1].ttype);
- /* Remove the block from the tree at this point.
- It gets put back at the proper place
- when the BIND_EXPR is expanded. */
- delete_block (yyvsp[-1].ttype);
- ;
- break;}
-case 213:
-#line 1330 "cp-parse.y"
-{ /* [eichin:19911016.1902EST] */
- yyval.ttype = build_x_function_call (yyvsp[-3].ttype, yyvsp[-1].ttype, current_class_decl);
- /* here we instantiate_class_template as needed... */
- do_pending_templates ();
- ;
- break;}
-case 214:
-#line 1334 "cp-parse.y"
-{
- if (TREE_CODE (yyvsp[-1].ttype) == CALL_EXPR
- && TREE_TYPE (yyvsp[-1].ttype) != void_type_node)
- yyval.ttype = require_complete_type (yyvsp[-1].ttype);
- else
- yyval.ttype = yyvsp[-1].ttype;
- ;
- break;}
-case 215:
-#line 1342 "cp-parse.y"
-{
- if (yyval.ttype != error_mark_node)
- {
- yyval.ttype = build_x_function_call (yyval.ttype, NULL_TREE, current_class_decl);
- if (TREE_CODE (yyval.ttype) == CALL_EXPR
- && TREE_TYPE (yyval.ttype) != void_type_node)
- yyval.ttype = require_complete_type (yyval.ttype);
- }
- ;
- break;}
-case 216:
-#line 1352 "cp-parse.y"
-{
- do_array:
- {
- tree array_expr = yyval.ttype;
- tree index_exp = yyvsp[-1].ttype;
- tree type = TREE_TYPE (array_expr);
- if (type == error_mark_node || index_exp == error_mark_node)
- yyval.ttype = error_mark_node;
- else if (type == NULL_TREE)
- {
- /* Something has gone very wrong. Assume we
- are mistakenly reducing an expression
- instead of a declaration. */
- error ("parser may be lost: is there a '{' missing somewhere?");
- yyval.ttype = NULL_TREE;
- }
- else
- {
- if (TREE_CODE (type) == OFFSET_TYPE)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (TYPE_LANG_SPECIFIC (type)
- && TYPE_OVERLOADS_ARRAY_REF (type))
- yyval.ttype = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp, NULL_TREE);
- else if (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == ARRAY_TYPE)
- yyval.ttype = build_array_ref (array_expr, index_exp);
- else
- {
- type = TREE_TYPE (index_exp);
- if (TREE_CODE (type) == OFFSET_TYPE)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (TYPE_LANG_SPECIFIC (type)
- && TYPE_OVERLOADS_ARRAY_REF (type))
- error ("array expression backwards");
- else if (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == ARRAY_TYPE)
- yyval.ttype = build_array_ref (index_exp, array_expr);
- else
- error("[] applied to non-pointer type");
- }
- }
- }
- ;
- break;}
-case 217:
-#line 1402 "cp-parse.y"
-{ yyval.ttype = build_component_ref (yyval.ttype, yyvsp[0].ttype, NULL_TREE, 1); ;
- break;}
-case 218:
-#line 1404 "cp-parse.y"
-{
- tree basetype = yyvsp[-1].ttype;
- if (is_aggr_typedef (basetype, 1))
- {
- basetype = IDENTIFIER_TYPE_VALUE (basetype);
-
- if (yyval.ttype == error_mark_node)
- ;
- else if (binfo_or_else (basetype, TREE_TYPE (yyval.ttype)))
- yyval.ttype = build_component_ref (build_scoped_ref (yyval.ttype, yyvsp[-1].ttype), yyvsp[0].ttype, NULL_TREE, 1);
- else
- yyval.ttype = error_mark_node;
- }
- else yyval.ttype = error_mark_node;
- ;
- break;}
-case 219:
-#line 1420 "cp-parse.y"
-{ yyval.ttype = build_x_unary_op (POSTINCREMENT_EXPR, yyval.ttype); ;
- break;}
-case 220:
-#line 1422 "cp-parse.y"
-{ yyval.ttype = build_x_unary_op (POSTDECREMENT_EXPR, yyval.ttype); ;
- break;}
-case 221:
-#line 1426 "cp-parse.y"
-{ if (current_class_decl)
- {
-#ifdef WARNING_ABOUT_CCD
- TREE_USED (current_class_decl) = 1;
-#endif
- yyval.ttype = current_class_decl;
- }
- else if (current_function_decl
- && DECL_STATIC_FUNCTION_P (current_function_decl))
- {
- error ("`this' is unavailable for static member functions");
- yyval.ttype = error_mark_node;
- }
- else
- {
- if (current_function_decl)
- error ("invalid use of `this' in non-member function");
- else
- error ("invalid use of `this' at top level");
- yyval.ttype = error_mark_node;
- }
- ;
- break;}
-case 222:
-#line 1449 "cp-parse.y"
-{
- tree type;
- tree id = yyval.ttype;
-
- /* This is a C cast in C++'s `functional' notation. */
- if (yyvsp[-1].ttype == error_mark_node)
- {
- yyval.ttype = error_mark_node;
- break;
- }
-#if 0
- if (yyvsp[-1].ttype == NULL_TREE)
- {
- error ("cannot cast null list to type `%s'",
- IDENTIFIER_POINTER (TYPE_NAME (id)));
- yyval.ttype = error_mark_node;
- break;
- }
-#endif
-#if 0
- /* type is not set! (mrs) */
- if (type == error_mark_node)
- yyval.ttype = error_mark_node;
- else
-#endif
- {
- if (id == ridpointers[(int) RID_CONST])
- type = build_type_variant (integer_type_node, 1, 0);
- else if (id == ridpointers[(int) RID_VOLATILE])
- type = build_type_variant (integer_type_node, 0, 1);
-#if 0
- /* should not be able to get here (mrs) */
- else if (id == ridpointers[(int) RID_FRIEND])
- {
- error ("cannot cast expression to `friend' type");
- yyval.ttype = error_mark_node;
- break;
- }
-#endif
- else my_friendly_abort (79);
- yyval.ttype = build_c_cast (type, build_compound_expr (yyvsp[-1].ttype));
- }
- ;
- break;}
-case 223:
-#line 1493 "cp-parse.y"
-{ yyval.ttype = build_functional_cast (yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 224:
-#line 1495 "cp-parse.y"
-{ yyval.ttype = build_functional_cast (yyval.ttype, NULL_TREE); ;
- break;}
-case 225:
-#line 1497 "cp-parse.y"
-{ yyval.ttype = build_functional_cast (yyvsp[-3].ttype, yyvsp[-1].ttype); ;
- break;}
-case 226:
-#line 1499 "cp-parse.y"
-{ yyval.ttype = build_functional_cast (yyvsp[-1].ttype, NULL_TREE); ;
- break;}
-case 227:
-#line 1501 "cp-parse.y"
-{
- do_scoped_id:
- yyval.ttype = IDENTIFIER_GLOBAL_VALUE (yyvsp[0].ttype);
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- if (! yyval.ttype)
- {
- if (yychar == '(' || yychar == LEFT_RIGHT)
- yyval.ttype = implicitly_declare (yyvsp[0].ttype);
- else
- {
- if (IDENTIFIER_GLOBAL_VALUE (yyvsp[0].ttype) != error_mark_node)
- error ("undeclared variable `%s' (first use here)",
- IDENTIFIER_POINTER (yyvsp[0].ttype));
- yyval.ttype = error_mark_node;
- /* Prevent repeated error messages. */
- IDENTIFIER_GLOBAL_VALUE (yyvsp[0].ttype) = error_mark_node;
- }
- }
- else
- {
- if (TREE_CODE (yyval.ttype) == ADDR_EXPR)
- assemble_external (TREE_OPERAND (yyval.ttype, 0));
- else
- assemble_external (yyval.ttype);
- TREE_USED (yyval.ttype) = 1;
- }
- if (TREE_CODE (yyval.ttype) == CONST_DECL)
- {
- /* XXX CHS - should we set TREE_USED of the constant? */
- yyval.ttype = DECL_INITIAL (yyval.ttype);
- /* This is to prevent an enum whose value is 0
- from being considered a null pointer constant. */
- yyval.ttype = build1 (NOP_EXPR, TREE_TYPE (yyval.ttype), yyval.ttype);
- TREE_CONSTANT (yyval.ttype) = 1;
- }
-
- ;
- break;}
-case 228:
-#line 1540 "cp-parse.y"
-{
- if (TREE_CODE (yyvsp[0].ttype) == IDENTIFIER_NODE)
- goto do_scoped_id;
- do_scoped_operator:
- yyval.ttype = yyvsp[0].ttype;
- ;
- break;}
-case 229:
-#line 1547 "cp-parse.y"
-{ yyval.ttype = build_offset_ref (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 230:
-#line 1549 "cp-parse.y"
-{ yyval.ttype = build_member_call (yyval.ttype, yyvsp[-3].ttype, yyvsp[-1].ttype); ;
- break;}
-case 231:
-#line 1551 "cp-parse.y"
-{ yyval.ttype = build_member_call (yyval.ttype, yyvsp[-1].ttype, NULL_TREE); ;
- break;}
-case 232:
-#line 1553 "cp-parse.y"
-{ yyval.ttype = build_method_call (yyval.ttype, yyvsp[-3].ttype, yyvsp[-1].ttype, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR)); ;
- break;}
-case 233:
-#line 1556 "cp-parse.y"
-{ yyval.ttype = build_method_call (yyval.ttype, yyvsp[-1].ttype, NULL_TREE, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR)); ;
- break;}
-case 234:
-#line 1559 "cp-parse.y"
-{ yyval.ttype = build_scoped_method_call (yyval.ttype, yyvsp[-4].ttype, yyvsp[-3].ttype, yyvsp[-1].ttype); ;
- break;}
-case 235:
-#line 1561 "cp-parse.y"
-{ yyval.ttype = build_scoped_method_call (yyval.ttype, yyvsp[-2].ttype, yyvsp[-1].ttype, NULL_TREE); ;
- break;}
-case 236:
-#line 1603 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 237:
-#line 1605 "cp-parse.y"
-{
- yyval.ttype = yyvsp[-1].ttype;
- pedwarn ("old style placement syntax, use () instead");
- ;
- break;}
-case 238:
-#line 1610 "cp-parse.y"
-{ yyval.ttype = void_type_node; ;
- break;}
-case 239:
-#line 1612 "cp-parse.y"
-{ yyval.ttype = combine_strings (yyvsp[-1].ttype); ;
- break;}
-case 240:
-#line 1617 "cp-parse.y"
-{ yyval.itype = 0; ;
- break;}
-case 241:
-#line 1619 "cp-parse.y"
-{ yyval.itype = 1; ;
- break;}
-case 242:
-#line 1623 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 243:
-#line 1625 "cp-parse.y"
-{ if (yyvsp[0].ttype)
- error ("extra `::' before `delete' ignored");
- yyval.ttype = error_mark_node;
- ;
- break;}
-case 245:
-#line 1635 "cp-parse.y"
-{ yyval.ttype = chainon (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 246:
-#line 1640 "cp-parse.y"
-{
- if (! current_function_parms_stored)
- store_parm_decls ();
- setup_vtbl_ptr ();
- ;
- break;}
-case 247:
-#line 1648 "cp-parse.y"
-{
- if (yyval.ttype == error_mark_node)
- ;
- else
- {
- tree type = TREE_TYPE (yyval.ttype);
-
- if (! PROMOTES_TO_AGGR_TYPE (type, REFERENCE_TYPE))
- {
- error ("object in '.' expression is not of aggregate type");
- yyval.ttype = error_mark_node;
- }
- }
- ;
- break;}
-case 248:
-#line 1663 "cp-parse.y"
-{
- yyval.ttype = build_x_arrow (yyval.ttype);
- ;
- break;}
-case 250:
-#line 1673 "cp-parse.y"
-{
- resume_momentary (yyvsp[-1].itype);
- note_list_got_semicolon (yyval.ttype);
- ;
- break;}
-case 251:
-#line 1679 "cp-parse.y"
-{ tree d;
- int yes = suspend_momentary ();
- d = start_decl (yyvsp[-1].ttype, yyval.ttype, 0, NULL_TREE);
- finish_decl (d, NULL_TREE, NULL_TREE, 0);
- resume_momentary (yes);
- note_list_got_semicolon (yyval.ttype);
- ;
- break;}
-case 252:
-#line 1687 "cp-parse.y"
-{ resume_momentary ((int) yyvsp[-1].itype); ;
- break;}
-case 253:
-#line 1690 "cp-parse.y"
-{ tree d;
- int yes = suspend_momentary ();
- d = start_decl (yyvsp[-1].ttype, yyval.ttype, 0, NULL_TREE);
- finish_decl (d, NULL_TREE, NULL_TREE, 0);
- resume_momentary (yes);
- ;
- break;}
-case 254:
-#line 1697 "cp-parse.y"
-{
- shadow_tag (yyval.ttype);
- note_list_got_semicolon (yyval.ttype);
- ;
- break;}
-case 255:
-#line 1702 "cp-parse.y"
-{ warning ("empty declaration"); ;
- break;}
-case 258:
-#line 1712 "cp-parse.y"
-{ yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 259:
-#line 1714 "cp-parse.y"
-{ yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 260:
-#line 1723 "cp-parse.y"
-{ yyval.ttype = list_hash_lookup_or_cons (yyval.ttype); ;
- break;}
-case 261:
-#line 1725 "cp-parse.y"
-{ yyval.ttype = hash_tree_chain (yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 262:
-#line 1727 "cp-parse.y"
-{ yyval.ttype = hash_tree_chain (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 263:
-#line 1729 "cp-parse.y"
-{ yyval.ttype = hash_tree_chain (yyvsp[-1].ttype, hash_chainon (yyvsp[0].ttype, yyval.ttype)); ;
- break;}
-case 264:
-#line 1735 "cp-parse.y"
-{ yyval.ttype = build_decl_list (NULL_TREE, yyval.ttype); ;
- break;}
-case 265:
-#line 1737 "cp-parse.y"
-{ if (extra_warnings)
- warning ("`%s' is not at beginning of declaration",
- IDENTIFIER_POINTER (yyval.ttype));
- yyval.ttype = build_decl_list (NULL_TREE, yyval.ttype); ;
- break;}
-case 266:
-#line 1742 "cp-parse.y"
-{ yyval.ttype = decl_tree_cons (NULL_TREE, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 267:
-#line 1744 "cp-parse.y"
-{ if (extra_warnings)
- warning ("`%s' is not at beginning of declaration",
- IDENTIFIER_POINTER (yyvsp[0].ttype));
- yyval.ttype = decl_tree_cons (NULL_TREE, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 268:
-#line 1756 "cp-parse.y"
-{ yyval.ttype = IDENTIFIER_AS_LIST (yyval.ttype);
- TREE_STATIC (yyval.ttype) = 1; ;
- break;}
-case 269:
-#line 1759 "cp-parse.y"
-{ yyval.ttype = IDENTIFIER_AS_LIST (yyval.ttype); ;
- break;}
-case 270:
-#line 1761 "cp-parse.y"
-{ yyval.ttype = hash_tree_chain (yyvsp[0].ttype, yyval.ttype);
- TREE_STATIC (yyval.ttype) = 1; ;
- break;}
-case 271:
-#line 1764 "cp-parse.y"
-{ if (extra_warnings && TREE_STATIC (yyval.ttype))
- warning ("`%s' is not at beginning of declaration",
- IDENTIFIER_POINTER (yyvsp[0].ttype));
- yyval.ttype = hash_tree_chain (yyvsp[0].ttype, yyval.ttype);
- TREE_STATIC (yyval.ttype) = TREE_STATIC (yyvsp[-1].ttype); ;
- break;}
-case 272:
-#line 1780 "cp-parse.y"
-{ yyval.ttype = get_decl_list (yyval.ttype); ;
- break;}
-case 273:
-#line 1782 "cp-parse.y"
-{ yyval.ttype = decl_tree_cons (NULL_TREE, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 274:
-#line 1784 "cp-parse.y"
-{ yyval.ttype = decl_tree_cons (NULL_TREE, yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 275:
-#line 1786 "cp-parse.y"
-{ yyval.ttype = decl_tree_cons (NULL_TREE, yyvsp[-1].ttype, hash_chainon (yyvsp[0].ttype, yyval.ttype)); ;
- break;}
-case 276:
-#line 1791 "cp-parse.y"
-{ yyval.ttype = get_decl_list (yyval.ttype); ;
- break;}
-case 277:
-#line 1793 "cp-parse.y"
-{ yyval.ttype = decl_tree_cons (NULL_TREE, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 282:
-#line 1805 "cp-parse.y"
-{ yyval.ttype = TREE_TYPE (yyvsp[-1].ttype);
- if (pedantic)
- pedwarn ("ANSI C++ forbids `typeof'"); ;
- break;}
-case 283:
-#line 1809 "cp-parse.y"
-{ yyval.ttype = groktypename (yyvsp[-1].ttype);
- if (pedantic)
- pedwarn ("ANSI C++ forbids `typeof'"); ;
- break;}
-case 292:
-#line 1834 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 293:
-#line 1836 "cp-parse.y"
-{ if (TREE_CHAIN (yyvsp[-1].ttype)) yyvsp[-1].ttype = combine_strings (yyvsp[-1].ttype); yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 294:
-#line 1841 "cp-parse.y"
-{ current_declspecs = yyvsp[-5].ttype;
- yyvsp[0].itype = suspend_momentary ();
- yyval.ttype = start_decl (yyvsp[-4].ttype, current_declspecs, 1, yyvsp[-3].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 295:
-#line 1847 "cp-parse.y"
-{ finish_decl (yyvsp[-1].ttype, yyvsp[0].ttype, yyvsp[-4].ttype, 0);
- yyval.itype = yyvsp[-2].itype; ;
- break;}
-case 296:
-#line 1850 "cp-parse.y"
-{ tree d;
- current_declspecs = yyvsp[-4].ttype;
- yyval.itype = suspend_momentary ();
- d = start_decl (yyvsp[-3].ttype, current_declspecs, 0, yyvsp[-2].ttype);
- cplus_decl_attributes (d, yyvsp[0].ttype);
- finish_decl (d, NULL_TREE, yyvsp[-1].ttype, 0); ;
- break;}
-case 297:
-#line 1860 "cp-parse.y"
-{ yyval.ttype = start_decl (yyvsp[-4].ttype, current_declspecs, 1, yyvsp[-3].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 298:
-#line 1864 "cp-parse.y"
-{ finish_decl (yyvsp[-1].ttype, yyvsp[0].ttype, yyvsp[-4].ttype, 0); ;
- break;}
-case 299:
-#line 1866 "cp-parse.y"
-{ tree d = start_decl (yyvsp[-3].ttype, current_declspecs, 0, yyvsp[-2].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[0].ttype);
- finish_decl (d, NULL_TREE, yyvsp[-1].ttype, 0); ;
- break;}
-case 300:
-#line 1873 "cp-parse.y"
-{ current_declspecs = yyvsp[-5].ttype;
- yyvsp[0].itype = suspend_momentary ();
- yyval.ttype = start_decl (yyvsp[-4].ttype, current_declspecs, 1, yyvsp[-3].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 301:
-#line 1879 "cp-parse.y"
-{ finish_decl (yyvsp[-1].ttype, yyvsp[0].ttype, yyvsp[-4].ttype, 0);
- yyval.itype = yyvsp[-2].itype; ;
- break;}
-case 302:
-#line 1882 "cp-parse.y"
-{ tree d;
- current_declspecs = yyvsp[-4].ttype;
- yyval.itype = suspend_momentary ();
- d = start_decl (yyvsp[-3].ttype, current_declspecs, 0, yyvsp[-2].ttype);
- cplus_decl_attributes (d, yyvsp[0].ttype);
- finish_decl (d, NULL_TREE, yyvsp[-1].ttype, 0); ;
- break;}
-case 303:
-#line 1894 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 304:
-#line 1896 "cp-parse.y"
-{ yyval.ttype = yyvsp[-2].ttype; ;
- break;}
-case 305:
-#line 1901 "cp-parse.y"
-{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, NULL_TREE); ;
- break;}
-case 306:
-#line 1903 "cp-parse.y"
-{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-2].ttype); ;
- break;}
-case 307:
-#line 1908 "cp-parse.y"
-{ if (strcmp (IDENTIFIER_POINTER (yyvsp[0].ttype), "packed"))
- warning ("`%s' attribute directive ignored",
- IDENTIFIER_POINTER (yyvsp[0].ttype));
- yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 308:
-#line 1913 "cp-parse.y"
-{ /* if not "aligned(n)", then issue warning */
- if (strcmp (IDENTIFIER_POINTER (yyvsp[-3].ttype), "aligned") != 0
- || TREE_CODE (yyvsp[-1].ttype) != INTEGER_CST)
- {
- warning ("`%s' attribute directive ignored",
- IDENTIFIER_POINTER (yyvsp[-3].ttype));
- yyval.ttype = yyvsp[-3].ttype;
- }
- else
- yyval.ttype = tree_cons (yyvsp[-3].ttype, yyvsp[-1].ttype, NULL_TREE); ;
- break;}
-case 309:
-#line 1924 "cp-parse.y"
-{ /* if not "format(...)", then issue warning */
- if (strcmp (IDENTIFIER_POINTER (yyvsp[-7].ttype), "format") != 0
- || TREE_CODE (yyvsp[-3].ttype) != INTEGER_CST
- || TREE_CODE (yyvsp[-1].ttype) != INTEGER_CST)
- {
- warning ("`%s' attribute directive ignored",
- IDENTIFIER_POINTER (yyvsp[-7].ttype));
- yyval.ttype = yyvsp[-7].ttype;
- }
- else
- yyval.ttype = tree_cons (yyvsp[-7].ttype, tree_cons (yyvsp[-5].ttype, tree_cons (yyvsp[-3].ttype, yyvsp[-1].ttype, NULL_TREE), NULL_TREE), NULL_TREE); ;
- break;}
-case 310:
-#line 1940 "cp-parse.y"
-{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ;
- break;}
-case 311:
-#line 1942 "cp-parse.y"
-{ yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
- break;}
-case 313:
-#line 1948 "cp-parse.y"
-{ yyval.ttype = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);
- TREE_HAS_CONSTRUCTOR (yyval.ttype) = 1;
- if (pedantic)
- pedwarn ("ANSI C++ forbids empty initializer braces"); ;
- break;}
-case 314:
-#line 1953 "cp-parse.y"
-{ yyval.ttype = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (yyvsp[-1].ttype));
- TREE_HAS_CONSTRUCTOR (yyval.ttype) = 1; ;
- break;}
-case 315:
-#line 1956 "cp-parse.y"
-{ yyval.ttype = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (yyvsp[-2].ttype));
- TREE_HAS_CONSTRUCTOR (yyval.ttype) = 1; ;
- break;}
-case 316:
-#line 1959 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 317:
-#line 1966 "cp-parse.y"
-{ yyval.ttype = build_tree_list (NULL_TREE, yyval.ttype); ;
- break;}
-case 318:
-#line 1968 "cp-parse.y"
-{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 319:
-#line 1971 "cp-parse.y"
-{ yyval.ttype = build_tree_list (yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 320:
-#line 1973 "cp-parse.y"
-{ yyval.ttype = tree_cons (yyvsp[-2].ttype, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 321:
-#line 1975 "cp-parse.y"
-{ yyval.ttype = build_tree_list (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 322:
-#line 1977 "cp-parse.y"
-{ yyval.ttype = tree_cons (yyvsp[-2].ttype, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 323:
-#line 1982 "cp-parse.y"
-{ yyvsp[0].itype = suspend_momentary ();
- yyval.ttype = start_enum (yyvsp[-1].ttype); ;
- break;}
-case 324:
-#line 1985 "cp-parse.y"
-{ yyval.ttype = finish_enum (yyvsp[-3].ttype, yyvsp[-2].ttype);
- resume_momentary ((int) yyvsp[-4].itype);
- check_for_missing_semicolon (yyvsp[-3].ttype); ;
- break;}
-case 325:
-#line 1989 "cp-parse.y"
-{ yyval.ttype = finish_enum (start_enum (yyvsp[-2].ttype), NULL_TREE);
- check_for_missing_semicolon (yyval.ttype); ;
- break;}
-case 326:
-#line 1992 "cp-parse.y"
-{ yyvsp[0].itype = suspend_momentary ();
- yyval.ttype = start_enum (make_anon_name ()); ;
- break;}
-case 327:
-#line 1995 "cp-parse.y"
-{ yyval.ttype = finish_enum (yyvsp[-3].ttype, yyvsp[-2].ttype);
- resume_momentary ((int) yyvsp[-5].itype);
- check_for_missing_semicolon (yyvsp[-3].ttype); ;
- break;}
-case 328:
-#line 1999 "cp-parse.y"
-{ yyval.ttype = finish_enum (start_enum (make_anon_name()), NULL_TREE);
- check_for_missing_semicolon (yyval.ttype); ;
- break;}
-case 329:
-#line 2002 "cp-parse.y"
-{ yyval.ttype = xref_tag (enum_type_node, yyvsp[0].ttype, NULL_TREE); ;
- break;}
-case 330:
-#line 2006 "cp-parse.y"
-{
- int semi;
- tree id;
-
-#if 0
- /* Need to rework class nesting in the
- presence of nested classes, etc. */
- shadow_tag (CLASSTYPE_AS_LIST (yyval.ttype)); */
-#endif
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- semi = yychar == ';';
- /* finish_struct nukes this anyway; if
- finish_exception does too, then it can go. */
- if (semi)
- note_got_semicolon (yyval.ttype);
-
- if (TREE_CODE (yyval.ttype) == ENUMERAL_TYPE)
- /* $$ = $1 from default rule. */;
- else if (CLASSTYPE_DECLARED_EXCEPTION (yyval.ttype))
- {
- if (! semi)
- yyval.ttype = finish_exception (yyval.ttype, yyvsp[-1].ttype);
- else
- warning ("empty exception declaration\n");
- }
- else
- {
- yyval.ttype = finish_struct (yyval.ttype, yyvsp[-1].ttype, semi);
- if (semi) note_got_semicolon (yyval.ttype);
- }
-
- pop_obstacks ();
-
- id = TYPE_IDENTIFIER (yyval.ttype);
- if (IDENTIFIER_TEMPLATE (id))
- {
- tree decl;
-
- /* I don't know if the copying of this TYPE_DECL is
- * really needed. However, it's such a small per-
- * formance penalty that the extra safety is a bargain.
- * - niklas@appli.se
- */
- push_obstacks (&permanent_obstack, &permanent_obstack);
- decl = copy_node (lookup_name (id, 0));
- if (DECL_LANG_SPECIFIC (decl))
- copy_lang_decl (decl);
- pop_obstacks ();
- undo_template_name_overload (id, 0);
- pushdecl_top_level (decl);
- }
- if (! semi)
- check_for_missing_semicolon (yyval.ttype); ;
- break;}
-case 331:
-#line 2061 "cp-parse.y"
-{
-#if 0
- /* It's no longer clear what the following error is supposed to
- accomplish. If it turns out to be needed, add a comment why. */
- if (TYPE_BINFO_BASETYPES (yyval.ttype) && !TYPE_SIZE (yyval.ttype))
- {
- error ("incomplete definition of type `%s'",
- TYPE_NAME_STRING (yyval.ttype));
- yyval.ttype = error_mark_node;
- }
-#endif
- ;
- break;}
-case 335:
-#line 2083 "cp-parse.y"
-{ if (pedantic)
- pedwarn ("ANSI C++ forbids comma at end of enumerator list"); ;
- break;}
-case 337:
-#line 2089 "cp-parse.y"
-{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ;
- break;}
-case 338:
-#line 2091 "cp-parse.y"
-{ yyval.ttype = build_tree_list (yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 339:
-#line 2093 "cp-parse.y"
-{ error ("storage class specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER (yyvsp[0].ttype));
- ;
- break;}
-case 340:
-#line 2096 "cp-parse.y"
-{ error ("type specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER (yyvsp[0].ttype));
- ;
- break;}
-case 341:
-#line 2099 "cp-parse.y"
-{ error ("type qualifier `%s' not allowed after struct or class", IDENTIFIER_POINTER (yyvsp[0].ttype));
- ;
- break;}
-case 342:
-#line 2102 "cp-parse.y"
-{ error ("no body nor ';' separates two class, struct or union declarations");
- ;
- break;}
-case 343:
-#line 2108 "cp-parse.y"
-{ aggr1: current_aggr = yyval.ttype; yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 344:
-#line 2110 "cp-parse.y"
-{ current_aggr = yyval.ttype; yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 345:
-#line 2112 "cp-parse.y"
-{ yyungetc (':', 1); goto aggr1; ;
- break;}
-case 346:
-#line 2114 "cp-parse.y"
-{ yyungetc ('{', 1);
- aggr2:
- current_aggr = yyval.ttype;
- yyval.ttype = yyvsp[-1].ttype;
- overload_template_name (yyval.ttype, 0); ;
- break;}
-case 347:
-#line 2120 "cp-parse.y"
-{ yyungetc (':', 1); goto aggr2; ;
- break;}
-case 348:
-#line 2125 "cp-parse.y"
-{ current_aggr = yyval.ttype; yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 349:
-#line 2130 "cp-parse.y"
-{
- yyval.ttype = xref_tag (current_aggr, yyvsp[0].ttype, NULL_TREE);
- ;
- break;}
-case 350:
-#line 2134 "cp-parse.y"
-{
- if (yyvsp[0].ttype)
- yyval.ttype = xref_tag (current_aggr, yyvsp[-2].ttype, yyvsp[0].ttype);
- else
- yyval.ttype = yyvsp[-1].ttype;
- ;
- break;}
-case 351:
-#line 2142 "cp-parse.y"
-{
- yyval.ttype = xref_defn_tag (current_aggr, yyvsp[0].ttype, NULL_TREE);
- ;
- break;}
-case 352:
-#line 2146 "cp-parse.y"
-{
- if (yyvsp[0].ttype)
- yyval.ttype = xref_defn_tag (current_aggr, yyvsp[-2].ttype, yyvsp[0].ttype);
- else
- yyval.ttype = yyvsp[-1].ttype;
- ;
- break;}
-case 353:
-#line 2155 "cp-parse.y"
-{ yyval.ttype = xref_tag (yyval.ttype, make_anon_name (), NULL_TREE);
- yyungetc ('{', 1); ;
- break;}
-case 356:
-#line 2163 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 357:
-#line 2165 "cp-parse.y"
-{ yyungetc(':', 1); yyval.ttype = NULL_TREE; ;
- break;}
-case 358:
-#line 2167 "cp-parse.y"
-{ yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 360:
-#line 2173 "cp-parse.y"
-{ yyval.ttype = chainon (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 361:
-#line 2178 "cp-parse.y"
-{ if (! is_aggr_typedef (yyval.ttype, 1))
- yyval.ttype = NULL_TREE;
- else yyval.ttype = build_tree_list ((tree)visibility_default, yyval.ttype); ;
- break;}
-case 362:
-#line 2182 "cp-parse.y"
-{ if (! is_aggr_typedef (yyval.ttype, 1))
- yyval.ttype = NULL_TREE;
- else yyval.ttype = build_tree_list ((tree)visibility_default, yyval.ttype); ;
- break;}
-case 363:
-#line 2186 "cp-parse.y"
-{ if (! is_aggr_typedef (yyvsp[0].ttype, 1))
- yyval.ttype = NULL_TREE;
- else yyval.ttype = build_tree_list ((tree) yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 364:
-#line 2190 "cp-parse.y"
-{ if (! is_aggr_typedef (yyvsp[0].ttype, 1))
- yyval.ttype = NULL_TREE;
- else yyval.ttype = build_tree_list ((tree) yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 365:
-#line 2197 "cp-parse.y"
-{
- /* Kludge!!! See rule "template_type" and the code
- * dealing with "template_type_seen_before_scope" in
- * yylex(). */
- yyval.ttype = yyvsp[0].ttype;
- ;
- break;}
-case 366:
-#line 2206 "cp-parse.y"
-{
- extern tree template_type_seen_before_scope;
- tree id = yyvsp[0].ttype ? TYPE_IDENTIFIER (yyvsp[0].ttype) : yyvsp[-2].ttype;
-
- /* Check the rule template_type to get this... */
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- if (yychar == SCOPE) {
- template_type_seen_before_scope = id;
- yychar = YYLEX;
- }
- ;
- break;}
-case 369:
-#line 2224 "cp-parse.y"
-{ if (yyval.ttype != ridpointers[(int)RID_VIRTUAL])
- sorry ("non-virtual visibility");
- yyval.itype = visibility_default_virtual; ;
- break;}
-case 370:
-#line 2228 "cp-parse.y"
-{ int err = 0;
- if (yyvsp[0].itype == visibility_protected)
- {
- warning ("`protected' visibility not implemented");
- yyvsp[0].itype = visibility_public;
- err++;
- }
- else if (yyvsp[0].itype == visibility_public)
- {
- if (yyvsp[-1].itype == visibility_private)
- {
- mixed:
- error ("base class cannot be public and private");
- }
- else if (yyvsp[-1].itype == visibility_default_virtual)
- yyval.itype = visibility_public_virtual;
- }
- else /* $2 == visibility_private */
- {
- if (yyvsp[-1].itype == visibility_public)
- goto mixed;
- else if (yyvsp[-1].itype == visibility_default_virtual)
- yyval.itype = visibility_private_virtual;
- }
- ;
- break;}
-case 371:
-#line 2254 "cp-parse.y"
-{ if (yyvsp[0].ttype != ridpointers[(int)RID_VIRTUAL])
- sorry ("non-virtual visibility");
- if (yyval.itype == visibility_public)
- yyval.itype = visibility_public_virtual;
- else if (yyval.itype == visibility_private)
- yyval.itype = visibility_private_virtual; ;
- break;}
-case 372:
-#line 2263 "cp-parse.y"
-{ tree t;
- push_obstacks_nochange ();
- end_temporary_allocation ();
-
- if (! IS_AGGR_TYPE (yyvsp[-1].ttype))
- {
- yyvsp[-1].ttype = make_lang_type (RECORD_TYPE);
- TYPE_NAME (yyvsp[-1].ttype) = get_identifier ("erroneous type");
- }
- if (TYPE_SIZE (yyvsp[-1].ttype))
- duplicate_tag_error (yyvsp[-1].ttype);
- if (TYPE_SIZE (yyvsp[-1].ttype) || TYPE_BEING_DEFINED (yyvsp[-1].ttype))
- {
- t = make_lang_type (TREE_CODE (yyvsp[-1].ttype));
- pushtag (TYPE_IDENTIFIER (yyvsp[-1].ttype), t);
- yyvsp[-1].ttype = t;
- }
- pushclass (yyvsp[-1].ttype, 0);
- TYPE_BEING_DEFINED (yyvsp[-1].ttype) = 1;
- t = TYPE_IDENTIFIER (yyvsp[-1].ttype);
- if (IDENTIFIER_TEMPLATE (t))
- overload_template_name (t, 1);
- ;
- break;}
-case 373:
-#line 2290 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 374:
-#line 2292 "cp-parse.y"
-{ yyval.ttype = build_tree_list ((tree)visibility_default, yyval.ttype); ;
- break;}
-case 375:
-#line 2294 "cp-parse.y"
-{ yyval.ttype = chainon (yyval.ttype, build_tree_list ((tree) yyvsp[-2].itype, yyvsp[0].ttype)); ;
- break;}
-case 377:
-#line 2300 "cp-parse.y"
-{ if (yyval.ttype == void_type_node) yyval.ttype = NULL_TREE; ;
- break;}
-case 378:
-#line 2302 "cp-parse.y"
-{ if (yyvsp[0].ttype != NULL_TREE && yyvsp[0].ttype != void_type_node)
- yyval.ttype = chainon (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 379:
-#line 2305 "cp-parse.y"
-{ if (pedantic)
- pedwarn ("ANSI C++ forbids extra semicolons here"); ;
- break;}
-case 380:
-#line 2311 "cp-parse.y"
-{
- do_components:
- if (yyvsp[-1].ttype == void_type_node)
- /* We just got some friends.
- They have been recorded elsewhere. */
- yyval.ttype = NULL_TREE;
- else if (yyvsp[-1].ttype == NULL_TREE)
- {
- tree t = groktypename (build_decl_list (yyval.ttype, NULL_TREE));
- if (t == NULL_TREE)
- {
- error ("error in component specification");
- yyval.ttype = NULL_TREE;
- }
- else if (TREE_CODE (t) == UNION_TYPE)
- {
- /* handle anonymous unions */
- if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
- yyval.ttype = build_lang_field_decl (FIELD_DECL,
- NULL_TREE, t);
- else
- {
- /* This is a local union decl with a name, but
- no components, I think this is the right thing
- to do. (mrs) */
-#if 0
- /* I copied this from below, it is probably
- needed, but I cannot prove that to myself
- right now, but if you find it is needed
- please turn it on. (mrs) */
- if (TYPE_LANG_SPECIFIC (t)
- && CLASSTYPE_DECLARED_EXCEPTION (t))
- shadow_tag (yyval.ttype);
-#endif
- yyval.ttype = NULL_TREE;
- }
- }
- else if (TREE_CODE (t) == ENUMERAL_TYPE)
- yyval.ttype = grok_enum_decls (t, NULL_TREE);
- else if (TREE_CODE (t) == RECORD_TYPE)
- {
- if (TYPE_LANG_SPECIFIC (t)
- && CLASSTYPE_DECLARED_EXCEPTION (t))
- shadow_tag (yyval.ttype);
- yyval.ttype = NULL_TREE;
- }
- else if (t != void_type_node)
- {
- error ("empty component declaration");
- yyval.ttype = NULL_TREE;
- }
- else yyval.ttype = NULL_TREE;
- }
- else
- {
- tree t = TREE_TYPE (yyvsp[-1].ttype);
- if (TREE_CODE (t) == ENUMERAL_TYPE && TREE_NONLOCAL_FLAG (t))
- yyval.ttype = grok_enum_decls (t, yyvsp[-1].ttype);
- else
- yyval.ttype = yyvsp[-1].ttype;
- }
- end_exception_decls ();
- ;
- break;}
-case 381:
-#line 2375 "cp-parse.y"
-{ yyval.ttype = groktypefield (yyval.ttype, yyvsp[-2].ttype); ;
- break;}
-case 382:
-#line 2377 "cp-parse.y"
-{ error ("missing ';' before right brace");
- yyungetc ('}', 0);
- yyval.ttype = groktypefield (yyval.ttype, yyvsp[-2].ttype); ;
- break;}
-case 383:
-#line 2381 "cp-parse.y"
-{ yyval.ttype = groktypefield (yyval.ttype, empty_parms ()); ;
- break;}
-case 384:
-#line 2383 "cp-parse.y"
-{ error ("missing ';' before right brace");
- yyungetc ('}', 0);
- yyval.ttype = groktypefield (yyval.ttype, empty_parms ()); ;
- break;}
-case 385:
-#line 2387 "cp-parse.y"
-{ goto do_components; ;
- break;}
-case 386:
-#line 2390 "cp-parse.y"
-{ yyval.ttype = grokfield (yyvsp[-1].ttype, yyval.ttype,
- NULL_TREE, NULL_TREE, NULL_TREE); ;
- break;}
-case 387:
-#line 2393 "cp-parse.y"
-{ error ("missing ';' before right brace");
- yyungetc ('}', 0);
- goto do_components; ;
- break;}
-case 388:
-#line 2397 "cp-parse.y"
-{ yyval.ttype = groktypefield (yyval.ttype, yyvsp[-2].ttype); ;
- break;}
-case 389:
-#line 2399 "cp-parse.y"
-{ error ("missing ';' before right brace");
- yyungetc ('}', 0);
- yyval.ttype = groktypefield (yyval.ttype, yyvsp[-2].ttype); ;
- break;}
-case 390:
-#line 2403 "cp-parse.y"
-{ yyval.ttype = groktypefield (yyval.ttype, empty_parms ()); ;
- break;}
-case 391:
-#line 2405 "cp-parse.y"
-{ error ("missing ';' before right brace");
- yyungetc ('}', 0);
- yyval.ttype = groktypefield (yyval.ttype, empty_parms ()); ;
- break;}
-case 392:
-#line 2409 "cp-parse.y"
-{ yyval.ttype = grokbitfield (NULL_TREE, NULL_TREE, yyvsp[-1].ttype); ;
- break;}
-case 393:
-#line 2411 "cp-parse.y"
-{ error ("missing ';' before right brace");
- yyungetc ('}', 0);
- yyval.ttype = grokbitfield (NULL_TREE, NULL_TREE, yyvsp[-1].ttype); ;
- break;}
-case 394:
-#line 2415 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 395:
-#line 2420 "cp-parse.y"
-{ yyval.ttype = finish_method (yyval.ttype); ;
- break;}
-case 396:
-#line 2422 "cp-parse.y"
-{ yyval.ttype = finish_method (yyval.ttype); ;
- break;}
-case 397:
-#line 2424 "cp-parse.y"
-{ yyval.ttype = grokfield (yyval.ttype, NULL_TREE, yyvsp[-1].ttype, NULL_TREE, NULL_TREE); ;
- break;}
-case 398:
-#line 2426 "cp-parse.y"
-{ error ("missing ';' before right brace");
- yyungetc ('}', 0);
- yyval.ttype = grokfield (yyval.ttype, NULL_TREE, yyvsp[-1].ttype, NULL_TREE, NULL_TREE); ;
- break;}
-case 399:
-#line 2433 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 401:
-#line 2436 "cp-parse.y"
-{
- /* In this context, void_type_node encodes
- friends. They have been recorded elsewhere. */
- if (yyval.ttype == void_type_node)
- yyval.ttype = yyvsp[0].ttype;
- else
- yyval.ttype = chainon (yyval.ttype, yyvsp[0].ttype);
- ;
- break;}
-case 402:
-#line 2448 "cp-parse.y"
-{ current_declspecs = yyvsp[-4].ttype;
- yyval.ttype = grokfield (yyval.ttype, current_declspecs, yyvsp[-2].ttype, NULL_TREE, yyvsp[-1].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 403:
-#line 2452 "cp-parse.y"
-{ current_declspecs = yyvsp[-6].ttype;
- yyval.ttype = grokfield (yyval.ttype, current_declspecs, yyvsp[-4].ttype, yyvsp[0].ttype, yyvsp[-3].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[-2].ttype); ;
- break;}
-case 404:
-#line 2456 "cp-parse.y"
-{ current_declspecs = yyvsp[-4].ttype;
- yyval.ttype = grokbitfield (yyval.ttype, current_declspecs, yyvsp[-1].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 405:
-#line 2460 "cp-parse.y"
-{ current_declspecs = yyvsp[-3].ttype;
- yyval.ttype = grokbitfield (yyval.ttype, current_declspecs, yyvsp[-1].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 406:
-#line 2464 "cp-parse.y"
-{ current_declspecs = yyvsp[-2].ttype;
- yyval.ttype = grokbitfield (NULL_TREE, NULL_TREE, yyvsp[0].ttype); ;
- break;}
-case 407:
-#line 2470 "cp-parse.y"
-{ yyval.ttype = grokfield (yyval.ttype, current_declspecs, yyvsp[-2].ttype, NULL_TREE, yyvsp[-1].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 408:
-#line 2473 "cp-parse.y"
-{ yyval.ttype = grokfield (yyval.ttype, current_declspecs, yyvsp[-4].ttype, yyvsp[0].ttype, yyvsp[-3].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[-2].ttype); ;
- break;}
-case 409:
-#line 2476 "cp-parse.y"
-{ yyval.ttype = grokbitfield (yyval.ttype, current_declspecs, yyvsp[-1].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 410:
-#line 2479 "cp-parse.y"
-{ yyval.ttype = grokbitfield (yyval.ttype, current_declspecs, yyvsp[-1].ttype);
- cplus_decl_attributes (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 411:
-#line 2482 "cp-parse.y"
-{ yyval.ttype = grokbitfield (NULL_TREE, NULL_TREE, yyvsp[0].ttype); ;
- break;}
-case 413:
-#line 2492 "cp-parse.y"
-{ TREE_CHAIN (yyvsp[0].ttype) = yyval.ttype; yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 414:
-#line 2497 "cp-parse.y"
-{ yyval.ttype = build_enumerator (yyval.ttype, NULL_TREE); ;
- break;}
-case 415:
-#line 2499 "cp-parse.y"
-{ yyval.ttype = build_enumerator (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 416:
-#line 2504 "cp-parse.y"
-{ yyval.ttype = build_decl_list (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 417:
-#line 2506 "cp-parse.y"
-{ yyval.ttype = build_decl_list (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 418:
-#line 2511 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 420:
-#line 2514 "cp-parse.y"
-{ yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 421:
-#line 2519 "cp-parse.y"
-{ yyval.ttype = IDENTIFIER_AS_LIST (yyval.ttype); ;
- break;}
-case 422:
-#line 2521 "cp-parse.y"
-{ yyval.ttype = decl_tree_cons (NULL_TREE, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 423:
-#line 2526 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 424:
-#line 2528 "cp-parse.y"
-{ yyval.ttype = decl_tree_cons (NULL_TREE, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 425:
-#line 2536 "cp-parse.y"
-{ yyval.itype = suspend_momentary (); ;
- break;}
-case 426:
-#line 2537 "cp-parse.y"
-{ resume_momentary ((int) yyvsp[-1].itype); yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 427:
-#line 2543 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 428:
-#line 2545 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 429:
-#line 2547 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, empty_parms (), yyvsp[0].ttype); ;
- break;}
-case 430:
-#line 2549 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, NULL_TREE, NULL_TREE); ;
- break;}
-case 431:
-#line 2551 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 432:
-#line 2553 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, yyval.ttype, NULL_TREE); ;
- break;}
-case 433:
-#line 2555 "cp-parse.y"
-{ yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 434:
-#line 2557 "cp-parse.y"
-{ yyval.ttype = make_pointer_declarator (yyvsp[-2].ttype, yyvsp[-1].ttype); ;
- break;}
-case 435:
-#line 2559 "cp-parse.y"
-{ see_typename (); ;
- break;}
-case 437:
-#line 2562 "cp-parse.y"
-{ yyval.ttype = make_reference_declarator (yyvsp[-2].ttype, yyvsp[-1].ttype); ;
- break;}
-case 438:
-#line 2564 "cp-parse.y"
-{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
- break;}
-case 439:
-#line 2566 "cp-parse.y"
-{ yyval.ttype = make_reference_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
- break;}
-case 441:
-#line 2572 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 442:
-#line 2574 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 443:
-#line 2576 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, empty_parms (), yyvsp[0].ttype); ;
- break;}
-case 444:
-#line 2578 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, NULL_TREE, NULL_TREE); ;
- break;}
-case 445:
-#line 2580 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 446:
-#line 2582 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, yyval.ttype, NULL_TREE); ;
- break;}
-case 447:
-#line 2584 "cp-parse.y"
-{ yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 448:
-#line 2586 "cp-parse.y"
-{ see_typename (); ;
- break;}
-case 450:
-#line 2589 "cp-parse.y"
-{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
- break;}
-case 451:
-#line 2591 "cp-parse.y"
-{ yyval.ttype = make_reference_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
- break;}
-case 452:
-#line 2599 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 453:
-#line 2601 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 454:
-#line 2603 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, empty_parms (), yyvsp[0].ttype); ;
- break;}
-case 455:
-#line 2605 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, NULL_TREE, NULL_TREE); ;
- break;}
-case 456:
-#line 2607 "cp-parse.y"
-{ yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 457:
-#line 2609 "cp-parse.y"
-{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
- break;}
-case 458:
-#line 2611 "cp-parse.y"
-{ yyval.ttype = make_reference_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
- break;}
-case 459:
-#line 2613 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 460:
-#line 2615 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, yyval.ttype, NULL_TREE); ;
- break;}
-case 461:
-#line 2617 "cp-parse.y"
-{ see_typename (); ;
- break;}
-case 462:
-#line 2621 "cp-parse.y"
-{ see_typename (); ;
- break;}
-case 463:
-#line 2624 "cp-parse.y"
-{
- destructor_name:
- see_typename ();
- yyval.ttype = build_parse_node (BIT_NOT_EXPR, yyvsp[0].ttype);
- ;
- break;}
-case 464:
-#line 2630 "cp-parse.y"
-{ goto destructor_name; ;
- break;}
-case 465:
-#line 2632 "cp-parse.y"
-{ goto destructor_name; ;
- break;}
-case 466:
-#line 2634 "cp-parse.y"
-{ see_typename ();
- if (TREE_CODE (yyval.ttype) != SCOPE_REF)
- yyval.ttype = build_push_scope (yyval.ttype, yyvsp[0].ttype);
- else if (TREE_OPERAND (yyval.ttype, 1) == NULL_TREE)
- TREE_OPERAND (yyval.ttype, 1) = yyvsp[0].ttype;
- else
- yyval.ttype = build_parse_node (SCOPE_REF, yyval.ttype, yyvsp[0].ttype);
- ;
- break;}
-case 467:
-#line 2643 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 468:
-#line 2645 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, build_parse_node (CALL_EXPR, yyvsp[-4].ttype, yyvsp[-2].ttype, yyvsp[0].ttype)); ;
- break;}
-case 469:
-#line 2647 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, build_parse_node (CALL_EXPR, yyvsp[-4].ttype, yyvsp[-2].ttype, yyvsp[0].ttype)); ;
- break;}
-case 470:
-#line 2649 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, build_parse_node (CALL_EXPR, yyvsp[-2].ttype, empty_parms (), yyvsp[0].ttype)); ;
- break;}
-case 471:
-#line 2651 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, build_parse_node (CALL_EXPR, yyvsp[-4].ttype, NULL_TREE, NULL_TREE)); ;
- break;}
-case 472:
-#line 2654 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 473:
-#line 2656 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, build_parse_node (CALL_EXPR, yyvsp[-4].ttype, yyvsp[-2].ttype, yyvsp[0].ttype)); ;
- break;}
-case 474:
-#line 2658 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, build_parse_node (CALL_EXPR, yyvsp[-4].ttype, yyvsp[-2].ttype, yyvsp[0].ttype)); ;
- break;}
-case 475:
-#line 2660 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, build_parse_node (CALL_EXPR, yyvsp[-2].ttype, empty_parms (), yyvsp[0].ttype)); ;
- break;}
-case 476:
-#line 2662 "cp-parse.y"
-{ yyval.ttype = build_push_scope (yyval.ttype, build_parse_node (CALL_EXPR, yyvsp[-4].ttype, NULL_TREE, NULL_TREE)); ;
- break;}
-case 477:
-#line 2664 "cp-parse.y"
-{ yyval.ttype = build_parse_node (SCOPE_REF, NULL_TREE, yyvsp[0].ttype); ;
- break;}
-case 478:
-#line 2668 "cp-parse.y"
-{ yyval.ttype = resolve_scope_to_name (NULL_TREE, yyval.ttype);
- if (yyval.ttype == NULL_TREE)
- {
- error ("undefined explicitly scoped type");
- yyval.ttype = error_mark_node;
- }
- ;
- break;}
-case 479:
-#line 2676 "cp-parse.y"
-{
- if (yyval.ttype == error_mark_node)
- /* leave it alone */;
- else
- {
- yyval.ttype = resolve_scope_to_name (NULL_TREE, TYPE_IDENTIFIER (yyval.ttype));
- if (yyval.ttype == NULL_TREE)
- {
- error ("undefined explicitly scoped type");
- yyval.ttype = error_mark_node;
- }
- }
-/* if ($3) popclass (1); */
- ;
- break;}
-case 482:
-#line 2697 "cp-parse.y"
-{
- /* Kludge!!! See rule "template_type" and the code
- * dealing with "template_type_seen_before_scope" in
- * yylex(). */
- yyval.ttype = yyvsp[0].ttype;
- ;
- break;}
-case 483:
-#line 2719 "cp-parse.y"
-{ see_typename ();
- yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 484:
-#line 2723 "cp-parse.y"
-{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
- break;}
-case 485:
-#line 2725 "cp-parse.y"
-{ yyval.ttype = make_pointer_declarator (yyvsp[0].ttype, NULL_TREE); ;
- break;}
-case 486:
-#line 2727 "cp-parse.y"
-{ see_typename (); ;
- break;}
-case 487:
-#line 2729 "cp-parse.y"
-{ yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 488:
-#line 2731 "cp-parse.y"
-{ yyval.ttype = make_reference_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ;
- break;}
-case 489:
-#line 2733 "cp-parse.y"
-{ yyval.ttype = make_reference_declarator (yyvsp[0].ttype, NULL_TREE); ;
- break;}
-case 490:
-#line 2735 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 491:
-#line 2737 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, yyval.ttype, empty_parms (), yyvsp[0].ttype); ;
- break;}
-case 492:
-#line 2739 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 493:
-#line 2741 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, yyval.ttype, NULL_TREE); ;
- break;}
-case 494:
-#line 2743 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, NULL_TREE, yyvsp[-2].ttype, yyvsp[0].ttype); ;
- break;}
-case 495:
-#line 2745 "cp-parse.y"
-{ yyval.ttype = build_parse_node (CALL_EXPR, NULL_TREE, empty_parms (), yyvsp[0].ttype); ;
- break;}
-case 496:
-#line 2747 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, NULL_TREE, yyvsp[-1].ttype); ;
- break;}
-case 497:
-#line 2749 "cp-parse.y"
-{ yyval.ttype = build_parse_node (ARRAY_REF, NULL_TREE, NULL_TREE); ;
- break;}
-case 498:
-#line 2754 "cp-parse.y"
-{ tree t;
- t = yyval.ttype;
- while (TREE_OPERAND (t, 1))
- t = TREE_OPERAND (t, 1);
- TREE_OPERAND (t, 1) = build_parse_node (INDIRECT_REF, 0);
- ;
- break;}
-case 499:
-#line 2761 "cp-parse.y"
-{ tree t;
- t = yyval.ttype;
- while (TREE_OPERAND (t, 1))
- t = TREE_OPERAND (t, 1);
- TREE_OPERAND (t, 1) = build_parse_node (INDIRECT_REF, yyvsp[0].ttype);
- ;
- break;}
-case 500:
-#line 2768 "cp-parse.y"
-{ tree t;
- t = yyval.ttype;
- while (TREE_OPERAND (t, 1))
- t = TREE_OPERAND (t, 1);
- TREE_OPERAND (t, 1) = build_parse_node (ADDR_EXPR, 0);
- ;
- break;}
-case 501:
-#line 2775 "cp-parse.y"
-{ tree t;
- t = yyval.ttype;
- while (TREE_OPERAND (t, 1))
- t = TREE_OPERAND (t, 1);
- TREE_OPERAND (t, 1) = build_parse_node (ADDR_EXPR, yyvsp[0].ttype);
- ;
- break;}
-case 502:
-#line 2785 "cp-parse.y"
-{ tree t;
- t = yyval.ttype;
- while (TREE_OPERAND (t, 1))
- t = TREE_OPERAND (t, 1);
- TREE_OPERAND (t, 1) = build_parse_node (INDIRECT_REF, yyvsp[0].ttype);
- ;
- break;}
-case 503:
-#line 2792 "cp-parse.y"
-{ tree t;
- t = yyval.ttype;
- while (TREE_OPERAND (t, 1))
- t = TREE_OPERAND (t, 1);
- TREE_OPERAND (t, 1) = build_parse_node (ADDR_EXPR, yyvsp[0].ttype);
- ;
- break;}
-case 509:
-#line 2819 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0); ;
- break;}
-case 511:
-#line 2831 "cp-parse.y"
-{ if (pedantic)
- pedwarn ("ANSI C++ forbids label declarations"); ;
- break;}
-case 514:
-#line 2842 "cp-parse.y"
-{ tree link;
- for (link = yyvsp[-1].ttype; link; link = TREE_CHAIN (link))
- {
- tree label = shadow_label (TREE_VALUE (link));
- C_DECLARED_LABEL_FLAG (label) = 1;
- declare_nonlocal_label (label);
- }
- ;
- break;}
-case 515:
-#line 2856 "cp-parse.y"
-{;
- break;}
-case 517:
-#line 2861 "cp-parse.y"
-{ yyval.ttype = convert (void_type_node, integer_zero_node); ;
- break;}
-case 518:
-#line 2863 "cp-parse.y"
-{ pop_implicit_try_blocks (NULL_TREE);
- expand_end_bindings (getdecls (), kept_level_p (), 1);
- yyval.ttype = poplevel (kept_level_p (), 1, 0);
- pop_momentary (); ;
- break;}
-case 519:
-#line 2868 "cp-parse.y"
-{ pop_implicit_try_blocks (NULL_TREE);
- expand_end_bindings (getdecls (), kept_level_p (), 1);
- yyval.ttype = poplevel (kept_level_p (), 0, 0);
- pop_momentary (); ;
- break;}
-case 520:
-#line 2876 "cp-parse.y"
-{ cond_stmt_keyword = "if"; ;
- break;}
-case 521:
-#line 2878 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- expand_start_cond (truthvalue_conversion (yyvsp[0].ttype), 0); ;
- break;}
-case 523:
-#line 2885 "cp-parse.y"
-{ finish_stmt (); ;
- break;}
-case 524:
-#line 2887 "cp-parse.y"
-{ pop_implicit_try_blocks (NULL_TREE);
- expand_end_bindings (getdecls (), kept_level_p (), 1);
- yyval.ttype = poplevel (kept_level_p (), 1, 0);
- pop_momentary (); ;
- break;}
-case 525:
-#line 2895 "cp-parse.y"
-{ finish_stmt (); ;
- break;}
-case 527:
-#line 2901 "cp-parse.y"
-{ finish_stmt (); ;
- break;}
-case 528:
-#line 2903 "cp-parse.y"
-{
- tree expr = yyvsp[-1].ttype;
- emit_line_note (input_filename, lineno);
- /* Do default conversion if safe and possibly important,
- in case within ({...}). */
- if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
- && lvalue_p (expr))
- || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
- expr = default_conversion (expr);
- cplus_expand_expr_stmt (expr);
- clear_momentary ();
- finish_stmt (); ;
- break;}
-case 529:
-#line 2916 "cp-parse.y"
-{ expand_start_else (); ;
- break;}
-case 530:
-#line 2918 "cp-parse.y"
-{ expand_end_cond ();
- finish_stmt (); ;
- break;}
-case 531:
-#line 2921 "cp-parse.y"
-{ expand_end_cond ();
- finish_stmt (); ;
- break;}
-case 532:
-#line 2924 "cp-parse.y"
-{ emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop (1);
- cond_stmt_keyword = "while"; ;
- break;}
-case 533:
-#line 2929 "cp-parse.y"
-{ expand_exit_loop_if_false (0, truthvalue_conversion (yyvsp[0].ttype)); ;
- break;}
-case 534:
-#line 2931 "cp-parse.y"
-{ expand_end_loop ();
- finish_stmt (); ;
- break;}
-case 535:
-#line 2934 "cp-parse.y"
-{ emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop_continue_elsewhere (1); ;
- break;}
-case 536:
-#line 2938 "cp-parse.y"
-{ expand_loop_continue_here ();
- cond_stmt_keyword = "do"; ;
- break;}
-case 537:
-#line 2941 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- expand_exit_loop_if_false (0, truthvalue_conversion (yyvsp[-1].ttype));
- expand_end_loop ();
- clear_momentary ();
- finish_stmt (); ;
- break;}
-case 538:
-#line 2947 "cp-parse.y"
-{ emit_nop ();
- emit_line_note (input_filename, lineno);
- if (yyvsp[0].ttype) cplus_expand_expr_stmt (yyvsp[0].ttype);
- expand_start_loop_continue_elsewhere (1); ;
- break;}
-case 539:
-#line 2952 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- if (yyvsp[-1].ttype) expand_exit_loop_if_false (0, truthvalue_conversion (yyvsp[-1].ttype)); ;
- break;}
-case 540:
-#line 2957 "cp-parse.y"
-{ push_momentary (); ;
- break;}
-case 541:
-#line 2959 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- expand_loop_continue_here ();
- if (yyvsp[-3].ttype) cplus_expand_expr_stmt (yyvsp[-3].ttype);
- pop_momentary ();
- expand_end_loop ();
- finish_stmt (); ;
- break;}
-case 542:
-#line 2966 "cp-parse.y"
-{ emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop_continue_elsewhere (1); ;
- break;}
-case 543:
-#line 2970 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- if (yyvsp[-1].ttype) expand_exit_loop_if_false (0, truthvalue_conversion (yyvsp[-1].ttype)); ;
- break;}
-case 544:
-#line 2975 "cp-parse.y"
-{ push_momentary ();
- yyvsp[0].itype = lineno; ;
- break;}
-case 545:
-#line 2978 "cp-parse.y"
-{ emit_line_note (input_filename, (int) yyvsp[-2].itype);
- expand_loop_continue_here ();
- if (yyvsp[-3].ttype) cplus_expand_expr_stmt (yyvsp[-3].ttype);
- pop_momentary ();
- expand_end_loop ();
- pop_implicit_try_blocks (NULL_TREE);
- if (yyvsp[-8].itype)
- {
- register int keep = yyvsp[-8].itype > 0;
- if (keep) expand_end_bindings (0, keep, 1);
- poplevel (keep, 1, 0);
- pop_momentary ();
- }
- finish_stmt ();
- ;
- break;}
-case 546:
-#line 2994 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- c_expand_start_case (yyvsp[-1].ttype);
- /* Don't let the tree nodes for $3 be discarded by
- clear_momentary during the parsing of the next stmt. */
- push_momentary (); ;
- break;}
-case 547:
-#line 3000 "cp-parse.y"
-{ expand_end_case (yyvsp[-3].ttype);
- pop_momentary ();
- finish_stmt (); ;
- break;}
-case 548:
-#line 3004 "cp-parse.y"
-{ register tree value = yyvsp[-1].ttype;
- register tree label
- = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
- Strip such NOP_EXPRs. */
- if (TREE_CODE (value) == NOP_EXPR
- && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
- value = TREE_OPERAND (value, 0);
-
- if (TREE_READONLY_DECL_P (value))
- {
- value = decl_constant_value (value);
- /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
- Strip such NOP_EXPRs. */
- if (TREE_CODE (value) == NOP_EXPR
- && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
- value = TREE_OPERAND (value, 0);
- }
- value = fold (value);
-
- if (TREE_CODE (value) != INTEGER_CST
- && value != error_mark_node)
- {
- error ("case label does not reduce to an integer constant");
- value = error_mark_node;
- }
- else
- /* Promote char or short to int. */
- value = default_conversion (value);
- if (value != error_mark_node)
- {
- tree duplicate;
- int success = pushcase (value, label, &duplicate);
- if (success == 1)
- error ("case label not within a switch statement");
- else if (success == 2)
- {
- error ("duplicate case value");
- error_with_decl (duplicate, "this is the first entry for that value");
- }
- else if (success == 3)
- warning ("case value out of range");
- else if (success == 5)
- error ("case label within scope of cleanup or variable array");
- }
- define_case_label (label);
- ;
- break;}
-case 550:
-#line 3054 "cp-parse.y"
-{ register tree value1 = yyvsp[-3].ttype;
- register tree value2 = yyvsp[-1].ttype;
- register tree label
- = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- if (pedantic)
- pedwarn ("ANSI C++ forbids range expressions in switch statement");
-
- /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
- Strip such NOP_EXPRs. */
- if (TREE_CODE (value1) == NOP_EXPR
- && TREE_TYPE (value1) == TREE_TYPE (TREE_OPERAND (value1, 0)))
- value1 = TREE_OPERAND (value1, 0);
-
- if (TREE_READONLY_DECL_P (value1))
- {
- value1 = decl_constant_value (value1);
- /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
- Strip such NOP_EXPRs. */
- if (TREE_CODE (value1) == NOP_EXPR
- && TREE_TYPE (value1) == TREE_TYPE (TREE_OPERAND (value1, 0)))
- value1 = TREE_OPERAND (value1, 0);
- }
- value1 = fold (value1);
-
- /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
- Strip such NOP_EXPRs. */
- if (TREE_CODE (value2) == NOP_EXPR
- && TREE_TYPE (value2) == TREE_TYPE (TREE_OPERAND (value2, 0)))
- value2 = TREE_OPERAND (value2, 0);
-
- if (TREE_READONLY_DECL_P (value2))
- {
- value2 = decl_constant_value (value2);
- /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
- Strip such NOP_EXPRs. */
- if (TREE_CODE (value2) == NOP_EXPR
- && TREE_TYPE (value2) == TREE_TYPE (TREE_OPERAND (value2, 0)))
- value2 = TREE_OPERAND (value2, 0);
- }
- value2 = fold (value2);
-
-
- if (TREE_CODE (value1) != INTEGER_CST
- && value1 != error_mark_node)
- {
- error ("case label does not reduce to an integer constant");
- value1 = error_mark_node;
- }
- if (TREE_CODE (value2) != INTEGER_CST
- && value2 != error_mark_node)
- {
- error ("case label does not reduce to an integer constant");
- value2 = error_mark_node;
- }
- if (value1 != error_mark_node
- && value2 != error_mark_node)
- {
- tree duplicate;
- int success = pushcase_range (value1, value2, label,
- &duplicate);
- if (success == 1)
- error ("case label not within a switch statement");
- else if (success == 2)
- {
- error ("duplicate (or overlapping) case value");
- error_with_decl (duplicate, "this is the first entry overlapping that value");
- }
- else if (success == 3)
- warning ("case value out of range");
- else if (success == 4)
- warning ("empty range specified");
- else if (success == 5)
- error ("case label within scope of cleanup or variable array");
- }
- define_case_label (label);
- ;
- break;}
-case 552:
-#line 3133 "cp-parse.y"
-{
- tree duplicate;
- register tree label
- = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- int success = pushcase (NULL_TREE, label, &duplicate);
- if (success == 1)
- error ("default label not within a switch statement");
- else if (success == 2)
- {
- error ("multiple default labels in one switch");
- error_with_decl (duplicate, "this is the first default label");
- }
- define_case_label (NULL_TREE);
- ;
- break;}
-case 554:
-#line 3149 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- if ( ! expand_exit_something ())
- error ("break statement not within loop or switch"); ;
- break;}
-case 555:
-#line 3153 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- if (! expand_continue_loop (0))
- error ("continue statement not within a loop"); ;
- break;}
-case 556:
-#line 3157 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- c_expand_return (NULL_TREE); ;
- break;}
-case 557:
-#line 3160 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- c_expand_return (yyvsp[-1].ttype);
- finish_stmt ();
- ;
- break;}
-case 558:
-#line 3165 "cp-parse.y"
-{ if (TREE_CHAIN (yyvsp[-2].ttype)) yyvsp[-2].ttype = combine_strings (yyvsp[-2].ttype);
- emit_line_note (input_filename, lineno);
- expand_asm (yyvsp[-2].ttype);
- finish_stmt ();
- ;
- break;}
-case 559:
-#line 3172 "cp-parse.y"
-{ if (TREE_CHAIN (yyvsp[-4].ttype)) yyvsp[-4].ttype = combine_strings (yyvsp[-4].ttype);
- emit_line_note (input_filename, lineno);
- c_expand_asm_operands (yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE, NULL_TREE,
- yyvsp[-6].ttype == ridpointers[(int)RID_VOLATILE],
- input_filename, lineno);
- finish_stmt ();
- ;
- break;}
-case 560:
-#line 3181 "cp-parse.y"
-{ if (TREE_CHAIN (yyvsp[-6].ttype)) yyvsp[-6].ttype = combine_strings (yyvsp[-6].ttype);
- emit_line_note (input_filename, lineno);
- c_expand_asm_operands (yyvsp[-6].ttype, yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE,
- yyvsp[-8].ttype == ridpointers[(int)RID_VOLATILE],
- input_filename, lineno);
- finish_stmt ();
- ;
- break;}
-case 561:
-#line 3191 "cp-parse.y"
-{ if (TREE_CHAIN (yyvsp[-8].ttype)) yyvsp[-8].ttype = combine_strings (yyvsp[-8].ttype);
- emit_line_note (input_filename, lineno);
- c_expand_asm_operands (yyvsp[-8].ttype, yyvsp[-6].ttype, yyvsp[-4].ttype, yyvsp[-2].ttype,
- yyvsp[-10].ttype == ridpointers[(int)RID_VOLATILE],
- input_filename, lineno);
- finish_stmt ();
- ;
- break;}
-case 562:
-#line 3199 "cp-parse.y"
-{ emit_line_note (input_filename, lineno);
- expand_computed_goto (yyvsp[-1].ttype); ;
- break;}
-case 563:
-#line 3202 "cp-parse.y"
-{ tree decl;
- emit_line_note (input_filename, lineno);
- decl = lookup_label (yyvsp[-1].ttype);
- TREE_USED (decl) = 1;
- expand_goto (decl); ;
- break;}
-case 564:
-#line 3208 "cp-parse.y"
-{ finish_stmt (); ;
- break;}
-case 565:
-#line 3210 "cp-parse.y"
-{ error ("label must be followed by statement");
- yyungetc ('}', 0);
- finish_stmt (); ;
- break;}
-case 566:
-#line 3214 "cp-parse.y"
-{ finish_stmt (); ;
- break;}
-case 567:
-#line 3217 "cp-parse.y"
-{ cplus_expand_throw (NULL_TREE); ;
- break;}
-case 568:
-#line 3218 "cp-parse.y"
-{ cplus_expand_throw (yyvsp[-1].ttype); ;
- break;}
-case 569:
-#line 3220 "cp-parse.y"
-{ cplus_expand_raise (yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE, 0);
- finish_stmt (); ;
- break;}
-case 570:
-#line 3223 "cp-parse.y"
-{ cplus_expand_raise (yyvsp[-2].ttype, NULL_TREE, NULL_TREE, 0);
- finish_stmt (); ;
- break;}
-case 571:
-#line 3226 "cp-parse.y"
-{ cplus_expand_raise (yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE, 0);
- finish_stmt (); ;
- break;}
-case 572:
-#line 3229 "cp-parse.y"
-{ cplus_expand_raise (yyvsp[-2].ttype, NULL_TREE, NULL_TREE, 0);
- finish_stmt (); ;
- break;}
-case 573:
-#line 3232 "cp-parse.y"
-{ cplus_expand_reraise (yyvsp[-1].ttype);
- finish_stmt (); ;
- break;}
-case 574:
-#line 3235 "cp-parse.y"
-{
- tree decl = cplus_expand_end_try (yyvsp[-3].itype);
- yyvsp[-2].ttype = current_exception_type;
- yyvsp[0].ttype = current_exception_decl;
- yyval.ttype = current_exception_object;
- cplus_expand_start_except (yyvsp[-1].ttype, decl);
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
- ;
- break;}
-case 575:
-#line 3247 "cp-parse.y"
-{
- tree decls = getdecls ();
- /* If there is a default exception to handle,
- handle it here. */
- if (yyvsp[-1].ttype)
- {
- tree decl = build_decl (CPLUS_CATCH_DECL, NULL_TREE, 0);
- tree block;
-
- pushlevel (1);
- expand_start_bindings (0);
- expand_expr (yyvsp[-1].ttype, 0, 0, 0);
- expand_end_bindings (0, 1, 0);
- block = poplevel (1, 0, 0);
-
- /* This is a catch block. */
- TREE_LANG_FLAG_2 (block) = 1;
- BLOCK_VARS (block) = decl;
- }
-
- expand_end_bindings (decls, decls != 0, 1);
- poplevel (decls != 0, 1, 0);
- pop_momentary ();
- current_exception_type = yyvsp[-5].ttype;
- current_exception_decl = yyvsp[-3].ttype;
- current_exception_object = yyvsp[-2].ttype;
- cplus_expand_end_except (yyvsp[-1].ttype);
- ;
- break;}
-case 576:
-#line 3276 "cp-parse.y"
-{
- cplus_expand_end_try (yyvsp[-1].itype);
- /* These are the important actions of
- `cplus_expand_end_except' which we must emulate. */
- if (expand_escape_except ())
- expand_end_except ();
- expand_end_bindings (0, 0, 1);
- poplevel (0, 0, 0);
- ;
- break;}
-case 577:
-#line 3286 "cp-parse.y"
-{
- tree decl = cplus_expand_end_try (yyvsp[-2].itype);
- yyvsp[-1].ttype = current_exception_type;
- yyvsp[0].ttype = current_exception_decl;
- yyval.ttype = current_exception_object;
- cplus_expand_start_except (NULL, decl);
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
- ;
- break;}
-case 578:
-#line 3298 "cp-parse.y"
-{
- tree decls = getdecls ();
- /* If there is a default exception to handle,
- handle it here. */
- if (yyvsp[0].ttype)
- {
- tree decl = build_decl (CPLUS_CATCH_DECL, NULL_TREE, 0);
- tree block;
-
- pushlevel (1);
- expand_start_bindings (0);
- expand_expr (yyvsp[0].ttype, 0, 0, 0);
- expand_end_bindings (0, 1, 0);
- block = poplevel (1, 0, 0);
-
- /* This is a catch block. */
- TREE_LANG_FLAG_2 (block) = 1;
- BLOCK_VARS (block) = decl;
- }
-
- expand_end_bindings (decls, decls != 0, 1);
- poplevel (decls != 0, 1, 0);
- pop_momentary ();
- current_exception_type = yyvsp[-3].ttype;
- current_exception_decl = yyvsp[-2].ttype;
- current_exception_object = yyvsp[-1].ttype;
- cplus_expand_end_except (yyvsp[0].ttype);
- ;
- break;}
-case 579:
-#line 3327 "cp-parse.y"
-{ tree name = get_identifier ("(compiler error)");
- tree orig_ex_type = current_exception_type;
- tree orig_ex_decl = current_exception_decl;
- tree orig_ex_obj = current_exception_object;
- tree decl = cplus_expand_end_try (yyvsp[-2].itype), decls;
-
- /* Start hidden EXCEPT. */
- cplus_expand_start_except (name, decl);
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
-
- /* This sets up the reraise. */
- cplus_expand_reraise (yyvsp[0].ttype);
-
- decls = getdecls ();
- expand_end_bindings (decls, decls != 0, 1);
- poplevel (decls != 0, 1, 0);
- pop_momentary ();
- current_exception_type = orig_ex_type;
- current_exception_decl = orig_ex_decl;
- current_exception_object = orig_ex_obj;
- /* This will reraise for us. */
- cplus_expand_end_except (error_mark_node);
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- if (yychar != ';')
- error ("missing ';' after reraise statement");
- ;
- break;}
-case 580:
-#line 3358 "cp-parse.y"
-{ yyerror ("`except' missing after `try' statement");
- /* Terminate the binding contour started by special
- code in `.pushlevel'. Automagically pops off
- the conditional we started for `try' stmt. */
- cplus_expand_end_try (yyvsp[0].itype);
- expand_end_bindings (0, 0, 1);
- poplevel (0, 0, 0);
- pop_momentary ();
- YYERROR; ;
- break;}
-case 581:
-#line 3373 "cp-parse.y"
-{
- yyval.itype = 1;
- pop_implicit_try_blocks (NULL_TREE);
- ;
- break;}
-case 582:
-#line 3378 "cp-parse.y"
-{
- yyval.itype = 1;
- pop_implicit_try_blocks (NULL_TREE);
- ;
- break;}
-case 583:
-#line 3383 "cp-parse.y"
-{
- yyval.itype = 0;
- pop_implicit_try_blocks (NULL_TREE);
- ;
- break;}
-case 584:
-#line 3391 "cp-parse.y"
-{ tree label;
- do_label:
- label = define_label (input_filename, lineno, yyvsp[-1].ttype);
- if (label)
- expand_label (label);
- ;
- break;}
-case 585:
-#line 3398 "cp-parse.y"
-{ goto do_label; ;
- break;}
-case 586:
-#line 3400 "cp-parse.y"
-{ tree label = define_label (input_filename, lineno, yyvsp[0].ttype);
- if (label)
- expand_label (label);
- ;
- break;}
-case 587:
-#line 3406 "cp-parse.y"
-{ cplus_expand_start_try (0); ;
- break;}
-case 589:
-#line 3412 "cp-parse.y"
-{
- yyval.itype = 1;
- pop_implicit_try_blocks (NULL_TREE);
- ;
- break;}
-case 590:
-#line 3417 "cp-parse.y"
-{
- yyval.itype = 1;
- pop_implicit_try_blocks (NULL_TREE);
- ;
- break;}
-case 591:
-#line 3422 "cp-parse.y"
-{
- yyval.itype = 0;
- pop_implicit_try_blocks (NULL_TREE);
- ;
- break;}
-case 593:
-#line 3429 "cp-parse.y"
-{ cplus_expand_start_try (0); ;
- break;}
-case 595:
-#line 3433 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 596:
-#line 3435 "cp-parse.y"
-{
- tree type = lookup_exception_type (current_class_type, current_class_name, yyvsp[0].ttype);
- if (type == NULL_TREE)
- {
- error ("`%s' is not an exception type",
- IDENTIFIER_POINTER (TREE_VALUE (yyvsp[0].ttype)));
- current_exception_type = NULL_TREE;
- TREE_TYPE (current_exception_object) = error_mark_node;
- }
- else
- {
- current_exception_type = type;
- /* In-place union. */
- TREE_TYPE (current_exception_object) = type;
- }
- yyvsp[0].ttype = cplus_expand_start_catch (yyvsp[0].ttype);
- pushlevel (1);
- expand_start_bindings (0);
- ;
- break;}
-case 597:
-#line 3455 "cp-parse.y"
-{
- expand_end_bindings (0, 1, 0);
- yyvsp[0].ttype = poplevel (1, 0, 0);
-
- cplus_expand_end_catch (0);
-
- /* Mark this as a catch block. */
- TREE_LANG_FLAG_2 (yyvsp[0].ttype) = 1;
- if (yyvsp[-2].ttype != error_mark_node)
- {
- tree decl = build_decl (CPLUS_CATCH_DECL, DECL_NAME (yyvsp[-2].ttype), 0);
- DECL_RTL (decl) = DECL_RTL (yyvsp[-2].ttype);
- TREE_CHAIN (decl) = BLOCK_VARS (yyvsp[0].ttype);
- BLOCK_VARS (yyvsp[0].ttype) = decl;
- }
- ;
- break;}
-case 598:
-#line 3472 "cp-parse.y"
-{
- if (yyvsp[-1].ttype)
- error ("duplicate default in exception handler");
- current_exception_type = NULL_TREE;
- /* Takes it right out of scope. */
- TREE_TYPE (current_exception_object) = error_mark_node;
-
- if (! expand_catch_default ())
- compiler_error ("default catch botch");
-
- /* The default exception is handled as the
- last in the chain of exceptions handled. */
- do_pending_stack_adjust ();
- start_sequence ();
- yyvsp[-1].ttype = make_node (RTL_EXPR);
- TREE_TYPE (yyvsp[-1].ttype) = void_type_node;
- ;
- break;}
-case 599:
-#line 3490 "cp-parse.y"
-{
- extern struct rtx_def *get_insns ();
- do_pending_stack_adjust ();
- if (! expand_catch (NULL_TREE))
- compiler_error ("except nesting botch");
- if (! expand_end_catch ())
- compiler_error ("except nesting botch");
- RTL_EXPR_SEQUENCE (yyvsp[-3].ttype) = get_insns ();
- if (yyvsp[0].ttype)
- {
- /* Mark this block as the default catch block. */
- TREE_LANG_FLAG_1 (yyvsp[0].ttype) = 1;
- TREE_LANG_FLAG_2 (yyvsp[0].ttype) = 1;
- }
- end_sequence ();
- ;
- break;}
-case 600:
-#line 3510 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 602:
-#line 3515 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 603:
-#line 3517 "cp-parse.y"
-{
- tree type = groktypename (yyvsp[-2].ttype);
- current_exception_type = type;
- /* In-place union. */
- if (yyvsp[-1].ttype)
- {
- tree tmp;
- tmp = pushdecl (build_decl (VAR_DECL, yyvsp[-1].ttype, type));
- current_exception_object =
- build1 (INDIRECT_REF, type, tmp);
- }
- yyvsp[-2].ttype = ansi_expand_start_catch(type);
- pushlevel (1);
- expand_start_bindings (0);
- ;
- break;}
-case 604:
-#line 3533 "cp-parse.y"
-{
- expand_end_bindings (0, 1, 0);
- yyvsp[0].ttype = poplevel (1, 0, 0);
-
- cplus_expand_end_catch (0);
-
- /* Mark this as a catch block. */
- TREE_LANG_FLAG_2 (yyvsp[0].ttype) = 1;
- if (yyvsp[-4].ttype != error_mark_node)
- {
- tree decl = build_decl (CPLUS_CATCH_DECL, DECL_NAME (yyvsp[-4].ttype), 0);
- DECL_RTL (decl) = DECL_RTL (yyvsp[-4].ttype);
- TREE_CHAIN (decl) = BLOCK_VARS (yyvsp[0].ttype);
- BLOCK_VARS (yyvsp[0].ttype) = decl;
- }
- ;
- break;}
-case 605:
-#line 3553 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 606:
-#line 3555 "cp-parse.y"
-{ yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 607:
-#line 3557 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 608:
-#line 3562 "cp-parse.y"
-{ yyval.itype = 0; ;
- break;}
-case 609:
-#line 3564 "cp-parse.y"
-{ yyval.itype = 0; ;
- break;}
-case 610:
-#line 3566 "cp-parse.y"
-{ yyval.itype = 1; ;
- break;}
-case 611:
-#line 3568 "cp-parse.y"
-{ yyval.itype = -1; ;
- break;}
-case 612:
-#line 3575 "cp-parse.y"
-{ emit_line_note (input_filename, lineno); ;
- break;}
-case 613:
-#line 3577 "cp-parse.y"
-{ emit_line_note (input_filename, lineno); ;
- break;}
-case 614:
-#line 3582 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 616:
-#line 3585 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 617:
-#line 3591 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 620:
-#line 3598 "cp-parse.y"
-{ yyval.ttype = chainon (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 621:
-#line 3603 "cp-parse.y"
-{ yyval.ttype = build_tree_list (yyval.ttype, yyvsp[-1].ttype); ;
- break;}
-case 622:
-#line 3608 "cp-parse.y"
-{ yyval.ttype = tree_cons (NULL_TREE, yyval.ttype, NULL_TREE); ;
- break;}
-case 623:
-#line 3610 "cp-parse.y"
-{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 624:
-#line 3619 "cp-parse.y"
-{
- if (strict_prototype)
- yyval.ttype = void_list_node;
- else
- yyval.ttype = NULL_TREE;
- ;
- break;}
-case 625:
-#line 3626 "cp-parse.y"
-{
- yyval.ttype = chainon (yyval.ttype, void_list_node);
- TREE_PARMLIST (yyval.ttype) = 1;
- ;
- break;}
-case 626:
-#line 3631 "cp-parse.y"
-{
- TREE_PARMLIST (yyval.ttype) = 1;
- ;
- break;}
-case 627:
-#line 3636 "cp-parse.y"
-{
- TREE_PARMLIST (yyval.ttype) = 1;
- ;
- break;}
-case 628:
-#line 3640 "cp-parse.y"
-{
- /* ARM $8.2.5 has this as a boxed-off comment. */
- if (pedantic)
- warning ("use of `...' without a first argument is non-portable");
- yyval.ttype = NULL_TREE;
- ;
- break;}
-case 629:
-#line 3647 "cp-parse.y"
-{
- TREE_PARMLIST (yyval.ttype) = 1;
- ;
- break;}
-case 630:
-#line 3651 "cp-parse.y"
-{
- TREE_PARMLIST (yyval.ttype) = 1;
- ;
- break;}
-case 631:
-#line 3655 "cp-parse.y"
-{
- /* This helps us recover from really nasty
- parse errors, for example, a missing right
- parenthesis. */
- yyerror ("possibly missing ')'");
- yyval.ttype = chainon (yyval.ttype, void_list_node);
- TREE_PARMLIST (yyval.ttype) = 1;
- yyungetc (':', 0);
- yychar = ')';
- ;
- break;}
-case 632:
-#line 3670 "cp-parse.y"
-{ yyval.ttype = build_tree_list (NULL_TREE, yyval.ttype); ;
- break;}
-case 633:
-#line 3672 "cp-parse.y"
-{ yyval.ttype = build_tree_list (yyvsp[0].ttype, yyval.ttype); ;
- break;}
-case 634:
-#line 3674 "cp-parse.y"
-{ yyval.ttype = chainon (yyval.ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
- break;}
-case 635:
-#line 3676 "cp-parse.y"
-{ yyval.ttype = chainon (yyval.ttype, build_tree_list (yyvsp[0].ttype, yyvsp[-2].ttype)); ;
- break;}
-case 636:
-#line 3678 "cp-parse.y"
-{ yyval.ttype = chainon (yyval.ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ;
- break;}
-case 637:
-#line 3680 "cp-parse.y"
-{ yyval.ttype = chainon (yyval.ttype, build_tree_list (yyvsp[0].ttype, yyvsp[-2].ttype)); ;
- break;}
-case 638:
-#line 3701 "cp-parse.y"
-{ yyval.ttype = build_tree_list (yyval.ttype, yyvsp[0].ttype);
- see_typename (); ;
- break;}
-case 639:
-#line 3704 "cp-parse.y"
-{ yyval.ttype = build_tree_list (yyval.ttype, yyvsp[0].ttype);
- see_typename (); ;
- break;}
-case 642:
-#line 3711 "cp-parse.y"
-{ yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 643:
-#line 3715 "cp-parse.y"
-{ see_typename (); ;
- break;}
-case 644:
-#line 3719 "cp-parse.y"
-{ dont_see_typename (); ;
- break;}
-case 645:
-#line 3738 "cp-parse.y"
-{
- warning ("type specifier omitted for parameter");
- yyval.ttype = build_tree_list (TREE_PURPOSE (TREE_VALUE (yyvsp[-2].ttype)), yyval.ttype);
- ;
- break;}
-case 646:
-#line 3746 "cp-parse.y"
-{ yyval.ttype = NULL_TREE; ;
- break;}
-case 647:
-#line 3748 "cp-parse.y"
-{ yyval.ttype = yyvsp[0].ttype; ;
- break;}
-case 648:
-#line 3750 "cp-parse.y"
-{ yyval.ttype = yyvsp[-1].ttype; ;
- break;}
-case 649:
-#line 3755 "cp-parse.y"
-{ yyval.ttype = void_list_node; ;
- break;}
-case 650:
-#line 3757 "cp-parse.y"
-{ yyval.ttype = build_decl_list (NULL_TREE, yyval.ttype); ;
- break;}
-case 651:
-#line 3759 "cp-parse.y"
-{ yyval.ttype = build_decl_list (NULL_TREE, yyval.ttype); ;
- break;}
-case 652:
-#line 3761 "cp-parse.y"
-{ yyval.ttype = build_decl_list (void_type_node, yyvsp[0].ttype); ;
- break;}
-case 653:
-#line 3763 "cp-parse.y"
-{ yyval.ttype = build_decl_list (void_type_node, yyvsp[0].ttype); ;
- break;}
-case 654:
-#line 3765 "cp-parse.y"
-{ yyval.ttype = build_decl_list (yyval.ttype, yyvsp[0].ttype); ;
- break;}
-case 656:
-#line 3771 "cp-parse.y"
-{ yyval.ttype = build_decl_list (NULL_TREE, yyval.ttype); ;
- break;}
-case 658:
-#line 3777 "cp-parse.y"
-{
- TREE_CHAIN (yyvsp[0].ttype) = yyval.ttype;
- yyval.ttype = yyvsp[0].ttype;
- ;
- break;}
-case 660:
-#line 3786 "cp-parse.y"
-{
- TREE_CHAIN (yyvsp[0].ttype) = yyval.ttype;
- yyval.ttype = yyvsp[0].ttype;
- ;
- break;}
-case 661:
-#line 3794 "cp-parse.y"
-{ yyval.ttype = ansi_opname[MULT_EXPR]; ;
- break;}
-case 662:
-#line 3796 "cp-parse.y"
-{ yyval.ttype = ansi_opname[TRUNC_DIV_EXPR]; ;
- break;}
-case 663:
-#line 3798 "cp-parse.y"
-{ yyval.ttype = ansi_opname[TRUNC_MOD_EXPR]; ;
- break;}
-case 664:
-#line 3800 "cp-parse.y"
-{ yyval.ttype = ansi_opname[PLUS_EXPR]; ;
- break;}
-case 665:
-#line 3802 "cp-parse.y"
-{ yyval.ttype = ansi_opname[MINUS_EXPR]; ;
- break;}
-case 666:
-#line 3804 "cp-parse.y"
-{ yyval.ttype = ansi_opname[BIT_AND_EXPR]; ;
- break;}
-case 667:
-#line 3806 "cp-parse.y"
-{ yyval.ttype = ansi_opname[BIT_IOR_EXPR]; ;
- break;}
-case 668:
-#line 3808 "cp-parse.y"
-{ yyval.ttype = ansi_opname[BIT_XOR_EXPR]; ;
- break;}
-case 669:
-#line 3810 "cp-parse.y"
-{ yyval.ttype = ansi_opname[BIT_NOT_EXPR]; ;
- break;}
-case 670:
-#line 3812 "cp-parse.y"
-{ yyval.ttype = ansi_opname[COMPOUND_EXPR]; ;
- break;}
-case 671:
-#line 3814 "cp-parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
- break;}
-case 672:
-#line 3816 "cp-parse.y"
-{ yyval.ttype = ansi_opname[LT_EXPR]; ;
- break;}
-case 673:
-#line 3818 "cp-parse.y"
-{ yyval.ttype = ansi_opname[GT_EXPR]; ;
- break;}
-case 674:
-#line 3820 "cp-parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
- break;}
-case 675:
-#line 3822 "cp-parse.y"
-{ yyval.ttype = ansi_assopname[yyvsp[0].code]; ;
- break;}
-case 676:
-#line 3824 "cp-parse.y"
-{
- yyval.ttype = ansi_opname [MODIFY_EXPR];
- if (current_class_type)
- {
- TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
- TYPE_GETS_ASSIGNMENT (current_class_type) = 1;
- }
- ;
- break;}
-case 677:
-#line 3833 "cp-parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
- break;}
-case 678:
-#line 3835 "cp-parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
- break;}
-case 679:
-#line 3837 "cp-parse.y"
-{ yyval.ttype = ansi_opname[POSTINCREMENT_EXPR]; ;
- break;}
-case 680:
-#line 3839 "cp-parse.y"
-{ yyval.ttype = ansi_opname[PREDECREMENT_EXPR]; ;
- break;}
-case 681:
-#line 3841 "cp-parse.y"
-{ yyval.ttype = ansi_opname[TRUTH_ANDIF_EXPR]; ;
- break;}
-case 682:
-#line 3843 "cp-parse.y"
-{ yyval.ttype = ansi_opname[TRUTH_ORIF_EXPR]; ;
- break;}
-case 683:
-#line 3845 "cp-parse.y"
-{ yyval.ttype = ansi_opname[TRUTH_NOT_EXPR]; ;
- break;}
-case 684:
-#line 3847 "cp-parse.y"
-{ yyval.ttype = ansi_opname[COND_EXPR]; ;
- break;}
-case 685:
-#line 3849 "cp-parse.y"
-{ yyval.ttype = ansi_opname[yyvsp[0].code]; ;
- break;}
-case 686:
-#line 3851 "cp-parse.y"
-{ yyval.ttype = ansi_opname[COMPONENT_REF];
- if (current_class_type)
- {
- tree t = current_class_type;
- while (t)
- {
- TYPE_OVERLOADS_ARROW (t) = 1;
- t = TYPE_NEXT_VARIANT (t);
- }
- }
- ;
- break;}
-case 687:
-#line 3863 "cp-parse.y"
-{ yyval.ttype = ansi_opname[MEMBER_REF];
- if (current_class_type)
- {
- tree t = current_class_type;
- while (t)
- {
- TYPE_OVERLOADS_ARROW (t) = 1;
- t = TYPE_NEXT_VARIANT (t);
- }
- }
- ;
- break;}
-case 688:
-#line 3875 "cp-parse.y"
-{
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- if (yychar == '(' || yychar == LEFT_RIGHT)
- {
- yyval.ttype = ansi_opname[METHOD_CALL_EXPR];
- if (current_class_type)
- {
- tree t = current_class_type;
- while (t)
- {
- TYPE_OVERLOADS_METHOD_CALL_EXPR (t) = 1;
- t = TYPE_NEXT_VARIANT (t);
- }
- }
- }
- else
- {
- yyval.ttype = build_parse_node (CALL_EXPR, ansi_opname[COMPONENT_REF], void_list_node, yyvsp[0].ttype);
- if (current_class_type)
- {
- tree t = current_class_type;
- while (t)
- {
- TYPE_OVERLOADS_ARROW (t) = 1;
- t = TYPE_NEXT_VARIANT (t);
- }
- }
- }
- ;
- break;}
-case 689:
-#line 3906 "cp-parse.y"
-{ yyval.ttype = ansi_opname[CALL_EXPR];
- if (current_class_type)
- {
- tree t = current_class_type;
- while (t)
- {
- TYPE_OVERLOADS_CALL_EXPR (t) = 1;
- t = TYPE_NEXT_VARIANT (t);
- }
- }
- ;
- break;}
-case 690:
-#line 3918 "cp-parse.y"
-{ yyval.ttype = ansi_opname[ARRAY_REF];
- if (current_class_type)
- {
- tree t = current_class_type;
- while (t)
- {
- TYPE_OVERLOADS_ARRAY_REF (t) = 1;
- t = TYPE_NEXT_VARIANT (t);
- }
- }
- ;
- break;}
-case 691:
-#line 3930 "cp-parse.y"
-{
- yyval.ttype = ansi_opname[NEW_EXPR];
- if (current_class_type)
- {
- tree t = current_class_type;
- while (t)
- {
- TREE_GETS_NEW (t) = 1;
- t = TYPE_NEXT_VARIANT (t);
- }
- }
- ;
- break;}
-case 692:
-#line 3943 "cp-parse.y"
-{
- yyval.ttype = ansi_opname[DELETE_EXPR];
- if (current_class_type)
- {
- tree t = current_class_type;
- while (t)
- {
- TREE_GETS_DELETE (t) = 1;
- t = TYPE_NEXT_VARIANT (t);
- }
- }
- ;
- break;}
-case 693:
-#line 3959 "cp-parse.y"
-{ yyval.ttype = build1 (TYPE_EXPR, yyvsp[-1].ttype, yyvsp[0].ttype); ;
- break;}
-case 694:
-#line 3961 "cp-parse.y"
-{ yyval.ttype = ansi_opname[ERROR_MARK]; ;
- break;}
-}
- /* the action file gets copied in in place of this dollarsign */
-#line 440 "bison.simple"
-
- yyvsp -= yylen;
- yyssp -= yylen;
-#ifdef YYLSP_NEEDED
- yylsp -= yylen;
-#endif
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- short *ssp1 = yyss - 1;
- fprintf (stderr, "state stack now");
- while (ssp1 != yyssp)
- fprintf (stderr, " %d", *++ssp1);
- fprintf (stderr, "\n");
- }
-#endif
-
- *++yyvsp = yyval;
-
-#ifdef YYLSP_NEEDED
- yylsp++;
- if (yylen == 0)
- {
- yylsp->first_line = yylloc.first_line;
- yylsp->first_column = yylloc.first_column;
- yylsp->last_line = (yylsp-1)->last_line;
- yylsp->last_column = (yylsp-1)->last_column;
- yylsp->text = 0;
- }
- else
- {
- yylsp->last_line = (yylsp+yylen-1)->last_line;
- yylsp->last_column = (yylsp+yylen-1)->last_column;
- }
-#endif
-
- /* Now "shift" the result of the reduction.
- Determine what state that goes to,
- based on the state we popped back to
- and the rule number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
- if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTBASE];
-
- goto yynewstate;
-
-yyerrlab: /* here on detecting error */
-
- if (! yyerrstatus)
- /* If not already recovering from an error, report this error. */
- {
- ++yynerrs;
-
-#ifdef YYERROR_VERBOSE
- yyn = yypact[yystate];
-
- if (yyn > YYFLAG && yyn < YYLAST)
- {
- int size = 0;
- char *msg;
- int x, count;
-
- count = 0;
- for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
- if (yycheck[x + yyn] == x)
- size += strlen(yytname[x]) + 15, count++;
- msg = (char *) malloc(size + 15);
- if (msg != 0)
- {
- strcpy(msg, "parse error");
-
- if (count < 5)
- {
- count = 0;
- for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
- if (yycheck[x + yyn] == x)
- {
- strcat(msg, count == 0 ? ", expecting `" : " or `");
- strcat(msg, yytname[x]);
- strcat(msg, "'");
- count++;
- }
- }
- yyerror(msg);
- free(msg);
- }
- else
- yyerror ("parse error; also virtual memory exceeded");
- }
- else
-#endif /* YYERROR_VERBOSE */
- yyerror("parse error");
- }
-
-yyerrlab1: /* here on error raised explicitly by an action */
-
- if (yyerrstatus == 3)
- {
- /* if just tried and failed to reuse lookahead token after an error, discard it. */
-
- /* return failure if at end of input */
- if (yychar == YYEOF)
- YYABORT;
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
-#endif
-
- yychar = YYEMPTY;
- }
-
- /* Else will try to reuse lookahead token
- after shifting the error token. */
-
- yyerrstatus = 3; /* Each real token shifted decrements this */
-
- goto yyerrhandle;
-
-yyerrdefault: /* current state does not do anything special for the error token. */
-
-#if 0
- /* This is wrong; only states that explicitly want error tokens
- should shift them. */
- yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
- if (yyn) goto yydefault;
-#endif
-
-yyerrpop: /* pop the current state because it cannot handle the error token */
-
- if (yyssp == yyss) YYABORT;
- yyvsp--;
- yystate = *--yyssp;
-#ifdef YYLSP_NEEDED
- yylsp--;
-#endif
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- short *ssp1 = yyss - 1;
- fprintf (stderr, "Error: state stack now");
- while (ssp1 != yyssp)
- fprintf (stderr, " %d", *++ssp1);
- fprintf (stderr, "\n");
- }
-#endif
-
-yyerrhandle:
-
- yyn = yypact[yystate];
- if (yyn == YYFLAG)
- goto yyerrdefault;
-
- yyn += YYTERROR;
- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
- goto yyerrdefault;
-
- yyn = yytable[yyn];
- if (yyn < 0)
- {
- if (yyn == YYFLAG)
- goto yyerrpop;
- yyn = -yyn;
- goto yyreduce;
- }
- else if (yyn == 0)
- goto yyerrpop;
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Shifting error token, ");
-#endif
-
- *++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
- *++yylsp = yylloc;
-#endif
-
- yystate = yyn;
- goto yynewstate;
-}
-#line 3964 "cp-parse.y"
-
-
-tree
-get_current_declspecs ()
-{
- return current_declspecs;
-}
diff --git a/gnu/gcc2/cc1plus/cp-parse.h b/gnu/gcc2/cc1plus/cp-parse.h
deleted file mode 100644
index 87ea2b8de0f0..000000000000
--- a/gnu/gcc2/cc1plus/cp-parse.h
+++ /dev/null
@@ -1,88 +0,0 @@
-typedef union {long itype; tree ttype; char *strtype; enum tree_code code; } YYSTYPE;
-#define IDENTIFIER 258
-#define TYPENAME 259
-#define SCOPED_TYPENAME 260
-#define SCSPEC 261
-#define TYPESPEC 262
-#define TYPE_QUAL 263
-#define CONSTANT 264
-#define STRING 265
-#define ELLIPSIS 266
-#define SIZEOF 267
-#define ENUM 268
-#define IF 269
-#define ELSE 270
-#define WHILE 271
-#define DO 272
-#define FOR 273
-#define SWITCH 274
-#define CASE 275
-#define DEFAULT 276
-#define BREAK 277
-#define CONTINUE 278
-#define RETURN 279
-#define GOTO 280
-#define ASM_KEYWORD 281
-#define GCC_ASM_KEYWORD 282
-#define TYPEOF 283
-#define ALIGNOF 284
-#define HEADOF 285
-#define CLASSOF 286
-#define ATTRIBUTE 287
-#define EXTENSION 288
-#define LABEL 289
-#define AGGR 290
-#define VISSPEC 291
-#define DELETE 292
-#define NEW 293
-#define OVERLOAD 294
-#define THIS 295
-#define OPERATOR 296
-#define DYNAMIC 297
-#define POINTSAT_LEFT_RIGHT 298
-#define LEFT_RIGHT 299
-#define TEMPLATE 300
-#define SCOPE 301
-#define START_DECLARATOR 302
-#define EMPTY 303
-#define TYPENAME_COLON 304
-#define ASSIGN 305
-#define RANGE 306
-#define OROR 307
-#define ANDAND 308
-#define MIN_MAX 309
-#define EQCOMPARE 310
-#define ARITHCOMPARE 311
-#define LSHIFT 312
-#define RSHIFT 313
-#define UNARY 314
-#define PLUSPLUS 315
-#define MINUSMINUS 316
-#define HYPERUNARY 317
-#define PAREN_STAR_PAREN 318
-#define POINTSAT 319
-#define POINTSAT_STAR 320
-#define DOT_STAR 321
-#define RAISE 322
-#define RAISES 323
-#define RERAISE 324
-#define TRY 325
-#define EXCEPT 326
-#define CATCH 327
-#define THROW 328
-#define ANSI_TRY 329
-#define ANSI_THROW 330
-#define TYPENAME_ELLIPSIS 331
-#define PTYPENAME 332
-#define PRE_PARSED_FUNCTION_DECL 333
-#define EXTERN_LANG_STRING 334
-#define ALL 335
-#define PRE_PARSED_CLASS_DECL 336
-#define TYPENAME_DEFN 337
-#define IDENTIFIER_DEFN 338
-#define PTYPENAME_DEFN 339
-#define END_OF_SAVED_INPUT 340
-
-
-extern YYSTYPE yylval;
-#define YYEMPTY -2
diff --git a/gnu/gcc2/cc1plus/cp-pt.c b/gnu/gcc2/cc1plus/cp-pt.c
deleted file mode 100644
index 75e39677eb74..000000000000
--- a/gnu/gcc2/cc1plus/cp-pt.c
+++ /dev/null
@@ -1,2123 +0,0 @@
-/* Handle parameterized types (templates) for GNU C++.
- Copyright (C) 1992, 1993 Free Software Foundation, Inc.
- Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
-
-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. */
-
-/* Known bugs or deficiencies include:
- * templates for class static data don't work (methods only)
- * duplicated method templates can crash the compiler
- * interface/impl data is taken from file defining the template
- * all methods must be provided in header files; can't use a source
- file that contains only the method templates and "just win"
- * method templates must be seen before the expansion of the
- class template is done
- */
-
-#include "config.h"
-#include <stdio.h>
-#include "obstack.h"
-
-#include "tree.h"
-#include "cp-tree.h"
-#include "cp-decl.h"
-#include "cp-parse.h"
-
-extern struct obstack permanent_obstack;
-extern tree grokdeclarator ();
-
-extern int lineno;
-extern char *input_filename;
-struct pending_inline *pending_template_expansions;
-
-int processing_template_decl;
-int processing_template_defn;
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-static int unify ();
-static void add_pending_template ();
-
-void overload_template_name (), pop_template_decls ();
-
-/* We've got a template header coming up; set obstacks up to save the
- nodes created permanently. (There might be cases with nested templates
- where we don't have to do this, but they aren't implemented, and it
- probably wouldn't be worth the effort.) */
-void
-begin_template_parm_list ()
-{
- pushlevel (0);
- push_obstacks (&permanent_obstack, &permanent_obstack);
-}
-
-/* Process information from new template parameter NEXT and append it to the
- LIST being built. The rules for use of a template parameter type name
- by later parameters are not well-defined for us just yet. However, the
- only way to avoid having to parse expressions of unknown complexity (and
- with tokens of unknown types) is to disallow it completely. So for now,
- that is what is assumed. */
-tree
-process_template_parm (list, next)
- tree list, next;
-{
- tree parm;
- int is_type;
- parm = next;
- my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
- is_type = TREE_CODE (TREE_PURPOSE (parm)) == IDENTIFIER_NODE;
- if (!is_type)
- {
- parm = TREE_PURPOSE (parm);
- my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 260);
- parm = TREE_VALUE (parm);
- /* is a const-param */
- parm = grokdeclarator (TREE_VALUE (next), TREE_PURPOSE (next),
- NORMAL, 0, NULL_TREE);
- /* A template parameter is not modifiable. */
- TREE_READONLY (parm) = 1;
- if (TREE_CODE (TREE_TYPE (parm)) == RECORD_TYPE
- || TREE_CODE (TREE_TYPE (parm)) == UNION_TYPE)
- {
- sorry ("aggregate template parameter types");
- TREE_TYPE (parm) = void_type_node;
- }
- }
- return chainon (list, parm);
-}
-
-/* The end of a template parameter list has been reached. Process the
- tree list into a parameter vector, converting each parameter into a more
- useful form. Type parameters are saved as IDENTIFIER_NODEs, and others
- as PARM_DECLs. */
-
-tree
-end_template_parm_list (parms)
- tree parms;
-{
- int nparms = 0;
- tree saved_parmlist;
- tree parm;
- for (parm = parms; parm; parm = TREE_CHAIN (parm))
- nparms++;
- saved_parmlist = make_tree_vec (nparms);
-
- pushlevel (0);
-
- for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
- {
- tree p = parm, decl;
- if (TREE_CODE (p) == TREE_LIST)
- {
- tree t;
- p = TREE_PURPOSE (p);
- my_friendly_assert (TREE_CODE (p) == IDENTIFIER_NODE, 261);
- t = make_node (TEMPLATE_TYPE_PARM);
- TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms);
- decl = build_lang_decl (TYPE_DECL, p, t);
- TYPE_NAME (t) = decl;
- }
- else
- {
- tree tinfo = make_node (TEMPLATE_CONST_PARM);
- my_friendly_assert (TREE_PERMANENT (tinfo), 262);
- if (!TREE_PERMANENT (p))
- {
- tree old_p = p;
- TREE_PERMANENT (old_p) = 1;
- p = copy_node (p);
- TREE_PERMANENT (old_p) = 0;
- }
- TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms);
- TREE_TYPE (tinfo) = TREE_TYPE (p);
- decl = build_decl (CONST_DECL, DECL_NAME (p), TREE_TYPE (p));
- DECL_INITIAL (decl) = tinfo;
- }
- TREE_VEC_ELT (saved_parmlist, nparms) = p;
- pushdecl (decl);
- }
- set_current_level_tags_transparency (1);
- processing_template_decl++;
- return saved_parmlist;
-}
-
-/* end_template_decl is called after a template declaration is seen.
- D1 is template header; D2 is class_head_sans_basetype or a
- TEMPLATE_DECL with its DECL_RESULT field set. */
-void
-end_template_decl (d1, d2, is_class)
- tree d1, d2, is_class;
-{
- tree decl;
- struct template_info *tmpl;
-
- tmpl = (struct template_info *) obstack_alloc (&permanent_obstack,
- sizeof (struct template_info));
- tmpl->text = 0;
- tmpl->length = 0;
- tmpl->aggr = is_class;
-
- /* cloned from reinit_parse_for_template */
- tmpl->filename = input_filename;
- tmpl->lineno = lineno;
- tmpl->parm_vec = d1; /* [eichin:19911015.2306EST] */
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "end_template_decl");
- debug_bindings_indentation += 4;
-#endif
-
- if (d2 == NULL_TREE || d2 == error_mark_node)
- {
- decl = 0;
- goto lose;
- }
-
- if (is_class)
- {
- decl = build_lang_decl (TEMPLATE_DECL, d2, NULL_TREE);
- }
- else
- {
- if (TREE_CODE (d2) == TEMPLATE_DECL)
- decl = d2;
- else
- {
- /* Class destructor templates and operator templates are
- slipping past as non-template nodes. Process them here, since
- I haven't figured out where to catch them earlier. I could
- go do that, but it's a choice between getting that done and
- staying only N months behind schedule. Sorry.... */
- enum tree_code code;
- my_friendly_assert (TREE_CODE (d2) == CALL_EXPR, 263);
- code = TREE_CODE (TREE_OPERAND (d2, 0));
- my_friendly_assert (code == BIT_NOT_EXPR
- || code == OP_IDENTIFIER
- || code == SCOPE_REF, 264);
- d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE);
- decl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (d2),
- TREE_TYPE (d2));
- DECL_TEMPLATE_RESULT (decl) = d2;
- DECL_CONTEXT (decl) = DECL_CONTEXT (d2);
- DECL_CLASS_CONTEXT (decl) = DECL_CLASS_CONTEXT (d2);
- DECL_NAME (decl) = DECL_NAME (d2);
- TREE_TYPE (decl) = TREE_TYPE (d2);
- TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = 0;
- DECL_EXTERNAL (decl) = (DECL_EXTERNAL (d2)
- && !(DECL_CLASS_CONTEXT (d2)
- && !DECL_THIS_EXTERN (d2)));
- }
-
- /* All routines creating TEMPLATE_DECL nodes should now be using
- build_lang_decl, which will have set this up already. */
- my_friendly_assert (DECL_LANG_SPECIFIC (decl) != 0, 265);
-
- /* @@ Somewhere, permanent allocation isn't being used. */
- if (! DECL_TEMPLATE_IS_CLASS (decl)
- && TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == FUNCTION_DECL)
- {
- tree result = DECL_TEMPLATE_RESULT (decl);
- /* Will do nothing if allocation was already permanent. */
- DECL_ARGUMENTS (result) = copy_to_permanent (DECL_ARGUMENTS (result));
- }
-
- /* If this is for a method, there's an extra binding level here. */
- if (! DECL_TEMPLATE_IS_CLASS (decl)
- && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
- {
- /* @@ Find out where this should be getting set! */
- tree r = DECL_TEMPLATE_RESULT (decl);
- if (DECL_CLASS_CONTEXT (r) == NULL_TREE)
- DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
- }
- }
- DECL_TEMPLATE_INFO (decl) = tmpl;
- DECL_TEMPLATE_PARMS (decl) = d1;
-lose:
- if (decl)
- {
- /* If context of decl is non-null (i.e., method template), add it
- to the appropriate class template, and pop the binding levels. */
- if (! DECL_TEMPLATE_IS_CLASS (decl)
- && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
- {
- tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));
- tree tmpl;
- my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266);
- tmpl = UPT_TEMPLATE (ctx);
- DECL_TEMPLATE_MEMBERS (tmpl) =
- perm_tree_cons (DECL_NAME (decl), decl,
- DECL_TEMPLATE_MEMBERS (tmpl));
- poplevel (0, 0, 0);
- poplevel (0, 0, 0);
- }
- /* Otherwise, go back to top level first, and push the template decl
- again there. */
- else
- {
- poplevel (0, 0, 0);
- poplevel (0, 0, 0);
- if (TREE_TYPE (decl)
- && IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl)) != NULL_TREE)
- push_overloaded_decl (decl, 0);
- else
- pushdecl (decl);
- }
- }
-#if 0 /* It happens sometimes, with syntactic or semantic errors.
-
- One specific case:
- template <class A, int X, int Y> class Foo { ... };
- template <class A, int X, int y> Foo<X,Y>::method (Foo& x) { ... }
- Note the missing "A" in the class containing "method". */
- my_friendly_assert (global_bindings_p (), 267);
-#else
- while (! global_bindings_p ())
- poplevel (0, 0, 0);
-#endif
- pop_obstacks ();
- processing_template_decl--;
- (void) get_pending_sizes ();
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-
-/* Convert all template arguments to their appropriate types, and return
- a vector containing the resulting values. If any error occurs, return
- error_mark_node. */
-static tree
-coerce_template_parms (parms, arglist, in_decl)
- tree parms, arglist;
- tree in_decl;
-{
- int nparms, i, lost = 0;
- tree vec;
-
- if (TREE_CODE (arglist) == TREE_VEC)
- nparms = TREE_VEC_LENGTH (arglist);
- else
- nparms = list_length (arglist);
- if (nparms != TREE_VEC_LENGTH (parms))
- {
- error ("incorrect number of parameters (%d, should be %d)",
- nparms, TREE_VEC_LENGTH (parms));
- if (in_decl)
- error_with_decl (in_decl, "in template expansion for decl `%s'");
- return error_mark_node;
- }
-
- if (TREE_CODE (arglist) == TREE_VEC)
- vec = copy_node (arglist);
- else
- {
- vec = make_tree_vec (nparms);
- for (i = 0; i < nparms; i++)
- {
- tree arg = arglist;
- arglist = TREE_CHAIN (arglist);
- if (arg == error_mark_node)
- lost++;
- else
- arg = TREE_VALUE (arg);
- TREE_VEC_ELT (vec, i) = arg;
- }
- }
- for (i = 0; i < nparms; i++)
- {
- tree arg = TREE_VEC_ELT (vec, i);
- tree parm = TREE_VEC_ELT (parms, i);
- tree val;
- int is_type, requires_type;
-
- is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
- requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;
- if (is_type != requires_type)
- {
- if (in_decl)
- error_with_decl (in_decl,
- "type/value mismatch in template parameter list for `%s'");
- lost++;
- TREE_VEC_ELT (vec, i) = error_mark_node;
- continue;
- }
- if (is_type)
- val = groktypename (arg);
- else
- val = digest_init (TREE_TYPE (parm), arg, (tree *) 0);
-
- if (val == error_mark_node)
- lost++;
-
- TREE_VEC_ELT (vec, i) = val;
- }
- if (lost)
- return error_mark_node;
- return vec;
-}
-
-/* Given class template name and parameter list, produce a user-friendly name
- for the instantiation. Note that this name isn't necessarily valid as
- input to the compiler, because ">" characters may be adjacent. */
-static char *
-mangle_class_name_for_template (name, parms, arglist)
- char *name;
- tree parms, arglist;
-{
- static struct obstack scratch_obstack;
- static char *scratch_firstobj;
- int i, nparms;
- char ibuf[100];
-
- if (!scratch_firstobj)
- {
- gcc_obstack_init (&scratch_obstack);
- scratch_firstobj = obstack_alloc (&scratch_obstack, 1);
- }
- else
- obstack_free (&scratch_obstack, scratch_firstobj);
-
-#if 0
-#define buflen sizeof(buf)
-#define check if (bufp >= buf+buflen-1) goto too_long
-#define ccat(c) *bufp++=(c); check
-#define advance bufp+=strlen(bufp); check
-#define cat(s) strncpy(bufp, s, buf+buflen-bufp-1); advance
-#else
-#define check
-#define ccat(c) obstack_1grow (&scratch_obstack, (c));
-#define advance
-#define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s))
-#endif
-#define icat(n) sprintf(ibuf,"%d",(n)); cat(ibuf)
-#define xcat(n) sprintf(ibuf,"%ux",n); cat(ibuf)
-
- cat (name);
- ccat ('<');
- nparms = TREE_VEC_LENGTH (parms);
- my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
- for (i = 0; i < nparms; i++)
- {
- tree parm = TREE_VEC_ELT (parms, i), arg = TREE_VEC_ELT (arglist, i);
- tree type, id;
-
- if (i)
- ccat (',');
-
- if (TREE_CODE (parm) == IDENTIFIER_NODE)
- {
- /* parm is a type */
- char *typename;
-
- if (TYPE_NAME (arg)
- && (TREE_CODE (arg) == RECORD_TYPE
- || TREE_CODE (arg) == UNION_TYPE
- || TREE_CODE (arg) == ENUMERAL_TYPE)
- && TYPE_IDENTIFIER (arg)
- && IDENTIFIER_POINTER (TYPE_IDENTIFIER (arg)))
- typename = IDENTIFIER_POINTER (TYPE_IDENTIFIER (arg));
- else
- typename = type_as_string (arg);
- cat (typename);
- continue;
- }
- else
- my_friendly_assert (TREE_CODE (parm) == PARM_DECL, 269);
-
- /* Should do conversions as for "const" initializers. */
- type = TREE_TYPE (parm);
- id = DECL_NAME (parm);
-
- if (TREE_CODE (arg) == TREE_LIST)
- {
- /* New list cell was built because old chain link was in
- use. */
- my_friendly_assert (TREE_PURPOSE (arg) == NULL_TREE, 270);
- arg = TREE_VALUE (arg);
- }
-
- switch (TREE_CODE (type))
- {
- case INTEGER_TYPE:
- case ENUMERAL_TYPE:
- if (TREE_CODE (arg) == INTEGER_CST)
- {
- if (TREE_INT_CST_HIGH (arg)
- != (TREE_INT_CST_LOW (arg) >> (HOST_BITS_PER_WIDE_INT - 1)))
- {
- tree val = arg;
- if (TREE_INT_CST_HIGH (val) < 0)
- {
- ccat ('-');
- val = build_int_2 (~TREE_INT_CST_LOW (val),
- -TREE_INT_CST_HIGH (val));
- }
- /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
- systems? */
- {
- static char format[10]; /* "%x%09999x\0" */
- if (!format[0])
- sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
- sprintf (ibuf, format, TREE_INT_CST_HIGH (val),
- TREE_INT_CST_LOW (val));
- cat (ibuf);
- }
- }
- else
- icat (TREE_INT_CST_LOW (arg));
- }
- else
- {
- error ("invalid integer constant for template parameter");
- cat ("*error*");
- }
- break;
-#ifndef REAL_IS_NOT_DOUBLE
- case REAL_TYPE:
- sprintf (ibuf, "%e", TREE_REAL_CST (arg));
- cat (ibuf);
- break;
-#endif
- case POINTER_TYPE:
- if (TREE_CODE (arg) != ADDR_EXPR)
- {
- error ("invalid pointer constant for template parameter");
- cat ("*error*");
- break;
- }
- ccat ('&');
- arg = TREE_OPERAND (arg, 0);
- if (TREE_CODE (arg) == FUNCTION_DECL)
- cat (fndecl_as_string (0, arg, 0));
- else
- {
- my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd',
- 271);
- cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
- }
- break;
- default:
- sorry ("encoding %s as template parm",
- tree_code_name [(int) TREE_CODE (type)]);
- my_friendly_abort (81);
- }
- }
- {
- char *bufp = obstack_next_free (&scratch_obstack);
- int offset = 0;
- while (bufp[offset - 1] == ' ')
- offset--;
- obstack_blank_fast (&scratch_obstack, offset);
- }
- ccat ('>');
- ccat ('\0');
- return (char *) obstack_base (&scratch_obstack);
-
- too_long:
- fatal ("out of (preallocated) string space creating template instantiation name");
- /* NOTREACHED */
- return NULL;
-}
-
-/* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of
- parameters, find the desired type.
-
- D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
- Since ARGLIST is build on the decl_obstack, we must copy it here
- to keep it from being reclaimed when the decl storage is reclaimed.
-
- IN_DECL, if non-NULL, is the template declaration we are trying to
- instantiate. */
-tree
-lookup_template_class (d1, arglist, in_decl)
- tree d1, arglist;
- tree in_decl;
-{
- tree template, parmlist;
- char *mangled_name;
- tree id;
-
- my_friendly_assert (TREE_CODE (d1) == IDENTIFIER_NODE, 272);
- template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
- if (! template)
- template = IDENTIFIER_CLASS_VALUE (d1);
- /* With something like `template <class T> class X class X { ... };'
- we could end up with D1 having nothing but an IDENTIFIER_LOCAL_VALUE.
- We don't want to do that, but we have to deal with the situation, so
- let's give them some syntax errors to chew on instead of a crash. */
- if (! template)
- return error_mark_node;
- if (TREE_CODE (template) != TEMPLATE_DECL)
- {
- error ("non-template type '%s' used as a template",
- IDENTIFIER_POINTER (d1));
- if (in_decl)
- error_with_decl (in_decl, "for template declaration `%s'");
- return error_mark_node;
- }
- parmlist = DECL_TEMPLATE_PARMS (template);
-
- arglist = coerce_template_parms (parmlist, arglist, in_decl);
- if (arglist == error_mark_node)
- return error_mark_node;
- if (uses_template_parms (arglist))
- {
- tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
- tree d;
- id = make_anon_name ();
- d = build_lang_decl (TYPE_DECL, id, t);
- TYPE_NAME (t) = d;
- TYPE_VALUES (t) = build_tree_list (template, arglist);
- pushdecl_top_level (d);
- }
- else
- {
- mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
- parmlist, arglist);
- id = get_identifier (mangled_name);
- }
- if (!IDENTIFIER_TEMPLATE (id))
- {
- arglist = copy_to_permanent (arglist);
- IDENTIFIER_TEMPLATE (id) = perm_tree_cons (template, arglist, NULL_TREE);
- }
- return id;
-}
-
-void
-push_template_decls (parmlist, arglist, class_level)
- tree parmlist, arglist;
- int class_level;
-{
- int i, nparms;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "push_template_decls");
- debug_bindings_indentation += 4;
-#endif
-
- /* Don't want to push values into global context. */
- if (!class_level)
- pushlevel (0);
- nparms = TREE_VEC_LENGTH (parmlist);
-
- for (i = 0; i < nparms; i++)
- {
- int requires_type, is_type;
- tree parm = TREE_VEC_ELT (parmlist, i);
- tree arg = TREE_VEC_ELT (arglist, i);
- tree decl = 0;
-
- requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;
- is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
- if (is_type)
- {
- /* add typename to namespace */
- if (!requires_type)
- {
- error ("template use error: type provided where value needed");
- continue;
- }
- decl = arg;
- my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);
- decl = build_lang_decl (TYPE_DECL, parm, decl);
- }
- else
- {
- /* add const decl to namespace */
- tree val;
- if (requires_type)
- {
- error ("template use error: value provided where type needed");
- continue;
- }
- val = digest_init (TREE_TYPE (parm), arg, (tree *) 0);
- if (val != error_mark_node)
- {
- decl = build_decl (VAR_DECL, DECL_NAME (parm), TREE_TYPE (parm));
- DECL_INITIAL (decl) = val;
- TREE_READONLY (decl) = 1;
- }
- }
- if (decl != 0)
- {
- layout_decl (decl, 0);
- if (class_level)
- pushdecl_class_level (decl);
- else
- pushdecl (decl);
- }
- }
- if (!class_level)
- set_current_level_tags_transparency (1);
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-void
-pop_template_decls (parmlist, arglist, class_level)
- tree parmlist, arglist;
- int class_level;
-{
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "pop_template_decls");
- debug_bindings_indentation += 4;
-#endif
-
- if (!class_level)
- poplevel (0, 0, 0);
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-/* Should be defined in cp-parse.h. */
-extern int yychar;
-
-int
-uses_template_parms (t)
- tree t;
-{
- if (!t)
- return 0;
- switch (TREE_CODE (t))
- {
- case INDIRECT_REF:
- case COMPONENT_REF:
- /* We assume that the object must be instantiated in order to build
- the COMPONENT_REF, so we test only whether the type of the
- COMPONENT_REF uses template parms. */
- return uses_template_parms (TREE_TYPE (t));
-
- case IDENTIFIER_NODE:
- if (!IDENTIFIER_TEMPLATE (t))
- return 0;
- return uses_template_parms (TREE_VALUE (IDENTIFIER_TEMPLATE (t)));
-
- /* aggregates of tree nodes */
- case TREE_VEC:
- {
- int i = TREE_VEC_LENGTH (t);
- while (i--)
- if (uses_template_parms (TREE_VEC_ELT (t, i)))
- return 1;
- return 0;
- }
- case TREE_LIST:
- if (uses_template_parms (TREE_PURPOSE (t))
- || uses_template_parms (TREE_VALUE (t)))
- return 1;
- return uses_template_parms (TREE_CHAIN (t));
-
- /* constructed type nodes */
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- return uses_template_parms (TREE_TYPE (t));
- case RECORD_TYPE:
- case UNION_TYPE:
- if (!TYPE_NAME (t))
- return 0;
- if (!TYPE_IDENTIFIER (t))
- return 0;
- return uses_template_parms (TYPE_IDENTIFIER (t));
- case FUNCTION_TYPE:
- if (uses_template_parms (TYPE_ARG_TYPES (t)))
- return 1;
- return uses_template_parms (TREE_TYPE (t));
- case ARRAY_TYPE:
- if (uses_template_parms (TYPE_DOMAIN (t)))
- return 1;
- return uses_template_parms (TREE_TYPE (t));
- case OFFSET_TYPE:
- if (uses_template_parms (TYPE_OFFSET_BASETYPE (t)))
- return 1;
- return uses_template_parms (TREE_TYPE (t));
- case METHOD_TYPE:
- if (uses_template_parms (TYPE_OFFSET_BASETYPE (t)))
- return 1;
- if (uses_template_parms (TYPE_ARG_TYPES (t)))
- return 1;
- return uses_template_parms (TREE_TYPE (t));
-
- /* decl nodes */
- case TYPE_DECL:
- return uses_template_parms (DECL_NAME (t));
- case FUNCTION_DECL:
- if (uses_template_parms (TREE_TYPE (t)))
- return 1;
- /* fall through */
- case VAR_DECL:
- case PARM_DECL:
- /* ??? What about FIELD_DECLs? */
- /* The type of a decl can't use template parms if the name of the
- variable doesn't, because it's impossible to resolve them. So
- ignore the type field for now. */
- if (DECL_CONTEXT (t) && uses_template_parms (DECL_CONTEXT (t)))
- return 1;
- if (uses_template_parms (TREE_TYPE (t)))
- {
- error ("template parms used where they can't be resolved");
- }
- return 0;
-
- case CALL_EXPR:
- return uses_template_parms (TREE_TYPE (t));
- case ADDR_EXPR:
- return uses_template_parms (TREE_OPERAND (t, 0));
-
- /* template parm nodes */
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_CONST_PARM:
- return 1;
-
- /* simple type nodes */
- case INTEGER_TYPE:
- if (uses_template_parms (TYPE_MIN_VALUE (t)))
- return 1;
- return uses_template_parms (TYPE_MAX_VALUE (t));
-
- case REAL_TYPE:
- case VOID_TYPE:
- case ENUMERAL_TYPE:
- return 0;
-
- /* constants */
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- return 0;
-
- case ERROR_MARK:
- /* Non-error_mark_node ERROR_MARKs are bad things. */
- my_friendly_assert (t == error_mark_node, 274);
- /* NOTREACHED */
- return 0;
-
- case UNINSTANTIATED_P_TYPE:
- return 1;
-
- default:
- switch (TREE_CODE_CLASS (TREE_CODE (t)))
- {
- case '1':
- case '2':
- case '3':
- case '<':
- {
- int i;
- for (i = tree_code_length[(int) TREE_CODE (t)]; --i >= 0;)
- if (uses_template_parms (TREE_OPERAND (t, i)))
- return 1;
- return 0;
- }
- default:
- break;
- }
- sorry ("testing %s for template parms",
- tree_code_name [(int) TREE_CODE (t)]);
- my_friendly_abort (82);
- /* NOTREACHED */
- return 0;
- }
-}
-
-void
-instantiate_member_templates (arg)
- tree arg;
-{
- tree t;
- tree classname = TREE_VALUE (arg);
- tree id = classname;
- tree members = DECL_TEMPLATE_MEMBERS (TREE_PURPOSE (IDENTIFIER_TEMPLATE (id)));
-
- for (t = members; t; t = TREE_CHAIN (t))
- {
- tree parmvec, type, classparms, tdecl, t2;
- int nparms, xxx, i;
-
- my_friendly_assert (TREE_VALUE (t) != NULL_TREE, 275);
- my_friendly_assert (TREE_CODE (TREE_VALUE (t)) == TEMPLATE_DECL, 276);
- /* @@ Should verify that class parm list is a list of
- distinct template parameters, and covers all the template
- parameters. */
- tdecl = TREE_VALUE (t);
- type = DECL_CONTEXT (DECL_TEMPLATE_RESULT (tdecl));
- classparms = UPT_PARMS (type);
- nparms = TREE_VEC_LENGTH (classparms);
- parmvec = make_tree_vec (nparms);
- for (i = 0; i < nparms; i++)
- TREE_VEC_ELT (parmvec, i) = NULL_TREE;
- switch (unify (DECL_TEMPLATE_PARMS (tdecl),
- &TREE_VEC_ELT (parmvec, 0), nparms,
- type, IDENTIFIER_TYPE_VALUE (classname),
- &xxx))
- {
- case 0:
- /* Success -- well, no inconsistency, at least. */
- for (i = 0; i < nparms; i++)
- if (TREE_VEC_ELT (parmvec, i) == NULL_TREE)
- goto failure;
- t2 = instantiate_template (tdecl,
- &TREE_VEC_ELT (parmvec, 0));
- type = IDENTIFIER_TYPE_VALUE (id);
- my_friendly_assert (type != 0, 277);
- if (CLASSTYPE_INTERFACE_UNKNOWN (type))
- {
- DECL_EXTERNAL (t2) = 0;
- TREE_PUBLIC (t2) = 0;
- }
- else
- {
- DECL_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type);
- TREE_PUBLIC (t2) = 1;
- }
- break;
- case 1:
- /* Failure. */
- failure:
- error ("type unification error instantiating %s::%s",
- IDENTIFIER_POINTER (classname),
- IDENTIFIER_POINTER (DECL_NAME (tdecl)));
- error_with_decl (tdecl, "for template declaration `%s'");
-
- continue /* loop of members */;
- default:
- /* Eek, a bug. */
- my_friendly_abort (83);
- }
- }
-}
-
-tree
-instantiate_class_template (classname, setup_parse)
- tree classname;
- int setup_parse;
-{
- struct template_info *template_info;
- tree template, t1;
-
- if (classname == error_mark_node)
- return error_mark_node;
-
- my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 278);
- template = IDENTIFIER_TEMPLATE (classname);
-
- if (IDENTIFIER_HAS_TYPE_VALUE (classname))
- {
- tree type = IDENTIFIER_TYPE_VALUE (classname);
- if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- return type;
- if (TYPE_BEING_DEFINED (type)
- || TYPE_SIZE (type)
- || CLASSTYPE_USE_TEMPLATE (type) != 0)
- return type;
- }
- if (uses_template_parms (classname))
- {
- if (!TREE_TYPE (classname))
- {
- tree t = make_lang_type (RECORD_TYPE);
- tree d = build_lang_decl (TYPE_DECL, classname, t);
- DECL_NAME (d) = classname;
- TYPE_NAME (t) = d;
- pushdecl (d);
- }
- return NULL_TREE;
- }
-
- t1 = TREE_PURPOSE (template);
- my_friendly_assert (TREE_CODE (t1) == TEMPLATE_DECL, 279);
-
- /* If a template is declared but not defined, accept it; don't crash.
- Later uses requiring the definition will be flagged as errors by
- other code. Thanks to niklas@appli.se for this bug fix. */
- if (DECL_TEMPLATE_INFO (t1)->text == 0)
- setup_parse = 0;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "instantiate_class_template");
- debug_bindings_indentation += 4;
-#endif
-
- push_to_top_level ();
- push_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (template)),
- TREE_VALUE (template), 0);
- set_current_level_tags_transparency (1);
- template_info = DECL_TEMPLATE_INFO (t1);
- if (setup_parse)
- {
- feed_input (template_info->text, template_info->length, (struct obstack *)0);
- lineno = template_info->lineno;
- input_filename = template_info->filename;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- overload_template_name (classname, 0);
- yychar = PRE_PARSED_CLASS_DECL;
- yylval.ttype = build_tree_list (class_type_node, classname);
- processing_template_defn++;
- }
- else
- {
- tree t, decl, id, tmpl;
-
- id = classname;
- tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE (id));
- t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, id, NULL_TREE);
- my_friendly_assert (TREE_CODE (t) == RECORD_TYPE, 280);
-#if 1
- lineno = template_info->lineno;
- input_filename = template_info->filename;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
-#endif
-
- /* Now, put a copy of the decl in global scope, to avoid
- * recursive expansion. */
- decl = IDENTIFIER_LOCAL_VALUE (id);
- if (!decl)
- decl = IDENTIFIER_CLASS_VALUE (id);
- if (decl)
- {
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 281);
- /* We'd better make sure we're on the permanent obstack or else
- * we'll get a "friendly" abort 124 in pushdecl. Perhaps a
- * copy_to_permanent would be sufficient here, but then a
- * sharing problem might occur. I don't know -- niklas@appli.se */
- push_obstacks (&permanent_obstack, &permanent_obstack);
- pushdecl_top_level (copy_node (decl));
- pop_obstacks ();
- }
- pop_from_top_level ();
- }
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-
- return NULL_TREE;
-}
-
-static int
-list_eq (t1, t2)
- tree t1, t2;
-{
- if (t1 == NULL_TREE)
- return t2 == NULL_TREE;
- if (t2 == NULL_TREE)
- return 0;
- /* Don't care if one declares its arg const and the other doesn't -- the
- main variant of the arg type is all that matters. */
- if (TYPE_MAIN_VARIANT (TREE_VALUE (t1))
- != TYPE_MAIN_VARIANT (TREE_VALUE (t2)))
- return 0;
- return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));
-}
-
-static tree
-tsubst (t, args, nargs, in_decl)
- tree t, *args;
- int nargs;
- tree in_decl;
-{
- tree type;
-
- if (t == NULL_TREE || t == error_mark_node)
- return t;
-
- type = TREE_TYPE (t);
- if (type
- /* Minor optimization.
- ?? Are these really the most frequent cases? Is the savings
- significant? */
- && type != integer_type_node
- && type != void_type_node
- && type != char_type_node)
- type = build_type_variant (tsubst (type, args, nargs, in_decl),
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- switch (TREE_CODE (t))
- {
- case ERROR_MARK:
- case IDENTIFIER_NODE:
- case OP_IDENTIFIER:
- case VOID_TYPE:
- case REAL_TYPE:
- case ENUMERAL_TYPE:
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- case RECORD_TYPE:
- case UNION_TYPE:
- return t;
-
- case INTEGER_TYPE:
- if (t == integer_type_node)
- return t;
-
- if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
- && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
- return t;
- return build_index_2_type (tsubst (TYPE_MIN_VALUE (t), args, nargs, in_decl),
- tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl));
-
- case TEMPLATE_TYPE_PARM:
- return build_type_variant (args[TEMPLATE_TYPE_IDX (t)],
- TYPE_READONLY (t),
- TYPE_VOLATILE (t));
-
- case TEMPLATE_CONST_PARM:
- return args[TEMPLATE_CONST_IDX (t)];
-
- case FUNCTION_DECL:
- {
- tree r;
- tree fnargs, result;
-
- if (type == TREE_TYPE (t)
- && (DECL_CONTEXT (t) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't'))
- return t;
- fnargs = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
- result = tsubst (DECL_RESULT (t), args, nargs, t);
- if (DECL_CONTEXT (t) != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')
- {
- /* Look it up in that class, and return the decl node there,
- instead of creating a new one. */
- tree ctx, methods, name, method;
- int n_methods;
- int i, found = 0;
-
- name = DECL_NAME (t);
- ctx = tsubst (DECL_CONTEXT (t), args, nargs, t);
- methods = CLASSTYPE_METHOD_VEC (ctx);
- if (methods == NULL_TREE)
- /* No methods at all -- no way this one can match. */
- goto no_match;
- n_methods = TREE_VEC_LENGTH (methods);
-
- r = NULL_TREE;
-
- if (!strncmp (OPERATOR_TYPENAME_FORMAT,
- IDENTIFIER_POINTER (name),
- sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
- {
- /* Type-conversion operator. Reconstruct the name, in
- case it's the name of one of the template's parameters. */
- name = build_typename_overload (TREE_TYPE (type));
- }
-
- if (DECL_CONTEXT (t) != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'
- && constructor_name (DECL_CONTEXT (t)) == DECL_NAME (t))
- name = constructor_name (ctx);
-#if 0
- fprintf (stderr, "\nfor function %s in class %s:\n",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));
-#endif
- for (i = 0; i < n_methods; i++)
- {
- int pass;
-
- method = TREE_VEC_ELT (methods, i);
- if (method == NULL_TREE || DECL_NAME (method) != name)
- continue;
-
- pass = 0;
- maybe_error:
- for (; method; method = TREE_CHAIN (method))
- {
- my_friendly_assert (TREE_CODE (method) == FUNCTION_DECL,
- 282);
- if (TREE_TYPE (method) != type)
- {
- tree mtype = TREE_TYPE (method);
- tree t1, t2;
-
- /* Keep looking for a method that matches
- perfectly. This takes care of the problem
- where destructors (which have implicit int args)
- look like constructors which have an int arg. */
- if (pass == 0)
- continue;
-
- t1 = TYPE_ARG_TYPES (mtype);
- t2 = TYPE_ARG_TYPES (type);
- if (TREE_CODE (mtype) == FUNCTION_TYPE)
- t2 = TREE_CHAIN (t2);
-
- if (list_eq (t1, t2))
- {
- if (TREE_CODE (mtype) == FUNCTION_TYPE)
- {
- tree newtype;
- newtype = build_function_type (TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- newtype = build_type_variant (newtype,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- type = newtype;
- if (TREE_TYPE (type) != TREE_TYPE (mtype))
- goto maybe_bad_return_type;
- }
- else if (TYPE_METHOD_BASETYPE (mtype)
- == TYPE_METHOD_BASETYPE (type))
- {
- /* Types didn't match, but arg types and
- `this' do match, so the return type is
- all that should be messing it up. */
- maybe_bad_return_type:
- if (TREE_TYPE (type) != TREE_TYPE (mtype))
- error ("inconsistent return types for method `%s' in class `%s'",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));
- }
- r = method;
- break;
- }
- found = 1;
- continue;
- }
-#if 0
- fprintf (stderr, "\tfound %s\n\n",
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method)));
-#endif
- if (DECL_ARGUMENTS (method)
- && ! TREE_PERMANENT (DECL_ARGUMENTS (method)))
- /* @@ Is this early enough? Might we want to do
- this instead while processing the expansion? */
- DECL_ARGUMENTS (method)
- = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
- r = method;
- break;
- }
- if (r == NULL_TREE && pass == 0)
- {
- pass = 1;
- method = TREE_VEC_ELT (methods, i);
- goto maybe_error;
- }
- }
- if (r == NULL_TREE)
- {
- no_match:
- error (found
- ? "template for method `%s' doesn't match any in class `%s'"
- : "method `%s' not found in class `%s'",
- IDENTIFIER_OPNAME_P (name)
- ? operator_name_string (name) : IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));
- if (in_decl)
- error_with_decl (in_decl, "in attempt to instantiate `%s' declared at this point in file");
- return error_mark_node;
- }
- }
- else
- {
- r = DECL_NAME (t);
- {
- tree decls, val;
- int got_it = 0;
-
- decls = IDENTIFIER_GLOBAL_VALUE (r);
- if (decls == NULL_TREE)
- /* no match */;
- else if (TREE_CODE (decls) == TREE_LIST)
- while (decls)
- {
- val = TREE_VALUE (decls);
- decls = TREE_CHAIN (decls);
- try_one:
- if (TREE_CODE (val) == FUNCTION_DECL
- && TREE_TYPE (val) == type)
- {
- got_it = 1;
- r = val;
- break;
- }
- }
- else
- {
- val = decls;
- decls = NULL_TREE;
- goto try_one;
- }
-
- if (!got_it)
- {
- r = build_decl_overload (r, TYPE_VALUES (type),
- DECL_CONTEXT (t) != NULL_TREE);
- r = build_lang_decl (FUNCTION_DECL, r, type);
- }
- }
- }
- TREE_PUBLIC (r) = TREE_PUBLIC (t);
- DECL_EXTERNAL (r) = DECL_EXTERNAL (t);
- TREE_STATIC (r) = TREE_STATIC (t);
- DECL_INLINE (r) = DECL_INLINE (t);
- DECL_SOURCE_FILE (r) = DECL_SOURCE_FILE (t);
- DECL_SOURCE_LINE (r) = DECL_SOURCE_LINE (t);
- DECL_CLASS_CONTEXT (r) = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, t);
- make_decl_rtl (r, NULL_PTR, 1);
- DECL_ARGUMENTS (r) = fnargs;
- DECL_RESULT (r) = result;
- if (DECL_CONTEXT (t) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't')
- push_overloaded_decl_top_level (r, 0);
- return r;
- }
-
- case PARM_DECL:
- {
- tree r;
- r = build_decl (PARM_DECL, DECL_NAME (t), type);
- DECL_INITIAL (r) = TREE_TYPE (r);
- if (TREE_CHAIN (t))
- TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, nargs, TREE_CHAIN (t));
- return r;
- }
-
- case TREE_LIST:
- {
- tree purpose, value, chain, result;
- int via_public, via_virtual, via_protected;
-
- if (t == void_list_node)
- return t;
-
- via_public = TREE_VIA_PUBLIC (t);
- via_protected = TREE_VIA_PROTECTED (t);
- via_virtual = TREE_VIA_VIRTUAL (t);
-
- purpose = TREE_PURPOSE (t);
- if (purpose)
- purpose = tsubst (purpose, args, nargs, in_decl);
- value = TREE_VALUE (t);
- if (value)
- value = tsubst (value, args, nargs, in_decl);
- chain = TREE_CHAIN (t);
- if (chain && chain != void_type_node)
- chain = tsubst (chain, args, nargs, in_decl);
- if (purpose == TREE_PURPOSE (t)
- && value == TREE_VALUE (t)
- && chain == TREE_CHAIN (t))
- return t;
- result = hash_tree_cons (via_public, via_virtual, via_protected,
- purpose, value, chain);
- TREE_PARMLIST (result) = TREE_PARMLIST (t);
- return result;
- }
- case TREE_VEC:
- {
- int len = TREE_VEC_LENGTH (t), need_new = 0, i;
- tree *elts = (tree *) alloca (len * sizeof (tree));
- bzero (elts, len * sizeof (tree));
-
- for (i = 0; i < len; i++)
- {
- elts[i] = tsubst (TREE_VEC_ELT (t, i), args, nargs, in_decl);
- if (elts[i] != TREE_VEC_ELT (t, i))
- need_new = 1;
- }
-
- if (!need_new)
- return t;
-
- t = make_tree_vec (len);
- for (i = 0; i < len; i++)
- TREE_VEC_ELT (t, i) = elts[i];
- return t;
- }
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- {
- tree r;
- enum tree_code code;
- if (type == TREE_TYPE (t))
- return t;
-
- code = TREE_CODE (t);
- if (code == POINTER_TYPE)
- r = build_pointer_type (type);
- else
- r = build_reference_type (type);
- r = build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t));
- /* Will this ever be needed for TYPE_..._TO values? */
- layout_type (r);
- return r;
- }
- case FUNCTION_TYPE:
- case METHOD_TYPE:
- {
- tree values = TYPE_VALUES (t); /* same as TYPE_ARG_TYPES */
- tree context = TYPE_CONTEXT (t);
- tree new_value;
-
- /* Don't bother recursing if we know it won't change anything. */
- if (! (values == void_type_node
- || values == integer_type_node))
- values = tsubst (values, args, nargs, in_decl);
- if (context)
- context = tsubst (context, args, nargs, in_decl);
- /* Could also optimize cases where return value and
- values have common elements (e.g., T min(const &T, const T&). */
-
- /* If the above parameters haven't changed, just return the type. */
- if (type == TREE_TYPE (t)
- && values == TYPE_VALUES (t)
- && context == TYPE_CONTEXT (t))
- return t;
-
- /* Construct a new type node and return it. */
- if (TREE_CODE (t) == FUNCTION_TYPE
- && context == NULL_TREE)
- {
- new_value = build_function_type (type, values);
- }
- else if (context == NULL_TREE)
- {
- tree base = tsubst (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))),
- args, nargs, in_decl);
- new_value = build_cplus_method_type (base, type,
- TREE_CHAIN (values));
- }
- else
- {
- new_value = make_node (TREE_CODE (t));
- TREE_TYPE (new_value) = type;
- TYPE_CONTEXT (new_value) = context;
- TYPE_VALUES (new_value) = values;
- TYPE_SIZE (new_value) = TYPE_SIZE (t);
- TYPE_ALIGN (new_value) = TYPE_ALIGN (t);
- TYPE_MODE (new_value) = TYPE_MODE (t);
- if (TYPE_METHOD_BASETYPE (t))
- TYPE_METHOD_BASETYPE (new_value) = tsubst (TYPE_METHOD_BASETYPE (t),
- args, nargs, in_decl);
- /* Need to generate hash value. */
- my_friendly_abort (84);
- }
- new_value = build_type_variant (new_value,
- TYPE_READONLY (t),
- TYPE_VOLATILE (t));
- return new_value;
- }
- case ARRAY_TYPE:
- {
- tree domain = tsubst (TYPE_DOMAIN (t), args, nargs, in_decl);
- tree r;
- if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))
- return t;
- r = build_cplus_array_type (type, domain);
- return r;
- }
-
- case UNINSTANTIATED_P_TYPE:
- {
- int nparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (UPT_TEMPLATE (t)));
- tree argvec = make_tree_vec (nparms);
- tree parmvec = UPT_PARMS (t);
- int i;
- tree id;
- for (i = 0; i < nparms; i++)
- TREE_VEC_ELT (argvec, i) = tsubst (TREE_VEC_ELT (parmvec, i),
- args, nargs, in_decl);
- id = lookup_template_class (DECL_NAME (UPT_TEMPLATE (t)), argvec, NULL_TREE);
- if (! IDENTIFIER_HAS_TYPE_VALUE (id)) {
- instantiate_class_template(id, 0);
- /* set up pending_classes */
- add_pending_template (id);
-
- TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (id)) =
- IDENTIFIER_TYPE_VALUE (id);
- }
- return build_type_variant (IDENTIFIER_TYPE_VALUE (id),
- TYPE_READONLY (t),
- TYPE_VOLATILE (t));
- }
-
- case MINUS_EXPR:
- case PLUS_EXPR:
- return fold (build (TREE_CODE (t), TREE_TYPE (t),
- tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
- tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl)));
-
- case NEGATE_EXPR:
- case NOP_EXPR:
- return fold (build1 (TREE_CODE (t), TREE_TYPE (t),
- tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl)));
-
- default:
- sorry ("use of `%s' in function template",
- tree_code_name [(int) TREE_CODE (t)]);
- return error_mark_node;
- }
-}
-
-tree
-instantiate_template (tmpl, targ_ptr)
- tree tmpl, *targ_ptr;
-{
- tree targs, fndecl;
- int i, len;
- struct pending_inline *p;
- struct template_info *t;
- struct obstack *old_fmp_obstack;
- extern struct obstack *function_maybepermanent_obstack;
-
- push_obstacks (&permanent_obstack, &permanent_obstack);
- old_fmp_obstack = function_maybepermanent_obstack;
- function_maybepermanent_obstack = &permanent_obstack;
-
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
- len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
-
- for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
- fndecl; fndecl = TREE_CHAIN (fndecl))
- {
- tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0);
- for (i = len - 1; i >= 0; i--)
- if (t1[i] != targ_ptr[i])
- goto no_match;
-
- /* Here, we have a match. */
- fndecl = TREE_VALUE (fndecl);
- function_maybepermanent_obstack = old_fmp_obstack;
- pop_obstacks ();
- return fndecl;
-
- no_match:
- ;
- }
-
- targs = make_tree_vec (len);
- i = len;
- while (i--)
- TREE_VEC_ELT (targs, i) = targ_ptr[i];
-
- /* substitute template parameters */
- fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr,
- TREE_VEC_LENGTH (targs), tmpl);
-
- /* If it's a static member fn in the template, we need to change it
- into a FUNCTION_TYPE and chop off its this pointer. */
- if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE
- && fndecl != error_mark_node
- && DECL_STATIC_FUNCTION_P (fndecl))
- {
- tree olddecl = DECL_RESULT (tmpl);
- revert_static_member_fn (&TREE_TYPE (olddecl), &DECL_RESULT (tmpl),
- &TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
- /* Chop off the this pointer that grokclassfn so kindly added
- for us (it didn't know yet if the fn was static or not). */
- DECL_ARGUMENTS (olddecl) = TREE_CHAIN (DECL_ARGUMENTS (olddecl));
- DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
- }
-
- t = DECL_TEMPLATE_INFO (tmpl);
- if (t->text)
- {
- p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
- p->parm_vec = t->parm_vec;
- p->bindings = targs;
- p->can_free = 0;
- p->deja_vu = 0;
- p->lineno = t->lineno;
- p->filename = t->filename;
- p->buf = t->text;
- p->len = t->length;
- p->fndecl = fndecl;
- p->interface = 1; /* unknown */
- }
- else
- p = (struct pending_inline *)0;
-
- DECL_TEMPLATE_INSTANTIATIONS (tmpl) =
- tree_cons (targs, fndecl, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
-
- function_maybepermanent_obstack = old_fmp_obstack;
- pop_obstacks ();
-
- if (fndecl == error_mark_node || p == (struct pending_inline *)0)
- {
- /* do nothing */
- }
- else if (DECL_INLINE (fndecl))
- {
- DECL_PENDING_INLINE_INFO (fndecl) = p;
- p->next = pending_inlines;
- pending_inlines = p;
- }
- else
- {
- p->next = pending_template_expansions;
- pending_template_expansions = p;
- }
- return fndecl;
-}
-
-void
-undo_template_name_overload (id, classlevel)
- tree id;
- int classlevel;
-{
- tree template;
-
- template = IDENTIFIER_TEMPLATE (id);
- if (!template)
- return;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "undo_template_name_overload");
- debug_bindings_indentation += 4;
-#endif
-
-#if 0 /* not yet, should get fixed properly later */
- poplevel (0, 0, 0);
-#endif
- if (!classlevel)
- poplevel (0, 0, 0);
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-void
-overload_template_name (id, classlevel)
- tree id;
- int classlevel;
-{
- tree template, t, decl;
- struct template_info *tinfo;
-
- my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 284);
- template = IDENTIFIER_TEMPLATE (id);
- if (!template)
- return;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "overload_template_name(%d)", classlevel);
- debug_bindings_indentation += 4;
-#endif
- template = TREE_PURPOSE (template);
- tinfo = DECL_TEMPLATE_INFO (template);
- template = DECL_NAME (template);
- my_friendly_assert (template != NULL_TREE, 285);
-
- if (!classlevel)
- {
- pushlevel (1);
- declare_pseudo_global_level ();
- }
-
- t = xref_tag (tinfo->aggr, id, NULL_TREE);
- my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
- || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);
-
- decl = build_decl (TYPE_DECL, template, t);
-
-#if 0 /* fix this later */
- /* We don't want to call here if the work has already been done. */
- t = (classlevel
- ? IDENTIFIER_CLASS_VALUE (template)
- : IDENTIFIER_LOCAL_VALUE (template));
- if (t
- && TREE_CODE (t) == TYPE_DECL
- && TREE_TYPE (t) == t)
- my_friendly_abort (85);
-#endif
-
- if (classlevel)
- pushdecl_class_level (decl);
- else
-#if 0 /* not yet, should get fixed properly later */
- pushdecl (decl);
- pushlevel (1);
-#else
- {
- pushdecl (decl);
- /* @@ Is this necessary now? */
- IDENTIFIER_LOCAL_VALUE (template) = decl;
- }
-#endif
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-/* T1 is PRE_PARSED_CLASS_DECL; T3 is result of XREF_TAG lookup. */
-void
-end_template_instantiation (t1, t3)
- tree t1, t3;
-{
- extern struct pending_input *to_be_restored;
- tree t, decl;
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- indent_to (stderr, debug_bindings_indentation);
- fprintf (stderr, "end_template_instantiation");
- debug_bindings_indentation += 4;
-#endif
-
- processing_template_defn--;
-
- /* Restore the old parser input state. */
- if (yychar == YYEMPTY)
- yychar = yylex ();
- if (yychar != END_OF_SAVED_INPUT)
- error ("parse error at end of class template");
- else
- {
- restore_pending_input (to_be_restored);
- to_be_restored = 0;
- }
-
- /* Our declarations didn't get stored in the global slot, since
- there was a (supposedly tags-transparent) scope in between. */
- t = IDENTIFIER_TYPE_VALUE (TREE_VALUE (t1));
- my_friendly_assert (t != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (t)) == 't',
- 287);
- CLASSTYPE_USE_TEMPLATE (t) = 2;
- /* Always make methods of template classes static, until we've
- got a decent scheme for handling them. The pragmas as they
- are now are inadequate. */
- CLASSTYPE_INTERFACE_UNKNOWN (t) = 1;
- decl = IDENTIFIER_GLOBAL_VALUE (TREE_VALUE (t1));
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 288);
-
- undo_template_name_overload (TREE_VALUE (t1), 0);
- t = IDENTIFIER_TEMPLATE (TREE_VALUE (t1));
- pop_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (t)), TREE_VALUE (t),
- 0);
- pop_from_top_level ();
-
- /* This will fix up the type-value field. */
- pushdecl_top_level (decl);
-
- /* Restore interface/implementation settings. */
- extract_interface_info ();
-
-#ifdef DEBUG_CP_BINDING_LEVELS
- debug_bindings_indentation -= 4;
-#endif
-}
-
-/* Store away the text of an inline template function. No rtl is
- generated for this function until it is actually needed. */
-
-void
-reinit_parse_for_template (yychar, d1, d2)
- int yychar;
- tree d1, d2;
-{
- struct template_info *template_info;
-
- if (d2 == NULL_TREE || d2 == error_mark_node)
- {
- lose:
- /* @@ Should use temp obstack, and discard results. */
- reinit_parse_for_block (yychar, &permanent_obstack, 1);
- return;
- }
-
- if (TREE_CODE (d2) == IDENTIFIER_NODE)
- d2 = IDENTIFIER_GLOBAL_VALUE (d2);
- if (!d2)
- goto lose;
- template_info = DECL_TEMPLATE_INFO (d2);
- if (!template_info)
- {
- template_info = (struct template_info *) permalloc (sizeof (struct template_info));
- bzero (template_info, sizeof (struct template_info));
- DECL_TEMPLATE_INFO (d2) = template_info;
- }
- template_info->filename = input_filename;
- template_info->lineno = lineno;
- reinit_parse_for_block (yychar, &permanent_obstack, 1);
- template_info->text = obstack_base (&permanent_obstack);
- template_info->length = obstack_object_size (&permanent_obstack);
- obstack_finish (&permanent_obstack);
- template_info->parm_vec = d1;
-}
-
-/* Type unification.
-
- We have a function template signature with one or more references to
- template parameters, and a parameter list we wish to fit to this
- template. If possible, produce a list of parameters for the template
- which will cause it to fit the supplied parameter list.
-
- Return zero for success, 2 for an incomplete match that doesn't resolve
- all the types, and 1 for complete failure. An error message will be
- printed only for an incomplete match.
-
- TPARMS[NTPARMS] is an array of template parameter types;
- TARGS[NTPARMS] is the array of template parameter values. PARMS is
- the function template's signature (using TEMPLATE_PARM_IDX nodes),
- and ARGS is the argument list we're trying to match against it. */
-
-int
-type_unification (tparms, targs, parms, args, nsubsts)
- tree tparms, *targs, parms, args;
- int *nsubsts;
-{
- tree parm, arg;
- int i;
- int ntparms = TREE_VEC_LENGTH (tparms);
-
- my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
- my_friendly_assert (TREE_CODE (parms) == TREE_LIST, 290);
- /* ARGS could be NULL (via a call from cp-parse.y to
- build_x_function_call). */
- if (args)
- my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
- my_friendly_assert (ntparms > 0, 292);
-
- bzero (targs, sizeof (tree) * ntparms);
-
- while (parms
- && parms != void_list_node
- && args)
- {
- parm = TREE_VALUE (parms);
- parms = TREE_CHAIN (parms);
- arg = TREE_VALUE (args);
- args = TREE_CHAIN (args);
-
- if (arg == error_mark_node)
- return 1;
- if (arg == unknown_type_node)
- return 1;
-#if 0
- if (TREE_CODE (arg) == VAR_DECL)
- arg = TREE_TYPE (arg);
- else if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'e')
- arg = TREE_TYPE (arg);
-#else
- my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);
- arg = TREE_TYPE (arg);
-#endif
-
- switch (unify (tparms, targs, ntparms, parm, arg, nsubsts))
- {
- case 0:
- break;
- case 1:
- return 1;
- }
- }
- /* Fail if we've reached the end of the parm list, and more args
- are present, and the parm list isn't variadic. */
- if (args && parms == void_list_node)
- return 1;
- /* Fail if parms are left and they don't have default values. */
- if (parms
- && parms != void_list_node
- && TREE_PURPOSE (parms) == NULL_TREE)
- return 1;
- for (i = 0; i < ntparms; i++)
- if (!targs[i])
- {
- error ("incomplete type unification");
- return 2;
- }
- return 0;
-}
-
-/* Tail recursion is your friend. */
-static int
-unify (tparms, targs, ntparms, parm, arg, nsubsts)
- tree tparms, *targs, parm, arg;
- int *nsubsts;
-{
- int idx;
-
- /* I don't think this will do the right thing with respect to types.
- But the only case I've seen it in so far has been array bounds, where
- signedness is the only information lost, and I think that will be
- okay. */
- while (TREE_CODE (parm) == NOP_EXPR)
- parm = TREE_OPERAND (parm, 0);
-
- if (arg == error_mark_node)
- return 1;
- if (arg == unknown_type_node)
- return 1;
- if (arg == parm)
- return 0;
-
- switch (TREE_CODE (parm))
- {
- case TEMPLATE_TYPE_PARM:
- (*nsubsts)++;
- if (TEMPLATE_TYPE_TPARMLIST (parm) != tparms)
- {
- error ("mixed template headers?!");
- my_friendly_abort (86);
- return 1;
- }
- idx = TEMPLATE_TYPE_IDX (parm);
- /* Simple cases: Value already set, does match or doesn't. */
- if (targs[idx] == arg)
- return 0;
- else if (targs[idx])
- return 1;
- /* Check for mixed types and values. */
- if (TREE_CODE (TREE_VEC_ELT (tparms, idx)) != IDENTIFIER_NODE)
- return 1;
- targs[idx] = arg;
- return 0;
- case TEMPLATE_CONST_PARM:
- (*nsubsts)++;
- idx = TEMPLATE_CONST_IDX (parm);
- if (targs[idx] == arg)
- return 0;
- else if (targs[idx])
- {
- my_friendly_abort (87);
- return 1;
- }
-/* else if (typeof arg != tparms[idx])
- return 1;*/
-
- targs[idx] = copy_to_permanent (arg);
- return 0;
-
- case POINTER_TYPE:
- if (TREE_CODE (arg) != POINTER_TYPE)
- return 1;
- return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
- nsubsts);
-
- case REFERENCE_TYPE:
- return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, nsubsts);
-
- case ARRAY_TYPE:
- if (TREE_CODE (arg) != ARRAY_TYPE)
- return 1;
- if (unify (tparms, targs, ntparms, TYPE_DOMAIN (parm), TYPE_DOMAIN (arg),
- nsubsts) != 0)
- return 1;
- return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
- nsubsts);
-
- case REAL_TYPE:
- case INTEGER_TYPE:
- if (TREE_CODE (parm) == INTEGER_TYPE && TREE_CODE (arg) == INTEGER_TYPE)
- {
- if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
- && unify (tparms, targs, ntparms,
- TYPE_MIN_VALUE (parm), TYPE_MIN_VALUE (arg), nsubsts))
- return 1;
- if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
- && unify (tparms, targs, ntparms,
- TYPE_MAX_VALUE (parm), TYPE_MAX_VALUE (arg), nsubsts))
- return 1;
- }
- /* As far as unification is concerned, this wins. Later checks
- will invalidate it if necessary. */
- return 0;
-
- /* Types INTEGER_CST and MINUS_EXPR can come from array bounds. */
- case INTEGER_CST:
- if (TREE_CODE (arg) != INTEGER_CST)
- return 1;
- return !tree_int_cst_equal (parm, arg);
-
- case MINUS_EXPR:
- {
- tree t1, t2;
- t1 = TREE_OPERAND (parm, 0);
- t2 = TREE_OPERAND (parm, 1);
- if (TREE_CODE (t1) != TEMPLATE_CONST_PARM)
- return 1;
- return unify (tparms, targs, ntparms, t1,
- fold (build (PLUS_EXPR, integer_type_node, arg, t2)),
- nsubsts);
- }
-
- case TREE_VEC:
- {
- int i;
- if (TREE_CODE (arg) != TREE_VEC)
- return 1;
- if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
- return 1;
- for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)
- if (unify (tparms, targs, ntparms,
- TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
- nsubsts))
- return 1;
- return 0;
- }
-
- case UNINSTANTIATED_P_TYPE:
- {
- tree a;
- /* Unification of something that is not a template fails. (mrs) */
- if (TYPE_NAME (arg) == 0)
- return 1;
- a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg));
- /* Unification of something that is not a template fails. (mrs) */
- if (a == 0)
- return 1;
- if (UPT_TEMPLATE (parm) != TREE_PURPOSE (a))
- /* different templates */
- return 1;
- return unify (tparms, targs, ntparms, UPT_PARMS (parm), TREE_VALUE (a),
- nsubsts);
- }
-
- case RECORD_TYPE:
- /* Unification of something that is not a template fails. (mrs) */
- return 1;
-
- default:
- sorry ("use of `%s' in template type unification",
- tree_code_name [(int) TREE_CODE (parm)]);
- return 1;
- }
-}
-
-
-#undef DEBUG
-
-int
-do_pending_expansions ()
-{
- struct pending_inline *i, *new_list = 0;
-
- if (!pending_template_expansions)
- return 0;
-
-#ifdef DEBUG
- fprintf (stderr, "\n\n\t\t IN DO_PENDING_EXPANSIONS\n\n");
-#endif
-
- i = pending_template_expansions;
- while (i)
- {
- tree context;
-
- struct pending_inline *next = i->next;
- tree t = i->fndecl;
-
- int decision = 0;
-#define DECIDE(N) if(1){decision=(N); goto decided;}else
-
- my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
- || TREE_CODE (t) == VAR_DECL, 294);
- if (TREE_ASM_WRITTEN (t))
- DECIDE (0);
- /* If it's a method, let the class type decide it.
- @@ What if the method template is in a separate file?
- Maybe both file contexts should be taken into account? */
- context = DECL_CONTEXT (t);
- if (context != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (context)) == 't')
- {
- /* If `unknown', we might want a static copy.
- If `implementation', we want a global one.
- If `interface', ext ref. */
- if (!CLASSTYPE_INTERFACE_UNKNOWN (context))
- DECIDE (!CLASSTYPE_INTERFACE_ONLY (context));
-#if 0 /* This doesn't get us stuff needed only by the file initializer. */
- DECIDE (TREE_USED (t));
-#else /* This compiles too much stuff, but that's probably better in
- most cases than never compiling the stuff we need. */
- DECIDE (1);
-#endif
- }
- /* else maybe call extract_interface_info? */
- if (TREE_USED (t)) /* is this right? */
- DECIDE (1);
-
- decided:
-#ifdef DEBUG
- print_node_brief (stderr, decision ? "yes: " : "no: ", t, 0);
- fprintf (stderr, "\t%s\n",
- (DECL_ASSEMBLER_NAME (t)
- ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t))
- : ""));
-#endif
- if (decision == 1)
- {
- i->next = pending_inlines;
- pending_inlines = i;
- }
- else
- {
- i->next = new_list;
- new_list = i;
- }
- i = next;
- }
- pending_template_expansions = new_list;
- if (!pending_inlines)
- return 0;
- do_pending_inlines ();
- return 1;
-}
-
-
-struct pending_template {
- struct pending_template *next;
- tree id;
-};
-
-static struct pending_template* pending_templates;
-
-void
-do_pending_templates ()
-{
- struct pending_template* t;
-
- for ( t = pending_templates; t; t = t->next)
- {
- instantiate_class_template (t->id, 1);
- }
-
- for ( t = pending_templates; t; t = pending_templates)
- {
- pending_templates = t->next;
- free(t);
- }
-}
-
-static void
-add_pending_template (pt)
- tree pt;
-{
- struct pending_template *p;
-
- p = (struct pending_template *) malloc (sizeof (struct pending_template));
- p->next = pending_templates;
- pending_templates = p;
- p->id = pt;
-}
diff --git a/gnu/gcc2/cc1plus/cp-ptree.c b/gnu/gcc2/cc1plus/cp-ptree.c
deleted file mode 100644
index a976fac36ddf..000000000000
--- a/gnu/gcc2/cc1plus/cp-ptree.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* Prints out trees in human readable form.
- Copyright (C) 1992, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-
-#include "config.h"
-#include "tree.h"
-#include <stdio.h>
-#include "cp-tree.h"
-
-void
-print_lang_decl (file, node, indent)
- FILE *file;
- tree node;
- int indent;
-{
- if (!DECL_LANG_SPECIFIC (node))
- return;
- /* A FIELD_DECL only has the flags structure, which we aren't displaying
- anyways. */
- if (TREE_CODE (node) == FIELD_DECL)
- return;
- indent_to (file, indent + 3);
- if (DECL_MAIN_VARIANT (node))
- {
- fprintf (file, " decl-main-variant ");
- fprintf (file, HOST_PTR_PRINTF, DECL_MAIN_VARIANT (node));
- }
- if (DECL_PENDING_INLINE_INFO (node))
- {
- fprintf (file, " pending-inline-info ");
- fprintf (file, HOST_PTR_PRINTF, DECL_PENDING_INLINE_INFO (node));
- }
- if (DECL_TEMPLATE_INFO (node))
- {
- fprintf (file, " template-info ");
- fprintf (file, HOST_PTR_PRINTF, DECL_TEMPLATE_INFO (node));
- }
-}
-
-void
-print_lang_type (file, node, indent)
- FILE *file;
- register tree node;
- int indent;
-{
- if (TREE_CODE (node) == TEMPLATE_TYPE_PARM)
- {
- print_node (file, "tinfo", TYPE_VALUES (node), indent + 4);
- return;
- }
-
- if (TREE_CODE (node) == UNINSTANTIATED_P_TYPE)
- {
- print_node (file, "template", UPT_TEMPLATE (node), indent + 4);
- print_node (file, "parameters", UPT_PARMS (node), indent + 4);
- return;
- }
-
- if (! (TREE_CODE (node) == RECORD_TYPE
- || TREE_CODE (node) == UNION_TYPE))
- return;
-
- if (!TYPE_LANG_SPECIFIC (node))
- return;
-
- indent_to (file, indent + 3);
-
- if (TYPE_NEEDS_CONSTRUCTOR (node))
- fputs ( "needs-constructor", file);
- if (TYPE_NEEDS_DESTRUCTOR (node))
- fputs (" needs-destructor", file);
- if (TYPE_HAS_CONVERSION (node))
- fputs (" has-type-conversion", file);
- if (TYPE_HAS_INT_CONVERSION (node))
- fputs (" has-int-conversion", file);
- if (TYPE_HAS_REAL_CONVERSION (node))
- fputs (" has-float-conversion", file);
- if (TYPE_HAS_INIT_REF (node))
- fputs (" X(X&)", file);
- if (TREE_GETS_NEW (node))
- fputs (" gets-new", file);
- if (TREE_GETS_DELETE (node))
- fputs (" gets-delete", file);
- if (TYPE_HAS_ASSIGNMENT (node))
- fputs (" has=", file);
- if (TYPE_GETS_ASSIGNMENT (node))
- fputs (" gets=", file);
- if (TYPE_HAS_ASSIGN_REF (node))
- fputs (" this=(X&)", file);
- if (TYPE_GETS_ASSIGN_REF (node))
- fputs (" gets=(X&)", file);
- if (TYPE_OVERLOADS_METHOD_CALL_EXPR (node))
- fputs (" op->()", file);
- if (TYPE_GETS_INIT_AGGR (node))
- fputs (" gets X(X, ...)", file);
- if (TYPE_OVERLOADS_CALL_EXPR (node))
- fputs (" op()", file);
- if (TYPE_OVERLOADS_ARRAY_REF (node))
- fputs (" op[]", file);
- if (TYPE_OVERLOADS_ARROW (node))
- fputs (" op->", file);
- if (TYPE_USES_MULTIPLE_INHERITANCE (node))
- fputs (" uses-multiple-inheritance", file);
-
- if (TREE_CODE (node) == RECORD_TYPE)
- {
- fprintf (file, " n_parents %d n_ancestors %d",
- CLASSTYPE_N_BASECLASSES (node),
- CLASSTYPE_N_SUPERCLASSES (node));
- fprintf (file, " use_template=%d", CLASSTYPE_USE_TEMPLATE (node));
- if (CLASSTYPE_INTERFACE_ONLY (node))
- fprintf (file, " interface-only");
- if (CLASSTYPE_INTERFACE_UNKNOWN (node))
- fprintf (file, " interface-unknown");
- print_node (file, "member-functions", CLASSTYPE_METHOD_VEC (node),
- indent + 4);
- print_node (file, "baselinks",
- TYPE_BINFO_BASETYPES (node) ? CLASSTYPE_BASELINK_VEC (node) : NULL_TREE,
- indent + 4);
- }
-}
-
-void
-print_lang_identifier (file, node, indent)
- FILE *file;
- tree node;
- int indent;
-{
- print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
- print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
- print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
- print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
- print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
- print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
- print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
-}
diff --git a/gnu/gcc2/cc1plus/cp-search.c b/gnu/gcc2/cc1plus/cp-search.c
deleted file mode 100644
index 9f3e0a5a1549..000000000000
--- a/gnu/gcc2/cc1plus/cp-search.c
+++ /dev/null
@@ -1,4284 +0,0 @@
-/* Breadth-first and depth-first routines for
- searching multiple-inheritance lattice for GNU C++.
- 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. */
-
-#if 0
-/* Remove before release, should only appear for development and testing. */
-#define CHECK_convert_pointer_to_single_level
-#endif
-
-/* High-level class interface. */
-
-#include "config.h"
-#include "tree.h"
-#include <stdio.h>
-#include "cp-tree.h"
-#include "obstack.h"
-#include "flags.h"
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-void init_search ();
-extern struct obstack *current_obstack;
-
-#include "stack.h"
-
-/* Obstack used for remembering decision points of breadth-first. */
-static struct obstack search_obstack;
-
-/* Obstack used to bridge from one function context to another. */
-static struct obstack bridge_obstack;
-
-/* Methods for pushing and popping objects to and from obstacks. */
-
-struct stack_level *
-push_stack_level (obstack, tp, size)
- struct obstack *obstack;
- char *tp; /* Sony NewsOS 5.0 compiler doesn't like void * here. */
- int size;
-{
- struct stack_level *stack;
- /* FIXME. Doesn't obstack_grow, in the case when the current chunk has
- insufficient space, move the base so that obstack_next_free is not
- valid? Perhaps obstack_copy should be used rather than obstack_grow,
- and its returned value be used. -- Raeburn
- */
- stack = (struct stack_level *) obstack_next_free (obstack);
- obstack_grow (obstack, tp, size);
- obstack_finish (obstack);
- stack->obstack = obstack;
- stack->first = (tree *) obstack_base (obstack);
- stack->limit = obstack_room (obstack) / sizeof (tree *);
- return stack;
-}
-
-struct stack_level *
-pop_stack_level (stack)
- struct stack_level *stack;
-{
- struct stack_level *tem = stack;
- struct obstack *obstack = tem->obstack;
- stack = tem->prev;
- obstack_free (obstack, tem);
- return stack;
-}
-
-#define search_level stack_level
-static struct search_level *search_stack;
-
-static tree lookup_field_1 ();
-static int lookup_fnfields_1 ();
-static void dfs_walk ();
-static int markedp ();
-static void dfs_unmark ();
-static void dfs_init_vbase_pointers ();
-
-static tree vbase_types;
-static tree vbase_decl, vbase_decl_ptr;
-static tree vbase_decl_ptr_intermediate;
-static tree vbase_init_result;
-
-/* Allocate a level of searching. */
-static struct search_level *
-push_search_level (stack, obstack)
- struct stack_level *stack;
- struct obstack *obstack;
-{
- struct search_level tem;
- tem.prev = stack;
-
- return push_stack_level (obstack, (char *) &tem, sizeof (tem));
-}
-
-/* Discard a level of search allocation. */
-#define pop_search_level pop_stack_level
-
-/* Search memoization. */
-struct type_level
-{
- struct stack_level base;
-
- /* First object allocated in obstack of entries. */
- char *entries;
-
- /* Number of types memoized in this context. */
- int len;
-
- /* Type being memoized; save this if we are saving
- memoized contexts. */
- tree type;
-};
-
-/* Obstack used for memoizing member and member function lookup. */
-
-static struct obstack type_obstack, type_obstack_entries;
-static struct type_level *type_stack;
-static tree _vptr_name;
-
-/* Make things that look like tree nodes, but allocate them
- on type_obstack_entries. */
-static int my_tree_node_counter;
-static tree my_tree_cons (), my_build_string ();
-
-extern int flag_memoize_lookups, flag_save_memoized_contexts;
-
-/* Variables for gathering statistics. */
-static int my_memoized_entry_counter;
-static int memoized_fast_finds[2], memoized_adds[2], memoized_fast_rejects[2];
-static int memoized_fields_searched[2];
-static int n_fields_searched;
-static int n_calls_lookup_field, n_calls_lookup_field_1;
-static int n_calls_lookup_fnfields, n_calls_lookup_fnfields_1;
-static int n_calls_get_base_type;
-static int n_outer_fields_searched;
-static int n_contexts_saved;
-
-/* Local variables to help save memoization contexts. */
-static tree prev_type_memoized;
-static struct type_level *prev_type_stack;
-
-/* Allocate a level of type memoization context. */
-static struct type_level *
-push_type_level (stack, obstack)
- struct stack_level *stack;
- struct obstack *obstack;
-{
- struct type_level tem;
-
- tem.base.prev = stack;
-
- obstack_finish (&type_obstack_entries);
- tem.entries = (char *) obstack_base (&type_obstack_entries);
- tem.len = 0;
- tem.type = NULL_TREE;
-
- return (struct type_level *)push_stack_level (obstack, (char *) &tem,
- sizeof (tem));
-}
-
-/* Discard a level of type memoization context. */
-
-static struct type_level *
-pop_type_level (stack)
- struct type_level *stack;
-{
- obstack_free (&type_obstack_entries, stack->entries);
- return (struct type_level *)pop_stack_level ((struct stack_level *)stack);
-}
-
-/* Make something that looks like a TREE_LIST, but
- do it on the type_obstack_entries obstack. */
-static tree
-my_tree_cons (purpose, value, chain)
- tree purpose, value, chain;
-{
- tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_list));
- ++my_tree_node_counter;
- TREE_TYPE (p) = NULL_TREE;
- ((HOST_WIDE_INT *)p)[3] = 0;
- TREE_SET_CODE (p, TREE_LIST);
- TREE_PURPOSE (p) = purpose;
- TREE_VALUE (p) = value;
- TREE_CHAIN (p) = chain;
- return p;
-}
-
-static tree
-my_build_string (str)
- char *str;
-{
- tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_string));
- ++my_tree_node_counter;
- TREE_TYPE (p) = 0;
- ((int *)p)[3] = 0;
- TREE_SET_CODE (p, STRING_CST);
- TREE_STRING_POINTER (p) = str;
- TREE_STRING_LENGTH (p) = strlen (str);
- return p;
-}
-
-/* Memoizing machinery to make searches for multiple inheritance
- reasonably efficient. */
-#define MEMOIZE_HASHSIZE 8
-typedef struct memoized_entry
-{
- struct memoized_entry *chain;
- int uid;
- tree data_members[MEMOIZE_HASHSIZE];
- tree function_members[MEMOIZE_HASHSIZE];
-} *ME;
-
-#define MEMOIZED_CHAIN(ENTRY) (((ME)ENTRY)->chain)
-#define MEMOIZED_UID(ENTRY) (((ME)ENTRY)->uid)
-#define MEMOIZED_FIELDS(ENTRY,INDEX) (((ME)ENTRY)->data_members[INDEX])
-#define MEMOIZED_FNFIELDS(ENTRY,INDEX) (((ME)ENTRY)->function_members[INDEX])
-/* The following is probably a lousy hash function. */
-#define MEMOIZED_HASH_FN(NODE) (((long)(NODE)>>4)&(MEMOIZE_HASHSIZE - 1))
-
-static struct memoized_entry *
-my_new_memoized_entry (chain)
- struct memoized_entry *chain;
-{
- struct memoized_entry *p =
- (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
- sizeof (struct memoized_entry));
- bzero (p, sizeof (struct memoized_entry));
- MEMOIZED_CHAIN (p) = chain;
- MEMOIZED_UID (p) = ++my_memoized_entry_counter;
- return p;
-}
-
-/* Make an entry in the memoized table for type TYPE
- that the entry for NAME is FIELD. */
-
-tree
-make_memoized_table_entry (type, name, function_p)
- tree type, name;
- int function_p;
-{
- int index = MEMOIZED_HASH_FN (name);
- tree entry, *prev_entry;
-
- memoized_adds[function_p] += 1;
- if (CLASSTYPE_MTABLE_ENTRY (type) == 0)
- {
- obstack_ptr_grow (&type_obstack, type);
- obstack_blank (&type_obstack, sizeof (struct memoized_entry *));
- CLASSTYPE_MTABLE_ENTRY (type) = (char *)my_new_memoized_entry ((struct memoized_entry *)0);
- type_stack->len++;
- if (type_stack->len * 2 >= type_stack->base.limit)
- my_friendly_abort (88);
- }
- if (function_p)
- prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
- else
- prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
-
- entry = my_tree_cons (name, NULL_TREE, *prev_entry);
- *prev_entry = entry;
-
- /* Don't know the error message to give yet. */
- TREE_TYPE (entry) = error_mark_node;
-
- return entry;
-}
-
-/* When a new function or class context is entered, we build
- a table of types which have been searched for members.
- The table is an array (obstack) of types. When a type is
- entered into the obstack, its CLASSTYPE_MTABLE_ENTRY
- field is set to point to a new record, of type struct memoized_entry.
-
- A non-NULL TREE_TYPE of the entry contains a visibility error message.
-
- The slots for the data members are arrays of tree nodes.
- These tree nodes are lists, with the TREE_PURPOSE
- of this list the known member name, and the TREE_VALUE
- as the FIELD_DECL for the member.
-
- For member functions, the TREE_PURPOSE is again the
- name of the member functions for that class,
- and the TREE_VALUE of the list is a pairs
- whose TREE_PURPOSE is a member functions of this name,
- and whose TREE_VALUE is a list of known argument lists this
- member function has been called with. The TREE_TYPE of the pair,
- if non-NULL, is an error message to print. */
-
-/* Tell search machinery that we are entering a new context, and
- to update tables appropriately.
-
- TYPE is the type of the context we are entering, which can
- be NULL_TREE if we are not in a class's scope.
-
- USE_OLD, if nonzero tries to use previous context. */
-void
-push_memoized_context (type, use_old)
- tree type;
- int use_old;
-{
- int len;
- tree *tem;
-
- if (prev_type_stack)
- {
- if (use_old && prev_type_memoized == type)
- {
-#ifdef GATHER_STATISTICS
- n_contexts_saved++;
-#endif
- type_stack = prev_type_stack;
- prev_type_stack = 0;
-
- tem = &type_stack->base.first[0];
- len = type_stack->len;
- while (len--)
- CLASSTYPE_MTABLE_ENTRY (tem[len*2]) = (char *)tem[len*2+1];
- return;
- }
- /* Otherwise, need to pop old stack here. */
- type_stack = pop_type_level (prev_type_stack);
- prev_type_memoized = 0;
- prev_type_stack = 0;
- }
-
- type_stack = push_type_level ((struct stack_level *)type_stack,
- &type_obstack);
- type_stack->type = type;
-}
-
-/* Tell search machinery that we have left a context.
- We do not currently save these contexts for later use.
- If we wanted to, we could not use pop_search_level, since
- poping that level allows the data we have collected to
- be clobbered; a stack of obstacks would be needed. */
-void
-pop_memoized_context (use_old)
- int use_old;
-{
- int len;
- tree *tem = &type_stack->base.first[0];
-
- if (! flag_save_memoized_contexts)
- use_old = 0;
- else if (use_old)
- {
- len = type_stack->len;
- while (len--)
- tem[len*2+1] = (tree)CLASSTYPE_MTABLE_ENTRY (tem[len*2]);
-
- prev_type_stack = type_stack;
- prev_type_memoized = type_stack->type;
- }
-
- if (flag_memoize_lookups)
- {
- len = type_stack->len;
- while (len--)
- CLASSTYPE_MTABLE_ENTRY (tem[len*2])
- = (char *)MEMOIZED_CHAIN (CLASSTYPE_MTABLE_ENTRY (tem[len*2]));
- }
- if (! use_old)
- type_stack = pop_type_level (type_stack);
- else
- type_stack = (struct type_level *)type_stack->base.prev;
-}
-
-/* This can go away when the new searching strategy as a little mileage on it. */
-#define NEW_SEARCH 1
-#if NEW_SEARCH
-/* This is the newer recursive depth first one, the old one follows. */
-static tree
-get_binfo_recursive (binfo, is_private, parent, rval, rval_private_ptr, xtype,
- friends, protect)
- tree binfo, parent, rval, xtype, friends;
- int *rval_private_ptr, protect, is_private;
-{
- tree binfos;
- int i, n_baselinks;
-
- if (BINFO_TYPE (binfo) == parent)
- {
- if (rval == NULL_TREE)
- {
- rval = binfo;
- *rval_private_ptr = is_private;
- }
- else
- {
- /* I believe it is the case that this error is only an error
- when used by someone that wants error messages printed.
- Routines that call this one, that don't set protect want
- the first one found, even if there are more. */
- if (protect)
- {
- /* Found two or more possible return values. */
- error_with_aggr_type (parent, "type `%s' is ambiguous base class for type `%s'",
- TYPE_NAME_STRING (xtype));
- rval = error_mark_node;
- }
- }
- return rval;
- }
-
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Process base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (BINFO_MARKED (base_binfo) == 0)
- {
- int via_private = is_private || !TREE_VIA_PUBLIC (base_binfo);
-
- SET_BINFO_MARKED (base_binfo);
-
- if (via_private == 0)
- ;
- else if (protect == 0)
- via_private = 0;
- else if (protect == 1 && BINFO_TYPE (binfo) == current_class_type)
- /* The immediate base class of the class we are in
- does let its public members through. */
- via_private = 0;
-#ifndef NOJJG
- else if (protect
- && friends != NULL_TREE
- && BINFO_TYPE (binfo) == xtype
- && value_member (current_class_type, friends))
- /* Friend types of the most derived type have access
- to its baseclass pointers. */
- via_private = 0;
-#endif
-
- rval = get_binfo_recursive (base_binfo, via_private, parent, rval,
- rval_private_ptr, xtype, friends,
- protect);
- if (rval == error_mark_node)
- return rval;
- }
- }
-
- return rval;
-}
-
-/* Check whether the type given in BINFO is derived from PARENT. If
- it isn't, return 0. If it is, but the derivation is MI-ambiguous
- AND protect != 0, emit an error message and return error_mark_node.
-
- Otherwise, if TYPE is derived from PARENT, return the actual base
- information, unless a one of the protection violations below
- occurs, in which case emit an error message and return error_mark_node.
-
- The below should be worded better. It may not be exactly what the code
- does, but there should be a lose correlation. If you understand the code
- well, please try and make the comments below more readable.
-
- If PROTECT is 1, then check if access to a public field of PARENT
- would be private.
-
- If PROTECT is 2, then check if the given type is derived from
- PARENT via private visibility rules.
-
- If PROTECT is 3, then immediately private baseclass is ok,
- but deeper than that, check if private. */
-tree
-get_binfo (parent, binfo, protect)
- register tree parent, binfo;
- int protect;
-{
- tree xtype, type;
- tree otype;
- int head = 0, tail = 0;
- int is_private = 0;
- tree rval = NULL_TREE;
- int rval_private = 0;
- tree friends;
-
-#ifdef GATHER_STATISTICS
- n_calls_get_base_type++;
-#endif
-
- if (TREE_CODE (parent) == TREE_VEC)
- parent = BINFO_TYPE (parent);
- /* unions cannot participate in inheritance relationships */
- else if (TREE_CODE (parent) == UNION_TYPE)
- return NULL_TREE;
- else if (TREE_CODE (parent) != RECORD_TYPE)
- my_friendly_abort (89);
-
- parent = TYPE_MAIN_VARIANT (parent);
-
- if (TREE_CODE (binfo) == TREE_VEC)
- type = BINFO_TYPE (binfo);
- else if (TREE_CODE (binfo) == RECORD_TYPE)
- {
- type = binfo;
- binfo = TYPE_BINFO (type);
- }
- else my_friendly_abort (90);
- xtype = type;
- friends = current_class_type ? CLASSTYPE_FRIEND_CLASSES (type) : NULL_TREE;
-
- rval = get_binfo_recursive (binfo, is_private, parent, rval, &rval_private,
- xtype, friends, protect);
-
- dfs_walk (binfo, dfs_unmark, markedp);
-
- if (rval && protect && rval_private)
- {
- if (protect == 3)
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (xtype));
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (parent == BINFO_TYPE (base_binfo))
- /* It's ok, since it's immediate. */
- return rval;
- }
- }
- error_with_aggr_type (xtype, "type `%s' is derived from private `%s'",
- TYPE_NAME_STRING (parent));
- return error_mark_node;
- }
-
- return rval;
-}
-#else
-/* Check whether the type given in BINFO is derived from PARENT. If
- it isn't, return 0. If it is, but the derivation is MI-ambiguous
- AND protect != 0, emit an error message and return error_mark_node.
-
- Otherwise, if TYPE is derived from PARENT, return the actual base
- information, unless a one of the protection violations below
- occurs, in which case emit an error message and return error_mark_node.
-
- The below should be worded better. It may not be exactly what the code
- does, but there should be a lose correlation. If you understand the code
- well, please try and make the comments below more readable.
-
- If PROTECT is 1, then check if access to a public field of PARENT
- would be private.
-
- If PROTECT is 2, then check if the given type is derived from
- PARENT via private visibility rules.
-
- If PROTECT is 3, then immediately private baseclass is ok,
- but deeper than that, check if private. */
-tree
-get_binfo (parent, binfo, protect)
- register tree parent, binfo;
- int protect;
-{
- tree xtype, type;
- tree otype;
- int head = 0, tail = 0;
- int is_private = 0;
- tree rval = NULL_TREE;
- int rval_private = 0;
- tree friends;
-
-#ifdef GATHER_STATISTICS
- n_calls_get_base_type++;
-#endif
-
- if (TREE_CODE (parent) == TREE_VEC)
- parent = BINFO_TYPE (parent);
- /* unions cannot participate in inheritance relationships */
- else if (TREE_CODE (parent) == UNION_TYPE)
- return NULL_TREE;
- else if (TREE_CODE (parent) != RECORD_TYPE)
- my_friendly_abort (89);
-
- parent = TYPE_MAIN_VARIANT (parent);
- search_stack = push_search_level (search_stack, &search_obstack);
-
- if (TREE_CODE (binfo) == TREE_VEC)
- type = BINFO_TYPE (binfo);
- else if (TREE_CODE (binfo) == RECORD_TYPE)
- {
- type = binfo;
- binfo = TYPE_BINFO (type);
- }
- else my_friendly_abort (90);
- xtype = type;
- friends = current_class_type ? CLASSTYPE_FRIEND_CLASSES (type) : NULL_TREE;
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (BINFO_MARKED (base_binfo) == 0)
- {
- int via_private = is_private || !TREE_VIA_PUBLIC (base_binfo);
-
- SET_BINFO_MARKED (base_binfo);
-
- if (via_private == 0)
- ;
- else if (protect == 0)
- via_private = 0;
- else if (protect == 1 && BINFO_TYPE (binfo) == current_class_type)
- /* The immediate base class of the class we are in
- does let its public members through. */
- via_private = 0;
-#ifndef NOJJG
- else if (protect
- && friends != NULL_TREE
- && BINFO_TYPE (binfo) == xtype
- && value_member (current_class_type, friends))
- /* Friend types of the most derived type have access
- to its baseclass pointers. */
- via_private = 0;
-#endif
-
- otype = type;
- obstack_ptr_grow (&search_obstack, base_binfo);
- obstack_ptr_grow (&search_obstack, (void *) via_private);
- tail += 2;
- if (tail >= search_stack->limit)
- my_friendly_abort (91);
- }
-#if 0
- /* This code cannot possibly be right. Ambiguities can only be
- checked by traversing the whole tree, and seeing if it pops
- up twice. */
- else if (protect && ! TREE_VIA_VIRTUAL (base_binfo))
- {
- error_with_aggr_type (parent, "type `%s' is ambiguous base class for type `%s'",
- TYPE_NAME_STRING (xtype));
- error ("(base class for types `%s' and `%s')",
- TYPE_NAME_STRING (BINFO_TYPE (binfo)),
- TYPE_NAME_STRING (otype));
- rval = error_mark_node;
- goto cleanup;
- }
-#endif
- }
-
- dont_queue:
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- binfo = search_stack->first[head++];
- is_private = (int) search_stack->first[head++];
- if (BINFO_TYPE (binfo) == parent)
- {
- if (rval == 0)
- {
- rval = binfo;
- rval_private = is_private;
- }
- else
- /* I believe it is the case that this error is only an error when
- used by someone that wants error messages printed. Routines that
- call this one, that don't set protect want the first one found,
- even if there are more. */
- if (protect)
- {
- /* Found two or more possible return values. */
- error_with_aggr_type (parent, "type `%s' is ambiguous base class for type `%s'",
- TYPE_NAME_STRING (xtype));
- rval = error_mark_node;
- goto cleanup;
- }
- goto dont_queue;
- }
- }
-
- cleanup:
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
-
- while (tp < search_tail)
- {
- CLEAR_BINFO_MARKED (*tp);
- tp += 2;
- }
- }
- search_stack = pop_search_level (search_stack);
-
- if (rval == error_mark_node)
- return error_mark_node;
-
- if (rval && protect && rval_private)
- {
- if (protect == 3)
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (xtype));
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (parent == BINFO_TYPE (base_binfo))
- /* It's ok, since it's immediate. */
- return rval;
- }
- }
- error_with_aggr_type (xtype, "type `%s' is derived from private `%s'",
- TYPE_NAME_STRING (parent));
- return error_mark_node;
- }
-
- return rval;
-}
-#endif
-
-#if NEW_SEARCH
-/* This is the newer depth first get_base_distance, the older one follows. */
-static
-get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
- rval_private_ptr, new_binfo_ptr, parent, path_ptr,
- protect, via_virtual_ptr, via_virtual)
- tree binfo, basetype_path, *new_binfo_ptr, parent, *path_ptr;
- int *rval_private_ptr, depth, is_private, rval, protect, *via_virtual_ptr,
- via_virtual;
-{
- tree binfos;
- int i, n_baselinks;
-
- if (BINFO_TYPE (binfo) == parent)
- {
- if (rval == -1)
- {
- rval = depth;
- *rval_private_ptr = is_private;
- *new_binfo_ptr = binfo;
- *via_virtual_ptr = via_virtual;
- }
- else
- {
- int same_object = tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
- BINFO_OFFSET (binfo));
-
- if (*via_virtual_ptr && via_virtual==0)
- {
- *rval_private_ptr = is_private;
- *new_binfo_ptr = binfo;
- *via_virtual_ptr = via_virtual;
- }
- else if (same_object)
- {
- /* Note, this should probably succeed to find, and
- override the old one if the old one was private and
- this one isn't. */
- return rval;
- }
-
- rval = -2;
- }
- return rval;
- }
-
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- depth += 1;
-
- /* Process base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (BINFO_MARKED (base_binfo) == 0)
- {
- int via_private = is_private || !TREE_VIA_PUBLIC (base_binfo);
- int was;
-
- /* When searching for a non-virtual, we cannot mark
- virtually found binfos. */
- if (!via_virtual)
- SET_BINFO_MARKED (base_binfo);
-
- if (via_private == 0)
- ;
- else if (protect == 0)
- via_private = 0;
-
-#define WATCH_VALUES(rval, via_private) (rval == -1 ? 3 : via_private)
-
- was = WATCH_VALUES (rval, *via_virtual_ptr);
- rval = get_base_distance_recursive (base_binfo, depth, via_private,
- binfo, rval, rval_private_ptr,
- new_binfo_ptr, parent, path_ptr,
- protect, via_virtual_ptr,
- TREE_VIA_VIRTUAL (base_binfo)|via_virtual);
- /* watch for updates, only update, if path is good. */
- if (path_ptr && WATCH_VALUES (rval, *via_virtual_ptr) != was)
- BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
- if (rval == -2 && *via_virtual_ptr == 0)
- return rval;
-
-#undef WATCH_VALUES
-
- }
- }
-
- return rval;
-}
-
-/* Return the number of levels between type PARENT and the type given
- in BINFO, following the leftmost path to PARENT not found along a
- virtual path, if there are no real PARENTs (all come from virtual
- base classes), then follow the leftmost path to PARENT.
-
- Return -1 if TYPE is not derived from PARENT.
- Return -2 if PARENT is an ambiguous base class of TYPE.
- Return -3 if PARENT is private to TYPE, and protect is non-zero.
-
- If PATH_PTR is non-NULL, then also build the list of types
- from PARENT to TYPE, with TREE_VIA_VIRUAL and TREE_VIA_PUBLIC
- set.
-
- It is unclear whether or not the path should be built if -2 and/or
- -3 is returned. Maybe, maybe not. I suspect that there is code
- that relies upon it being built, such as prepare_fresh_vtable.
- (mrs)
-
- Also, it would appear that we only sometimes want -2. The question is
- under what exact conditions do we want to see -2, and when do we not
- want to see -2. (mrs)
-
- It is also unlikely that this thing finds all ambiguties, as I
- don't trust any deviation from the method used in get_binfo. It
- would be nice to use that method here, as it is simple and straight
- forward. The code here and in recursive_bounded_basetype_p is not.
- For now, I shall include an extra call to find ambiguities. (mrs)
- */
-
-int
-get_base_distance (parent, binfo, protect, path_ptr)
- register tree parent, binfo;
- int protect;
- tree *path_ptr;
-{
- int head, tail;
- int is_private = 0;
- int rval = -1;
- int depth = 0;
- int rval_private = 0;
- tree type, basetype_path;
- tree friends;
- int use_leftmost;
- tree new_binfo;
- int via_virtual;
-
- if (TYPE_READONLY (parent) || TYPE_VOLATILE (parent))
- parent = TYPE_MAIN_VARIANT (parent);
- use_leftmost = (parent == TYPE_MAIN_VARIANT (parent));
-
- if (TREE_CODE (binfo) == TREE_VEC)
- type = BINFO_TYPE (binfo);
- else if (TREE_CODE (binfo) == RECORD_TYPE)
- {
- type = binfo;
- binfo = TYPE_BINFO (type);
- }
- else my_friendly_abort (92);
-
- friends = current_class_type ? CLASSTYPE_FRIEND_CLASSES (type) : NULL_TREE;
-
- if (path_ptr)
- {
- basetype_path = TYPE_BINFO (type);
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
- }
-
- if (TYPE_MAIN_VARIANT (parent) == type)
- {
- /* If the distance is 0, then we don't really need
- a path pointer, but we shouldn't let garbage go back. */
- if (path_ptr)
- *path_ptr = basetype_path;
- return 0;
- }
-
- rval = get_base_distance_recursive (binfo, 0, 0, NULL_TREE, rval,
- &rval_private, &new_binfo, parent,
- path_ptr, protect, &via_virtual, 0);
-
- if (path_ptr)
- BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
-
- basetype_path = binfo;
-
- dfs_walk (binfo, dfs_unmark, markedp);
-
- binfo = new_binfo;
-
- /* Visibilities don't count if we found an ambiguous basetype. */
- if (rval == -2)
- rval_private = 0;
-
- if (rval && protect && rval_private)
- return -3;
-
- if (path_ptr)
- *path_ptr = binfo;
- return rval;
-}
-#else
-/* Recursively search for a path from PARENT to BINFO.
- If RVAL is > 0 and we succeed, update the BINFO_INHERITANCE_CHAIN
- pointers.
- If we find a distinct basetype that's not the one from BINFO,
- return -2;
- If we don't find any path, return 0.
-
- If we encounter a virtual basetype on the path, return RVAL
- and don't change any pointers after that point. */
-static int
-recursive_bounded_basetype_p (parent, binfo, rval, update_chain)
- tree parent, binfo;
- int rval;
- int update_chain;
-{
- tree binfos;
-
- if (BINFO_TYPE (parent) == BINFO_TYPE (binfo))
- {
- if (tree_int_cst_equal (BINFO_OFFSET (parent), BINFO_OFFSET (binfo)))
- return rval;
- return -2;
- }
-
- if (TREE_VIA_VIRTUAL (binfo))
- update_chain = 0;
-
- if (binfos = BINFO_BASETYPES (binfo))
- {
- int i, nval;
- for (i = 0; i < TREE_VEC_LENGTH (binfos); i++)
- {
- nval = recursive_bounded_basetype_p (parent, TREE_VEC_ELT (binfos, i),
- rval, update_chain);
- if (nval < 0)
- return nval;
- if (nval > 0 && update_chain)
- BINFO_INHERITANCE_CHAIN (TREE_VEC_ELT (binfos, i)) = binfo;
- }
- return rval;
- }
- return 0;
-}
-
-/* -------------------------------------------------- */
-/* These two routines are ONLY here to check for ambiguities for
- get_base_distance, as it probably cannot check by itself for
- all ambiguities. When get_base_distance is sure to check for all,
- these routines can go. (mrs) */
-
-static tree
-get_binfo2_recursive (binfo, parent, type)
- register tree binfo, parent;
- tree type;
-{
- tree rval = NULL_TREE;
- tree nrval;
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- if (BINFO_TYPE (binfo) == parent)
- {
- return binfo;
- }
-
- /* Process base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (BINFO_MARKED (base_binfo) == 0)
- {
- SET_BINFO_MARKED (base_binfo);
-
- nrval = get_binfo2_recursive (base_binfo, parent, type);
-
- if (nrval == error_mark_node)
- return nrval;
- if (nrval)
- if (rval == 0)
- {
- rval = nrval;
- }
- else
- return error_mark_node;
- }
- }
- return rval;
-}
-
-static tree
-get_binfo2 (parent, binfo)
- register tree parent, binfo;
-{
- tree type;
- tree rval = NULL_TREE;
-
- if (TREE_CODE (parent) == TREE_VEC)
- parent = BINFO_TYPE (parent);
- /* unions cannot participate in inheritance relationships */
- else if (TREE_CODE (parent) == UNION_TYPE)
- return 0;
- else if (TREE_CODE (parent) != RECORD_TYPE)
- my_friendly_abort (89);
-
- parent = TYPE_MAIN_VARIANT (parent);
-
- if (TREE_CODE (binfo) == TREE_VEC)
- type = BINFO_TYPE (binfo);
- else if (TREE_CODE (binfo) == RECORD_TYPE)
- {
- type = binfo;
- binfo = TYPE_BINFO (type);
- }
- else my_friendly_abort (90);
-
- rval = get_binfo2_recursive (binfo, parent, type);
-
- dfs_walk (binfo, dfs_unmark, markedp);
-
- return rval;
-}
-
-/* -------------------------------------------------- */
-
-/* Return the number of levels between type PARENT and the type given
- in BINFO, following the leftmost path to PARENT. If PARENT is its
- own main type variant, then if PARENT appears in different places
- from TYPE's point of view, the leftmost PARENT will be the one
- chosen.
-
- Return -1 if TYPE is not derived from PARENT.
- Return -2 if PARENT is an ambiguous base class of TYPE.
- Return -3 if PARENT is private to TYPE, and protect is non-zero.
-
- If PATH_PTR is non-NULL, then also build the list of types
- from PARENT to TYPE, with TREE_VIA_VIRUAL and TREE_VIA_PUBLIC
- set.
-
- It is unclear whether or not the path should be built if -2 and/or
- -3 is returned. Maybe, maybe not. I suspect that there is code
- that relies upon it being built, such as prepare_fresh_vtable.
- (mrs)
-
- Also, it would appear that we only sometimes want -2. The question is
- under what exact conditions do we want to see -2, and when do we not
- want to see -2. (mrs)
-
- It is also unlikely that this thing finds all ambiguties, as I
- don't trust any deviation from the method used in get_binfo. It
- would be nice to use that method here, as it is simple and straight
- forward. The code here and in recursive_bounded_basetype_p is not.
- For now, I shall include an extra call to find ambiguities. (mrs)
- */
-
-int
-get_base_distance (parent, binfo, protect, path_ptr)
- register tree parent, binfo;
- int protect;
- tree *path_ptr;
-{
- int head, tail;
- int is_private = 0;
- int rval = -1;
- int depth = 0;
- int rval_private = 0;
- tree type, basetype_path;
- tree friends;
- int use_leftmost;
-
- if (TYPE_READONLY (parent) || TYPE_VOLATILE (parent))
- parent = TYPE_MAIN_VARIANT (parent);
- use_leftmost = (parent == TYPE_MAIN_VARIANT (parent));
-
- if (TREE_CODE (binfo) == TREE_VEC)
- type = BINFO_TYPE (binfo);
- else if (TREE_CODE (binfo) == RECORD_TYPE)
- {
- type = binfo;
- binfo = TYPE_BINFO (type);
- }
- else if (TREE_CODE (binfo) == UNION_TYPE)
- {
- /* UNION_TYPEs do not participate in inheritance relationships. */
- return -1;
- }
- else my_friendly_abort (92);
-
- friends = current_class_type ? CLASSTYPE_FRIEND_CLASSES (type) : NULL_TREE;
-
- if (path_ptr)
- {
- basetype_path = TYPE_BINFO (type);
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
- }
-
- if (TYPE_MAIN_VARIANT (parent) == type)
- {
- /* If the distance is 0, then we don't really need
- a path pointer, but we shouldn't let garbage go back. */
- if (path_ptr)
- *path_ptr = basetype_path;
- return 0;
- }
-
- search_stack = push_search_level (search_stack, &search_obstack);
-
- /* Keep space for TYPE. */
- obstack_ptr_grow (&search_obstack, binfo);
- obstack_ptr_grow (&search_obstack, NULL_PTR);
- obstack_ptr_grow (&search_obstack, NULL_PTR);
- if (path_ptr)
- {
- obstack_ptr_grow (&search_obstack, NULL_PTR);
- head = 4;
- }
- else head = 3;
- tail = head;
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (BINFO_MARKED (base_binfo) == 0)
- {
- int via_private = is_private || !TREE_VIA_PUBLIC (base_binfo);
-
- SET_BINFO_MARKED (base_binfo);
-
- if (via_private == 0)
- ;
- else if (protect == 0)
- via_private = 0;
-
- obstack_ptr_grow (&search_obstack, base_binfo);
- obstack_ptr_grow (&search_obstack, (HOST_WIDE_INT) depth);
- obstack_ptr_grow (&search_obstack, (HOST_WIDE_INT) via_private);
- tail += 3;
- if (path_ptr)
- {
- obstack_ptr_grow (&search_obstack, basetype_path);
- tail += 1;
- }
- if (tail >= search_stack->limit)
- my_friendly_abort (93);
- }
-#if 0
- /* This code cannot possibly be right. Ambiguities can only be
- checked by traversing the whole tree, and seeing if it pops
- up twice. */
- else if (! TREE_VIA_VIRTUAL (base_binfo))
- {
- rval = -2;
- goto done;
- }
-#endif
- }
-
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- binfo = search_stack->first[head++];
- depth = (int) search_stack->first[head++] + 1;
- is_private = (int) search_stack->first[head++];
- if (path_ptr)
- {
- basetype_path = search_stack->first[head++];
- BINFO_INHERITANCE_CHAIN (binfo) = basetype_path;
- basetype_path = binfo;
- }
- if (BINFO_TYPE (binfo) == parent)
- {
- /* It is wrong to set this and break, the proper thing to do
- would be to set it only if it has not been set before,
- and if is has been set, an ambiguity exists, and just
- continue searching the tree for more of them as is done
- in get_binfo. But until the code below can cope, this
- can't be done. Also, it is not clear what should happen if
- use_leftmost is set. */
- rval = depth;
- rval_private = is_private;
- break;
- }
- }
-#if 0
- /* Unneeded now, as we know the above code in the #if 0 is wrong. */
- done:
-#endif
- {
- int increment = path_ptr ? 4 : 3;
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
-
- /* We can skip the first entry, since it wasn't marked. */
- tp += increment;
-
- basetype_path = binfo;
- while (tp < search_tail)
- {
- CLEAR_BINFO_MARKED (*tp);
- tp += increment;
- }
-
- /* Now, guarantee that we are following the leftmost path in the
- chain. Algorithm: the search stack holds tuples in BFS order.
- The last tuple on the search stack contains the tentative binfo
- for the basetype we are looking for. We know that starting
- with FIRST, each tuple with only a single basetype must be on
- the leftmost path. Each time we come to a split, we select
- the tuple for the leftmost basetype that can reach the ultimate
- basetype. */
-
- if (use_leftmost
- && rval > 0
- && (! BINFO_OFFSET_ZEROP (binfo) || TREE_VIA_VIRTUAL (binfo)))
- {
- tree tp_binfos;
-
- /* Farm out the tuples with a single basetype. */
- for (tp = search_stack->first; tp < search_tail; tp += increment)
- {
- tp_binfos = BINFO_BASETYPES (*tp);
- if (tp_binfos && TREE_VEC_LENGTH (tp_binfos) > 1)
- break;
- }
-
- if (tp < search_tail)
- {
- /* Pick the best path. */
- tree base_binfo;
- int i;
- int nrval = rval;
- for (i = 0; i < TREE_VEC_LENGTH (tp_binfos); i++)
- {
- base_binfo = TREE_VEC_ELT (tp_binfos, i);
- if (tp+((i+1)*increment) < search_tail)
- my_friendly_assert (base_binfo == tp[(i+1)*increment], 295);
- if (nrval = recursive_bounded_basetype_p (binfo, base_binfo, rval, 1))
- break;
- }
- rval = nrval;
- if (rval > 0)
- BINFO_INHERITANCE_CHAIN (base_binfo) = *tp;
- }
-
- /* Because I don't trust recursive_bounded_basetype_p to find
- all ambiguities, I will just make sure here. When it is
- sure that all ambiguities are found, the two routines and
- this call can be removed. Not toally sure this should be
- here, but I think it should. (mrs) */
-
- if (get_binfo2 (parent, type) == error_mark_node && rval != -2)
- {
-#if 1
- /* This warning is here because the code over in
- prepare_fresh_vtable relies on partial completion
- offered by recursive_bounded_basetype_p I think, but
- that behavior is not documented. It needs to be. I
- don't think prepare_fresh_vtable is the only routine
- that relies upon path_ptr being set to something in a
- particular way when this routine returns -2. (mrs) */
- /* See PR 428 for a test case that can tickle this. */
- warning ("internal consistency check failed, please report, recovering.");
- rval = -2;
-#endif
- }
-
- /* Visibilities don't count if we found an ambiguous basetype. */
- if (rval == -2)
- rval_private = 0;
- }
- }
- search_stack = pop_search_level (search_stack);
-
- if (rval && protect && rval_private)
- return -3;
-
- if (path_ptr)
- *path_ptr = binfo;
- return rval;
-}
-#endif
-
-/* Search for a member with name NAME in a multiple inheritance lattice
- specified by TYPE. If it does not exist, return NULL_TREE.
- If the member is ambiguously referenced, return `error_mark_node'.
- Otherwise, return the FIELD_DECL. */
-
-/* Do a 1-level search for NAME as a member of TYPE. The caller
- must figure out whether it has a visible path to this field.
- (Since it is only one level, this is reasonable.) */
-static tree
-lookup_field_1 (type, name)
- tree type, name;
-{
- register tree field = TYPE_FIELDS (type);
-
-#ifdef GATHER_STATISTICS
- n_calls_lookup_field_1++;
-#endif
- while (field)
- {
-#ifdef GATHER_STATISTICS
- n_fields_searched++;
-#endif
- if (DECL_NAME (field) == NULL_TREE
- && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
- {
- tree temp = lookup_field_1 (TREE_TYPE (field), name);
- if (temp)
- return temp;
- }
- if (DECL_NAME (field) == name)
- {
- if ((TREE_CODE(field) == VAR_DECL || TREE_CODE(field) == CONST_DECL)
- && DECL_ASSEMBLER_NAME (field) != NULL)
- GNU_xref_ref(current_function_decl,
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (field)));
- return field;
- }
- field = TREE_CHAIN (field);
- }
- /* Not found. */
- if (name == _vptr_name)
- {
- /* Give the user what s/he thinks s/he wants. */
- if (TYPE_VIRTUAL_P (type))
- return CLASSTYPE_VFIELD (type);
- }
- return NULL_TREE;
-}
-
-/* Compute the visibility of FIELD. This is done by computing
- the visibility available to each type in BASETYPES (which comes
- as a list of [via_public/basetype] in reverse order, namely base
- class before derived class). The first one which defines a
- visibility defines the visibility for the field. Otherwise, the
- visibility of the field is that which occurs normally.
-
- Uses global variables CURRENT_CLASS_TYPE and
- CURRENT_FUNCTION_DECL to use friend relationships
- if necessary.
-
- This will be static when lookup_fnfield comes into this file. */
-
-#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), visibility_public
-#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), visibility_protected
-#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), visibility_private
-
-enum visibility_type
-compute_visibility (basetype_path, field)
- tree basetype_path, field;
-{
- enum visibility_type visibility = visibility_public;
- tree types;
- tree context = DECL_CLASS_CONTEXT (field);
-
- /* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
- slot set to the union type rather than the record type containing
- the anonymous union. In this case, DECL_FIELD_CONTEXT is correct. */
- if (context && TREE_CODE (context) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
- context = DECL_FIELD_CONTEXT (field);
-
- /* Virtual function tables are never private.
- But we should know that we are looking for this,
- and not even try to hide it. */
- if (DECL_NAME (field) && VFIELD_NAME_P (DECL_NAME (field)) == 1)
- return visibility_public;
-
- /* Member function manipulating its own members. */
- if (current_class_type == context
- || (context && current_class_type == TYPE_MAIN_VARIANT (context)))
- PUBLIC_RETURN;
-
- /* Make these special cases fast. */
- if (BINFO_TYPE (basetype_path) == current_class_type)
- {
- if (DECL_PUBLIC (field))
- return visibility_public;
- if (DECL_PROTECTED (field))
- return visibility_protected;
- if (DECL_PRIVATE (field))
- return visibility_private;
- }
-
- /* Member found immediately within object. */
- if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE)
- {
- /* At object's top level, public members are public. */
- if (TREE_PROTECTED (field) == 0 && TREE_PRIVATE (field) == 0)
- PUBLIC_RETURN;
-
- /* Friend function manipulating members it gets (for being a friend). */
- if (is_friend (context, current_function_decl))
- PUBLIC_RETURN;
-
- /* Inner than that, without special visibility,
-
- protected members are ok if type of object is current_class_type
- is derived therefrom. This means that if the type of the object
- is a base type for our current class type, we cannot access
- protected members.
-
- private members are not ok. */
- if (current_class_type && DECL_VISIBILITY (field) == NULL_TREE)
- {
- if (TREE_PRIVATE (field))
- PRIVATE_RETURN;
-
- if (TREE_PROTECTED (field))
- {
- if (context == current_class_type
- || UNIQUELY_DERIVED_FROM_P (context, current_class_type))
- PUBLIC_RETURN;
- else
- PROTECTED_RETURN;
- }
- else my_friendly_abort (94);
- }
- }
- /* Friend function manipulating members it gets (for being a friend). */
- if (is_friend (context, current_function_decl))
- PUBLIC_RETURN;
-
- /* must reverse more than one element */
- basetype_path = reverse_path (basetype_path);
- types = basetype_path;
-
- while (types)
- {
- tree member;
- tree binfo = types;
- tree type = BINFO_TYPE (binfo);
-
- member = purpose_member (type, DECL_VISIBILITY (field));
- if (member)
- {
- visibility = (enum visibility_type)TREE_VALUE (member);
- if (visibility == visibility_public
- || is_friend (type, current_function_decl)
- || (visibility == visibility_protected
- && current_class_type
- && UNIQUELY_DERIVED_FROM_P (context, current_class_type)))
- visibility = visibility_public;
- goto ret;
- }
-
- /* Friends inherit the visibility of the class they inherit from. */
- if (is_friend (type, current_function_decl))
- {
- if (type == context)
- {
- visibility = visibility_public;
- goto ret;
- }
- if (TREE_PROTECTED (field))
- {
- visibility = visibility_public;
- goto ret;
- }
-#if 0
- /* This short-cut is too short. */
- if (visibility == visibility_public)
- goto ret;
-#endif
- /* else, may be a friend of a deeper base class */
- }
-
- if (type == context)
- break;
-
- types = BINFO_INHERITANCE_CHAIN (types);
- /* If the next type was not VIA_PUBLIC, then fields of all
- remaining class past that one are private. */
- if (types)
- {
- if (TREE_VIA_PROTECTED (types))
- visibility = visibility_protected;
- else if (! TREE_VIA_PUBLIC (types))
- visibility = visibility_private;
- }
- }
-
- /* No special visibilities apply. Use normal rules.
- No assignment needed for BASETYPEs here from the nreverse.
- This is because we use it only for information about the
- path to the base. The code earlier dealt with what
- happens when we are at the base level. */
-
- if (visibility == visibility_public)
- {
- basetype_path = reverse_path (basetype_path);
- if (TREE_PRIVATE (field))
- PRIVATE_RETURN;
- if (TREE_PROTECTED (field))
- {
- /* Used to check if the current class type was derived from
- the type that contains the field. This is wrong for
- multiple inheritance because is gives one class reference
- to protected members via another classes protected path.
- I.e., if A; B1 : A; B2 : A; Then B1 and B2 can access
- their own members which are protected in A, but not
- those same members in one another. */
- if (current_class_type
- && UNIQUELY_DERIVED_FROM_P (context, current_class_type))
- PUBLIC_RETURN;
- PROTECTED_RETURN;
- }
- PUBLIC_RETURN;
- }
-
- if (visibility == visibility_protected)
- {
- /* reverse_path? */
- if (TREE_PRIVATE (field))
- PRIVATE_RETURN;
- /* We want to make sure that all non-private members in
- the current class (as derived) are accessible. */
- if (current_class_type
- && UNIQUELY_DERIVED_FROM_P (context, current_class_type))
- PUBLIC_RETURN;
- PROTECTED_RETURN;
- }
-
- if (visibility == visibility_private
- && current_class_type != NULL_TREE)
- {
- if (TREE_PRIVATE (field))
- {
- reverse_path (basetype_path);
- PRIVATE_RETURN;
- }
-
- /* See if the field isn't protected. */
- if (TREE_PROTECTED (field))
- {
- tree test = basetype_path;
- while (test)
- {
- if (BINFO_TYPE (test) == current_class_type)
- break;
- test = BINFO_INHERITANCE_CHAIN (test);
- }
- reverse_path (basetype_path);
- if (test)
- PUBLIC_RETURN;
- PROTECTED_RETURN;
- }
-
- /* See if the field isn't a public member of
- a private base class. */
-
- visibility = visibility_public;
- types = BINFO_INHERITANCE_CHAIN (basetype_path);
- while (types)
- {
- if (! TREE_VIA_PUBLIC (types))
- {
- if (visibility == visibility_private)
- {
- visibility = visibility_private;
- goto ret;
- }
- visibility = visibility_private;
- }
- if (BINFO_TYPE (types) == context)
- {
- visibility = visibility_public;
- goto ret;
- }
- types = BINFO_INHERITANCE_CHAIN (types);
- }
- my_friendly_abort (95);
- }
-
- ret:
- reverse_path (basetype_path);
-
- if (visibility == visibility_public)
- DECL_PUBLIC (field) = 1;
- else if (visibility == visibility_protected)
- DECL_PROTECTED (field) = 1;
- else if (visibility == visibility_private)
- DECL_PRIVATE (field) = 1;
- else my_friendly_abort (96);
- return visibility;
-}
-
-/* Routine to see if the sub-object denoted by the binfo PARENT can be
- found as a base class and sub-object of the object denoted by
- BINFO. This routine relies upon binfos not being shared, except
- for binfos for virtual bases. */
-static int
-is_subobject_of_p (parent, binfo)
- tree parent, binfo;
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- if (parent == binfo)
- return 1;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TREE_VIA_VIRTUAL (base_binfo))
- base_binfo = TYPE_BINFO (BINFO_TYPE (base_binfo));
- if (is_subobject_of_p (parent, base_binfo))
- return 1;
- }
- return 0;
-}
-
-/* See if a one FIELD_DECL hides another. This routine is meant to
- correspond to ANSI working paper Sept 17, 1992 10p4. The two
- binfos given are the binfos corresponding to the particular places
- the FIELD_DECLs are found. This routine relies upon binfos not
- being shared, except for virtual bases. */
-static int
-hides (hider_binfo, hidee_binfo)
- tree hider_binfo, hidee_binfo;
-{
- /* hider hides hidee, if hider has hidee as a base class and
- the instance of hidee is a sub-object of hider. The first
- part is always true is the second part is true.
-
- When hider and hidee are the same (two ways to get to the exact
- same member) we consider either one as hiding the other. */
- return is_subobject_of_p (hidee_binfo, hider_binfo);
-}
-
-/* Very similar to lookup_fnfields_1 but it ensures that at least one
- function was declared inside the class given by TYPE. It really should
- only return functions that match the given TYPE. */
-static int
-lookup_fnfields_here (type, name)
- tree type, name;
-{
- int index = lookup_fnfields_1 (type, name);
- tree fndecls;
-
- if (index <= 0)
- return index;
- fndecls = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
- while (fndecls)
- {
- if (TYPE_MAIN_VARIANT (DECL_CLASS_CONTEXT (fndecls))
- == TYPE_MAIN_VARIANT (type))
- return index;
- fndecls = TREE_CHAIN (fndecls);
- }
- return -1;
-}
-
-/* Look for a field named NAME in an inheritance lattice dominated by
- XBASETYPE. PROTECT is zero if we can avoid computing visibility
- information, otherwise it is 1. WANT_TYPE is 1 when we should only
- return TYPE_DECLs, if no TYPE_DECL can be found return NULL_TREE.
-
- It was not clear what should happen if WANT_TYPE is set, and an
- ambiguity is found. At least one use (lookup_name) to not see
- the error. */
-tree
-lookup_field (xbasetype, name, protect, want_type)
- register tree xbasetype, name;
- int protect, want_type;
-{
- int head = 0, tail = 0;
- tree rval, rval_binfo = NULL_TREE, rval_binfo_h;
- tree type, basetype_chain, basetype_path;
- enum visibility_type this_v = visibility_default;
- tree entry, binfo, binfo_h;
- enum visibility_type own_visibility = visibility_default;
- int vbase_name_p = VBASE_NAME_P (name);
-
- /* rval_binfo is the binfo associated with the found member, note,
- this can be set with useful information, even when rval is not
- set, because it must deal with ALL members, not just non-function
- members. It is used for ambiguity checking and the hidden
- checks. Whereas rval is only set if a proper (not hidden)
- non-function member is found. */
-
- /* rval_binfo_h and binfo_h are binfo values used when we perform the
- hiding checks, as virtual base classes may not be shared. The strategy
- is we always go into the the binfo hierarchy owned by TYPE_BINFO of
- virtual base classes, as we cross virtual base class lines. This way
- we know that binfo of a virtual base class will always == itself when
- found along any line. (mrs) */
-
- /* Things for memoization. */
- char *errstr = 0;
-
- /* Set this to nonzero if we don't know how to compute
- accurate error messages for visibility. */
- int index = MEMOIZED_HASH_FN (name);
-
- if (TREE_CODE (xbasetype) == TREE_VEC)
- basetype_path = xbasetype, type = BINFO_TYPE (xbasetype);
- else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
- basetype_path = TYPE_BINFO (xbasetype), type = xbasetype;
- else my_friendly_abort (97);
-
- if (CLASSTYPE_MTABLE_ENTRY (type))
- {
- tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
-
- while (tem && TREE_PURPOSE (tem) != name)
- {
- memoized_fields_searched[0]++;
- tem = TREE_CHAIN (tem);
- }
- if (tem)
- {
- if (protect && TREE_TYPE (tem))
- {
- error (TREE_STRING_POINTER (TREE_TYPE (tem)),
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (DECL_FIELD_CONTEXT (TREE_VALUE (tem))));
- return error_mark_node;
- }
- if (TREE_VALUE (tem) == NULL_TREE)
- memoized_fast_rejects[0] += 1;
- else
- memoized_fast_finds[0] += 1;
- return TREE_VALUE (tem);
- }
- }
-
-#ifdef GATHER_STATISTICS
- n_calls_lookup_field++;
-#endif
- if (protect && flag_memoize_lookups && ! global_bindings_p ())
- entry = make_memoized_table_entry (type, name, 0);
- else
- entry = 0;
-
- rval = lookup_field_1 (type, name);
- if (rval || lookup_fnfields_here (type, name)>=0)
- {
- rval_binfo = basetype_path;
- rval_binfo_h = rval_binfo;
- }
-
- if (rval && TREE_CODE (rval) != TYPE_DECL && want_type)
- rval = NULL_TREE;
-
- if (rval)
- {
- if (protect)
- {
- if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval))
- this_v = compute_visibility (basetype_path, rval);
- if (TREE_CODE (rval) == CONST_DECL)
- {
- if (this_v == visibility_private)
- errstr = "enum `%s' is a private value of class `%s'";
- else if (this_v == visibility_protected)
- errstr = "enum `%s' is a protected value of class `%s'";
- }
- else
- {
- if (this_v == visibility_private)
- errstr = "member `%s' is a private member of class `%s'";
- else if (this_v == visibility_protected)
- errstr = "member `%s' is a protected member of class `%s'";
- }
- }
-
- if (entry)
- {
- if (errstr)
- {
- /* This depends on behavior of lookup_field_1! */
- tree error_string = my_build_string (errstr);
- TREE_TYPE (entry) = error_string;
- }
- else
- {
- /* Let entry know there is no problem with this access. */
- TREE_TYPE (entry) = NULL_TREE;
- }
- TREE_VALUE (entry) = rval;
- }
-
- if (errstr && protect)
- {
- error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
- return error_mark_node;
- }
- return rval;
- }
-
- basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
- TREE_VIA_PUBLIC (basetype_chain) = 1;
-
- /* The ambiguity check relies upon breadth first searching. */
-
- search_stack = push_search_level (search_stack, &search_obstack);
- BINFO_VIA_PUBLIC (basetype_path) = 1;
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
- binfo = basetype_path;
- binfo_h = binfo;
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- tree nval;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (BINFO_FIELDS_MARKED (base_binfo) == 0)
- {
- tree btypes;
-
- SET_BINFO_FIELDS_MARKED (base_binfo);
- btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
- TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
- TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
- TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
- if (TREE_VIA_VIRTUAL (base_binfo))
- btypes = tree_cons (NULL_TREE,
- TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
- btypes);
- else
- btypes = tree_cons (NULL_TREE,
- TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
- btypes);
- obstack_ptr_grow (&search_obstack, btypes);
- tail += 1;
- if (tail >= search_stack->limit)
- my_friendly_abort (98);
- }
- }
-
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- basetype_chain = search_stack->first[head++];
- binfo_h = TREE_VALUE (basetype_chain);
- basetype_chain = TREE_CHAIN (basetype_chain);
- basetype_path = TREE_VALUE (basetype_chain);
- if (TREE_CHAIN (basetype_chain))
- BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
- else
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
-
- binfo = basetype_path;
- type = BINFO_TYPE (binfo);
-
- /* See if we can find NAME in TYPE. If RVAL is nonzero,
- and we do find NAME in TYPE, verify that such a second
- sighting is in fact legal. */
-
- nval = lookup_field_1 (type, name);
-
- if (nval || lookup_fnfields_here (type, name)>=0)
- {
- if (rval_binfo && hides (rval_binfo_h, binfo_h))
- {
- /* This is ok, the member found is in rval_binfo, not
- here (binfo). */
- }
- else if (rval_binfo==NULL_TREE || hides (binfo_h, rval_binfo_h))
- {
- /* This is ok, the member found is here (binfo), not in
- rval_binfo. */
- if (nval)
- {
- rval = nval;
- if (entry || protect)
- this_v = compute_visibility (basetype_path, rval);
- /* These may look ambiguous, but they really are not. */
- if (vbase_name_p)
- break;
- }
- else
- {
- /* Undo finding it before, as something else hides it. */
- rval = NULL_TREE;
- }
- rval_binfo = binfo;
- rval_binfo_h = binfo_h;
- }
- else
- {
- /* This is ambiguous. */
- errstr = "request for member `%s' is ambiguous";
- protect = 2;
- break;
- }
- }
- }
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
-
- if (entry)
- TREE_VALUE (entry) = rval;
-
- if (want_type && (rval == NULL_TREE || TREE_CODE (rval) != TYPE_DECL))
- {
- rval = NULL_TREE;
- errstr = 0;
- }
-
- /* If this FIELD_DECL defines its own visibility, deal with that. */
- if (rval && errstr == 0
- && ((protect&1) || entry)
- && DECL_LANG_SPECIFIC (rval)
- && DECL_VISIBILITY (rval))
- {
- while (tp < search_tail)
- {
- /* If is possible for one of the derived types on the
- path to have defined special visibility for this
- field. Look for such declarations and report an
- error if a conflict is found. */
- enum visibility_type new_v;
-
- if (this_v != visibility_default)
- new_v = compute_visibility (TREE_VALUE (TREE_CHAIN (*tp)), rval);
- if (this_v != visibility_default && new_v != this_v)
- {
- errstr = "conflicting visibilities to member `%s'";
- this_v = visibility_default;
- }
- own_visibility = new_v;
- CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
- tp += 1;
- }
- }
- else
- {
- while (tp < search_tail)
- {
- CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
- tp += 1;
- }
- }
- }
- search_stack = pop_search_level (search_stack);
-
- if (errstr == 0)
- {
- if (own_visibility == visibility_private)
- errstr = "member `%s' declared private";
- else if (own_visibility == visibility_protected)
- errstr = "member `%s' declared protected";
- else if (this_v == visibility_private)
- errstr = TREE_PRIVATE (rval)
- ? "member `%s' is private"
- : "member `%s' is from private base class";
- else if (this_v == visibility_protected)
- errstr = TREE_PROTECTED (rval)
- ? "member `%s' is protected"
- : "member `%s' is from protected base class";
- }
-
- if (entry)
- {
- if (errstr)
- {
- tree error_string = my_build_string (errstr);
- /* Save error message with entry. */
- TREE_TYPE (entry) = error_string;
- }
- else
- {
- /* Mark entry as having no error string. */
- TREE_TYPE (entry) = NULL_TREE;
- }
- }
-
- if (errstr && protect)
- {
- error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
- rval = error_mark_node;
- }
- return rval;
-}
-
-/* Try to find NAME inside a nested class. */
-tree
-lookup_nested_field (name, complain)
- tree name;
- int complain;
-{
- register tree t;
-
- tree id = NULL_TREE;
- if (TREE_CHAIN (current_class_type))
- {
- /* Climb our way up the nested ladder, seeing if we're trying to
- modify a field in an enclosing class. If so, we should only
- be able to modify if it's static. */
- for (t = TREE_CHAIN (current_class_type);
- t && DECL_CONTEXT (t);
- t = TREE_CHAIN (DECL_CONTEXT (t)))
- {
- if (TREE_CODE (DECL_CONTEXT (t)) != RECORD_TYPE)
- break;
-
- /* N.B.: lookup_field will do the visibility checking for us */
- id = lookup_field (DECL_CONTEXT (t), name, complain, 0);
- if (id == error_mark_node)
- {
- id = NULL_TREE;
- continue;
- }
-
- if (id != NULL_TREE)
- {
- if (TREE_CODE (id) == FIELD_DECL
- && ! TREE_STATIC (id)
- && TREE_TYPE (id) != error_mark_node)
- {
- if (complain)
- {
- /* At parse time, we don't want to give this error, since
- we won't have enough state to make this kind of
- decision properly. But there are times (e.g., with
- enums in nested classes) when we do need to call
- this fn at parse time. So, in those cases, we pass
- complain as a 0 and just return a NULL_TREE. */
- error ("assignment to non-static member `%s' of enclosing class `%s'",
- lang_printable_name (id),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER
- (DECL_CONTEXT (t))));
- /* Mark this for do_identifier(). It would otherwise
- claim that the variable was undeclared. */
- TREE_TYPE (id) = error_mark_node;
- }
- else
- {
- id = NULL_TREE;
- continue;
- }
- }
- break;
- }
- }
- }
-
- return id;
-}
-
-/* TYPE is a class type. Return the index of the fields within
- the method vector with name NAME, or -1 is no such field exists. */
-static int
-lookup_fnfields_1 (type, name)
- tree type, name;
-{
- register tree method_vec = CLASSTYPE_METHOD_VEC (type);
-
- if (method_vec != 0)
- {
- register tree *methods = &TREE_VEC_ELT (method_vec, 0);
- register tree *end = TREE_VEC_END (method_vec);
-
-#ifdef GATHER_STATISTICS
- n_calls_lookup_fnfields_1++;
-#endif
- if (*methods && name == constructor_name (type))
- return 0;
-
- while (++methods != end)
- {
-#ifdef GATHER_STATISTICS
- n_outer_fields_searched++;
-#endif
- if (DECL_NAME (*methods) == name)
- break;
- }
- if (methods != end)
- return methods - &TREE_VEC_ELT (method_vec, 0);
- }
-
- return -1;
-}
-
-/* Starting from BASETYPE, return a TREE_BASELINK-like object
- which gives the following information (in a list):
-
- TREE_TYPE: list of basetypes needed to get to...
- TREE_VALUE: list of all functions in of given type
- which have name NAME.
-
- No visibility information is computed by this function,
- other then to adorn the list of basetypes with
- TREE_VIA_PUBLIC.
-
- If there are two ways to find a name (two members), if COMPLAIN is
- non-zero, then error_mark_node is returned, and an error message is
- printed, otherwise, just an error_mark_node is returned.
-
- As a special case, is COMPLAIN is -1, we don't complain, and we
- don't return error_mark_node, but rather the complete list of
- virtuals. This is used by get_virtuals_named_this. */
-tree
-lookup_fnfields (basetype_path, name, complain)
- tree basetype_path, name;
- int complain;
-{
- int head = 0, tail = 0;
- tree type, rval, rval_binfo = NULL_TREE, rvals = NULL_TREE, rval_binfo_h;
- tree entry, binfo, basetype_chain, binfo_h;
- int find_all = 0;
-
- /* rval_binfo is the binfo associated with the found member, note,
- this can be set with useful information, even when rval is not
- set, because it must deal with ALL members, not just function
- members. It is used for ambiguity checking and the hidden
- checks. Whereas rval is only set if a proper (not hidden)
- function member is found. */
-
- /* rval_binfo_h and binfo_h are binfo values used when we perform the
- hiding checks, as virtual base classes may not be shared. The strategy
- is we always go into the the binfo hierarchy owned by TYPE_BINFO of
- virtual base classes, as we cross virtual base class lines. This way
- we know that binfo of a virtual base class will always == itself when
- found along any line. (mrs) */
-
- /* For now, don't try this. */
- int protect = complain;
-
- /* Things for memoization. */
- char *errstr = 0;
-
- /* Set this to nonzero if we don't know how to compute
- accurate error messages for visibility. */
- int index = MEMOIZED_HASH_FN (name);
-
- if (complain == -1)
- {
- find_all = 1;
- protect = complain = 0;
- }
-
- binfo = basetype_path;
- binfo_h = binfo;
- type = BINFO_TYPE (basetype_path);
-
- /* The memoization code is in need of maintenance. */
- if (!find_all && CLASSTYPE_MTABLE_ENTRY (type))
- {
- tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
-
- while (tem && TREE_PURPOSE (tem) != name)
- {
- memoized_fields_searched[1]++;
- tem = TREE_CHAIN (tem);
- }
- if (tem)
- {
- if (protect && TREE_TYPE (tem))
- {
- error (TREE_STRING_POINTER (TREE_TYPE (tem)),
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (DECL_CLASS_CONTEXT (TREE_VALUE (TREE_VALUE (tem)))));
- return error_mark_node;
- }
- if (TREE_VALUE (tem) == NULL_TREE)
- {
- memoized_fast_rejects[1] += 1;
- return NULL_TREE;
- }
- else
- {
- /* Want to return this, but we must make sure
- that visibility information is consistent. */
- tree baselink = TREE_VALUE (tem);
- tree memoized_basetypes = TREE_PURPOSE (baselink);
- tree these_basetypes = basetype_path;
- while (memoized_basetypes && these_basetypes)
- {
- memoized_fields_searched[1]++;
- if (TREE_VALUE (memoized_basetypes) != these_basetypes)
- break;
- memoized_basetypes = TREE_CHAIN (memoized_basetypes);
- these_basetypes = BINFO_INHERITANCE_CHAIN (these_basetypes);
- }
- /* The following statement is true only when both are NULL. */
- if (memoized_basetypes == these_basetypes)
- {
- memoized_fast_finds[1] += 1;
- return TREE_VALUE (tem);
- }
- /* else, we must re-find this field by hand. */
- baselink = tree_cons (basetype_path, TREE_VALUE (baselink), TREE_CHAIN (baselink));
- return baselink;
- }
- }
- }
-
-#ifdef GATHER_STATISTICS
- n_calls_lookup_fnfields++;
-#endif
- if (protect && flag_memoize_lookups && ! global_bindings_p ())
- entry = make_memoized_table_entry (type, name, 1);
- else
- entry = 0;
-
- index = lookup_fnfields_here (type, name);
- if (index >= 0 || lookup_field_1 (type, name))
- {
- rval_binfo = basetype_path;
- rval_binfo_h = rval_binfo;
- }
-
- if (index >= 0)
- {
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
- rvals = my_tree_cons (basetype_path, rval, rvals);
- if (BINFO_BASETYPES (binfo) && CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
-
- if (entry)
- {
- TREE_VALUE (entry) = rvals;
- TREE_TYPE (entry) = NULL_TREE;
- }
-
- if (errstr && protect)
- {
- error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
- return error_mark_node;
- }
- return rvals;
- }
- rval = NULL_TREE;
-
- basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
- TREE_VIA_PUBLIC (basetype_chain) = 1;
-
- /* The ambiguity check relies upon breadth first searching. */
-
- search_stack = push_search_level (search_stack, &search_obstack);
- BINFO_VIA_PUBLIC (basetype_path) = 1;
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
- binfo = basetype_path;
- binfo_h = binfo;
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int index;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (BINFO_FIELDS_MARKED (base_binfo) == 0)
- {
- tree btypes;
-
- SET_BINFO_FIELDS_MARKED (base_binfo);
- btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
- TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
- TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
- TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
- if (TREE_VIA_VIRTUAL (base_binfo))
- btypes = tree_cons (NULL_TREE,
- TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
- btypes);
- else
- btypes = tree_cons (NULL_TREE,
- TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
- btypes);
- obstack_ptr_grow (&search_obstack, btypes);
- tail += 1;
- if (tail >= search_stack->limit)
- my_friendly_abort (99);
- }
- }
-
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- basetype_chain = search_stack->first[head++];
- binfo_h = TREE_VALUE (basetype_chain);
- basetype_chain = TREE_CHAIN (basetype_chain);
- basetype_path = TREE_VALUE (basetype_chain);
- if (TREE_CHAIN (basetype_chain))
- BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
- else
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
-
- binfo = basetype_path;
- type = BINFO_TYPE (binfo);
-
- /* See if we can find NAME in TYPE. If RVAL is nonzero,
- and we do find NAME in TYPE, verify that such a second
- sighting is in fact legal. */
-
- index = lookup_fnfields_here (type, name);
-
- if (index >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all))
- {
- if (rval_binfo && !find_all && hides (rval_binfo_h, binfo_h))
- {
- /* This is ok, the member found is in rval_binfo, not
- here (binfo). */
- }
- else if (rval_binfo==NULL_TREE || find_all || hides (binfo_h, rval_binfo_h))
- {
- /* This is ok, the member found is here (binfo), not in
- rval_binfo. */
- if (index >= 0)
- {
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
- /* Note, rvals can only be previously set if find_all is
- true. */
- rvals = my_tree_cons (basetype_path, rval, rvals);
- if (TYPE_BINFO_BASETYPES (type)
- && CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
- }
- else
- {
- /* Undo finding it before, as something else hides it. */
- rval = NULL_TREE;
- rvals = NULL_TREE;
- }
- rval_binfo = binfo;
- rval_binfo_h = binfo_h;
- }
- else
- {
- /* This is ambiguous. */
- errstr = "request for member `%s' is ambiguous";
- rvals = error_mark_node;
- break;
- }
- }
- }
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
-
- while (tp < search_tail)
- {
- CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
- tp += 1;
- }
- }
- search_stack = pop_search_level (search_stack);
-
- if (entry)
- {
- if (errstr)
- {
- tree error_string = my_build_string (errstr);
- /* Save error message with entry. */
- TREE_TYPE (entry) = error_string;
- }
- else
- {
- /* Mark entry as having no error string. */
- TREE_TYPE (entry) = NULL_TREE;
- TREE_VALUE (entry) = rvals;
- }
- }
-
- if (errstr && protect)
- {
- error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
- rvals = error_mark_node;
- }
-
- return rvals;
-}
-
-/* BREADTH-FIRST SEARCH ROUTINES. */
-
-/* Search a multiple inheritance hierarchy by breadth-first search.
-
- TYPE is an aggregate type, possibly in a multiple-inheritance hierarchy.
- TESTFN is a function, which, if true, means that our condition has been met,
- and its return value should be returned.
- QFN, if non-NULL, is a predicate dictating whether the type should
- even be queued. */
-
-HOST_WIDE_INT
-breadth_first_search (binfo, testfn, qfn)
- tree binfo;
- int (*testfn)();
- int (*qfn)();
-{
- int head = 0, tail = 0;
- int rval = 0;
-
- search_stack = push_search_level (search_stack, &search_obstack);
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int i;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (BINFO_MARKED (base_binfo) == 0
- && (qfn == 0 || (*qfn) (binfo, i)))
- {
- SET_BINFO_MARKED (base_binfo);
- obstack_ptr_grow (&search_obstack, binfo);
- obstack_ptr_grow (&search_obstack, (HOST_WIDE_INT) i);
- tail += 2;
- if (tail >= search_stack->limit)
- my_friendly_abort (100);
- }
- }
- /* Process head of queue, if one exists. */
- if (head >= tail)
- {
- rval = 0;
- break;
- }
-
- binfo = search_stack->first[head++];
- i = (int) search_stack->first[head++];
- if (rval = (*testfn) (binfo, i))
- break;
- binfo = BINFO_BASETYPE (binfo, i);
- }
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
- while (tp < search_tail)
- {
- tree binfo = *tp++;
- int i = (HOST_WIDE_INT)(*tp++);
- CLEAR_BINFO_MARKED (BINFO_BASETYPE (binfo, i));
- }
- }
-
- search_stack = pop_search_level (search_stack);
- return rval;
-}
-
-/* Functions to use in breadth first searches. */
-typedef tree (*pft)();
-typedef int (*pfi)();
-
-int tree_needs_constructor_p (binfo, i)
- tree binfo;
- int i;
-{
- tree basetype;
- my_friendly_assert (i != 0, 296);
- basetype = BINFO_TYPE (BINFO_BASETYPE (binfo, i));
- return TYPE_NEEDS_CONSTRUCTOR (basetype);
-}
-
-static tree declarator;
-
-static tree
-get_virtuals_named_this (binfo)
- tree binfo;
-{
- tree fields;
-
- fields = lookup_fnfields (binfo, declarator, -1);
- /* fields cannot be error_mark_node */
-
- if (fields == 0)
- return 0;
-
- /* Get to the function decls, and return the first virtual function
- with this name, if there is one. */
- while (fields)
- {
- tree fndecl;
-
- for (fndecl = TREE_VALUE (fields); fndecl; fndecl = DECL_CHAIN (fndecl))
- if (DECL_VINDEX (fndecl))
- return fields;
- fields = next_baselink (fields);
- }
- return NULL_TREE;
-}
-
-static tree get_virtual_destructor (binfo, i)
- tree binfo;
- int i;
-{
- tree type = BINFO_TYPE (binfo);
- if (i >= 0)
- type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
- if (TYPE_HAS_DESTRUCTOR (type)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0)))
- return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
- return 0;
-}
-
-int tree_has_any_destructor_p (binfo, i)
- tree binfo;
- int i;
-{
- tree type = BINFO_TYPE (binfo);
- if (i >= 0)
- type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
- return TYPE_NEEDS_DESTRUCTOR (type);
-}
-
-/* Given a class type TYPE, and a function decl FNDECL,
- look for the first function the TYPE's hierarchy which
- FNDECL could match as a virtual function.
-
- DTORP is nonzero if we are looking for a destructor. Destructors
- need special treatment because they do not match by name. */
-tree
-get_first_matching_virtual (binfo, fndecl, dtorp)
- tree binfo, fndecl;
- int dtorp;
-{
- tree tmp = NULL_TREE;
-
- /* Breadth first search routines start searching basetypes
- of TYPE, so we must perform first ply of search here. */
- if (dtorp)
- {
- if (tree_has_any_destructor_p (binfo, -1))
- tmp = get_virtual_destructor (binfo, -1);
-
- if (tmp)
- {
- if (get_base_distance (DECL_CONTEXT (tmp),
- DECL_CONTEXT (fndecl), 0, 0) > 0)
- DECL_CONTEXT (fndecl) = DECL_CONTEXT (tmp);
- return tmp;
- }
-
- tmp = (tree) breadth_first_search (binfo,
- (pfi) get_virtual_destructor,
- tree_has_any_destructor_p);
- if (tmp)
- {
- if (get_base_distance (DECL_CONTEXT (tmp),
- DECL_CONTEXT (fndecl), 0, 0) > 0)
- DECL_CONTEXT (fndecl) = DECL_CONTEXT (tmp);
- }
- return tmp;
- }
- else
- {
- tree drettype, dtypes, btypes, instptr_type;
- tree basetype = DECL_CLASS_CONTEXT (fndecl);
- tree baselink, best = NULL_TREE;
- tree name = DECL_ASSEMBLER_NAME (fndecl);
-
- declarator = DECL_NAME (fndecl);
- if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
- return NULL_TREE;
-
- drettype = TREE_TYPE (TREE_TYPE (fndecl));
- dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- if (DECL_STATIC_FUNCTION_P (fndecl))
- instptr_type = NULL_TREE;
- else
- instptr_type = TREE_TYPE (TREE_VALUE (dtypes));
-
- for (baselink = get_virtuals_named_this (binfo);
- baselink; baselink = next_baselink (baselink))
- {
- for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp))
- {
- if (! DECL_VINDEX (tmp))
- continue;
-
- btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp));
- if (instptr_type == NULL_TREE)
- {
- if (compparms (TREE_CHAIN (btypes), dtypes, 3))
- /* Caller knows to give error in this case. */
- return tmp;
- return NULL_TREE;
- }
-
- if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (btypes)))
- == TYPE_READONLY (instptr_type))
- && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3))
- {
- if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE
- && ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
- {
- error_with_decl (fndecl, "conflicting return type specified for virtual function `%s'");
- SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
- }
- break;
- }
- }
- if (tmp)
- {
- /* If this is ambiguous, we will warn about it later. */
- if (best)
- {
- if (get_base_distance (DECL_CLASS_CONTEXT (best),
- DECL_CLASS_CONTEXT (tmp), 0, 0) > 0)
- best = tmp;
- }
- else
- best = tmp;
- }
- }
- if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE
- && best == NULL_TREE && warn_overloaded_virtual)
- {
- warning_with_decl (fndecl,
- "conflicting specification deriving virtual function `%s'");
- SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
- }
- if (best)
- {
- if (get_base_distance (DECL_CONTEXT (best),
- DECL_CONTEXT (fndecl), 0, 0) > 0)
- DECL_CONTEXT (fndecl) = DECL_CONTEXT (best);
- }
- return best;
- }
-}
-
-/* Return the list of virtual functions which are abstract in type TYPE.
- This information is cached, and so must be built on a
- non-temporary obstack. */
-tree
-get_abstract_virtuals (type)
- tree type;
-{
- /* For each layer of base class (i.e., the first base class, and each
- virtual base class from that one), modify the virtual function table
- of the derived class to contain the new virtual function.
- A class has as many vfields as it has virtual base classes (total). */
- tree vfields, vbases, base, tmp;
- tree vfield = CLASSTYPE_VFIELD (type);
- tree fcontext = vfield ? DECL_FCONTEXT (vfield) : NULL_TREE;
- tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
-
- for (vfields = CLASSTYPE_VFIELDS (type); vfields; vfields = TREE_CHAIN (vfields))
- {
- int normal;
-
- /* This code is most likely wrong, and probably only works for single
- inheritance or by accident. */
-
- /* Find the right base class for this derived class, call it BASE. */
- base = VF_BASETYPE_VALUE (vfields);
- if (base == type)
- continue;
-
- /* We call this case NORMAL iff this virtual function table
- pointer field has its storage reserved in this class.
- This is normally the case without virtual baseclasses
- or off-center multiple baseclasses. */
- normal = (base == fcontext
- && (VF_BINFO_VALUE (vfields) == NULL_TREE
- || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))));
-
- if (normal)
- tmp = TREE_CHAIN (TYPE_BINFO_VIRTUALS (type));
- else
- {
- /* n.b.: VF_BASETYPE_VALUE (vfields) is the first basetype
- that provides the virtual function table, whereas
- VF_DERIVED_VALUE (vfields) is an immediate base type of TYPE
- that dominates VF_BASETYPE_VALUE (vfields). The list of
- vfields we want lies between these two values. */
- tree binfo = get_binfo (VF_NORMAL_VALUE (vfields), type, 0);
- tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
- }
-
- /* Get around dossier entry if there is one. */
- if (flag_dossier)
- tmp = TREE_CHAIN (tmp);
-
- while (tmp)
- {
- tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp));
- tree base_fndecl = TREE_OPERAND (base_pfn, 0);
- if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
- abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
- tmp = TREE_CHAIN (tmp);
- }
- }
- for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
- {
- if (! BINFO_VIRTUALS (vbases))
- continue;
-
- tmp = TREE_CHAIN (BINFO_VIRTUALS (vbases));
- while (tmp)
- {
- tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp));
- tree base_fndecl = TREE_OPERAND (base_pfn, 0);
- if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
- abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
- tmp = TREE_CHAIN (tmp);
- }
- }
- return nreverse (abstract_virtuals);
-}
-
-/* For the type TYPE, return a list of member functions available from
- base classes with name NAME. The TREE_VALUE of the list is a chain of
- member functions with name NAME. The TREE_PURPOSE of the list is a
- basetype, or a list of base types (in reverse order) which were
- traversed to reach the chain of member functions. If we reach a base
- type which provides a member function of name NAME, and which has at
- most one base type itself, then we can terminate the search. */
-
-tree
-get_baselinks (type_as_binfo_list, type, name)
- tree type_as_binfo_list;
- tree type, name;
-{
- int head = 0, tail = 0, index;
- tree rval = 0, nval = 0;
- tree basetypes = type_as_binfo_list;
- tree binfo = TYPE_BINFO (type);
-
- search_stack = push_search_level (search_stack, &search_obstack);
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree btypes;
-
- btypes = hash_tree_cons (TREE_VIA_PUBLIC (base_binfo),
- TREE_VIA_VIRTUAL (base_binfo),
- TREE_VIA_PROTECTED (base_binfo),
- NULL_TREE, base_binfo,
- basetypes);
- obstack_ptr_grow (&search_obstack, btypes);
- search_stack->first = (tree *)obstack_base (&search_obstack);
- tail += 1;
- }
-
- dont_queue:
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- basetypes = search_stack->first[head++];
- binfo = TREE_VALUE (basetypes);
- type = BINFO_TYPE (binfo);
- index = lookup_fnfields_1 (type, name);
- if (index >= 0)
- {
- nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
- rval = hash_tree_cons (0, 0, 0, basetypes, nval, rval);
- if (TYPE_BINFO_BASETYPES (type) == 0)
- goto dont_queue;
- else if (TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) == 1)
- {
- if (CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
- goto dont_queue;
- }
- }
- nval = NULL_TREE;
- }
-
- search_stack = pop_search_level (search_stack);
- return rval;
-}
-
-tree
-next_baselink (baselink)
- tree baselink;
-{
- tree tmp = TREE_TYPE (baselink);
- baselink = TREE_CHAIN (baselink);
- while (tmp)
- {
- /* @@ does not yet add previous base types. */
- baselink = tree_cons (TREE_PURPOSE (tmp), TREE_VALUE (tmp),
- baselink);
- TREE_TYPE (baselink) = TREE_TYPE (tmp);
- tmp = TREE_CHAIN (tmp);
- }
- return baselink;
-}
-
-/* DEPTH-FIRST SEARCH ROUTINES. */
-
-/* Assign unique numbers to _CLASSTYPE members of the lattice
- specified by TYPE. The root nodes are marked first; the nodes
- are marked depth-fisrt, left-right. */
-
-static int cid;
-
-/* Matrix implementing a relation from CLASSTYPE X CLASSTYPE => INT.
- Relation yields 1 if C1 <= C2, 0 otherwise. */
-typedef char mi_boolean;
-static mi_boolean *mi_matrix;
-
-/* Type for which this matrix is defined. */
-static tree mi_type;
-
-/* Size of the matrix for indexing purposes. */
-static int mi_size;
-
-/* Return nonzero if class C2 derives from class C1. */
-#define BINFO_DERIVES_FROM(C1, C2) \
- ((mi_matrix+mi_size*(BINFO_CID (C1)-1))[BINFO_CID (C2)-1])
-#define TYPE_DERIVES_FROM(C1, C2) \
- ((mi_matrix+mi_size*(CLASSTYPE_CID (C1)-1))[CLASSTYPE_CID (C2)-1])
-#define BINFO_DERIVES_FROM_STAR(C) \
- (mi_matrix+(BINFO_CID (C)-1))
-
-/* This routine converts a pointer to be a pointer of an immediate
- base class. The normal convert_pointer_to routine would diagnose
- the conversion as ambiguous, under MI code that has the base class
- as an ambiguous base class. */
-static tree
-convert_pointer_to_single_level (to_type, expr)
- tree to_type, expr;
-{
- tree binfo_of_derived;
- tree last;
-
- binfo_of_derived = TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr)));
- last = get_binfo (to_type, TREE_TYPE (TREE_TYPE (expr)), 0);
- BINFO_INHERITANCE_CHAIN (last) = binfo_of_derived;
- BINFO_INHERITANCE_CHAIN (binfo_of_derived) = NULL_TREE;
- return build_vbase_path (PLUS_EXPR, TYPE_POINTER_TO (to_type), expr, last, 1);
-}
-
-/* The main function which implements depth first search.
-
- This routine has to remember the path it walked up, when
- dfs_init_vbase_pointers is the work function, as otherwise there
- would be no record. */
-static void
-dfs_walk (binfo, fn, qfn)
- tree binfo;
- void (*fn)();
- int (*qfn)();
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if ((*qfn)(base_binfo))
- {
-#define NEW_CONVERT 1
-#if NEW_CONVERT
- if (fn == dfs_init_vbase_pointers)
- {
- /* When traversing an arbitrary MI hierarchy, we need to keep
- a record of the path we took to get down to the final base
- type, as otherwise there would be no record of it, and just
- trying to blindly convert at the bottom would be ambiguous.
-
- The easiest way is to do the conversions one step at a time,
- as we know we want the immediate base class at each step.
-
- The only special trick to converting one step at a time,
- is that when we hit the last virtual base class, we must
- use the SLOT value for it, and not use the normal convert
- routine. We use the last virtual base class, as in our
- implementation, we have pointers to all virtual base
- classes in the base object. */
-
- tree saved_vbase_decl_ptr_intermediate
- = vbase_decl_ptr_intermediate;
-
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- /* No need for the conversion here, as we know it is the
- right type. */
- vbase_decl_ptr_intermediate =
- (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo));
- }
- else
- {
-#ifdef CHECK_convert_pointer_to_single_level
- /* This code here introduces a little software fault
- tolerance It should be that case that the second
- one always gets the same valid answer that the
- first one gives, if the first one gives a valid
- answer.
-
- If it doesn't, the second algorithm is at fault
- and needs to be fixed.
-
- The first one is known to be bad and produce
- error_mark_node when dealing with MI base
- classes. It is the only problem supposed to be
- fixed by the second. */
-#endif
- tree vdpi1, vdpi2;
-
-#ifdef CHECK_convert_pointer_to_single_level
- vdpi1 = convert_pointer_to (BINFO_TYPE (base_binfo),
- vbase_decl_ptr_intermediate);
-#endif
- vdpi2 = convert_pointer_to_single_level (BINFO_TYPE (base_binfo),
- vbase_decl_ptr_intermediate);
- vbase_decl_ptr_intermediate = vdpi2;
-#ifdef CHECK_convert_pointer_to_single_level
- if (vdpi1 == error_mark_node && vdpi2 != vdpi1)
- {
- extern int errorcount;
- errorcount -=2;
- warning ("internal: Don't worry, be happy, I can fix tangs man. (ignore above error)");
- }
- else if (simple_cst_equal (vdpi1, vdpi2) != 1) {
- if (simple_cst_equal (vdpi1, vdpi2) == 0)
- warning ("internal: convert_pointer_to_single_level: They are not the same, going with old algorithm");
- else
- warning ("internal: convert_pointer_to_single_level: They might not be the same, going with old algorithm");
- vbase_decl_ptr_intermediate = vdpi1;
- }
-#endif
- }
-
- dfs_walk (base_binfo, fn, qfn);
-
- vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
- } else
-#endif
- dfs_walk (base_binfo, fn, qfn);
- }
- }
-
- fn (binfo);
-}
-
-/* Predicate functions which serve for dfs_walk. */
-static int numberedp (binfo) tree binfo;
-{ return BINFO_CID (binfo); }
-static int unnumberedp (binfo) tree binfo;
-{ return BINFO_CID (binfo) == 0; }
-
-static int markedp (binfo) tree binfo;
-{ return BINFO_MARKED (binfo); }
-static int bfs_markedp (binfo, i) tree binfo; int i;
-{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int unmarkedp (binfo) tree binfo;
-{ return BINFO_MARKED (binfo) == 0; }
-static int bfs_unmarkedp (binfo, i) tree binfo; int i;
-{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int marked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo); }
-static int bfs_marked_vtable_pathp (binfo, i) tree binfo; int i;
-{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int unmarked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
-static int bfs_unmarked_vtable_pathp (binfo, i) tree binfo; int i;
-{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int marked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo); }
-static int bfs_marked_new_vtablep (binfo, i) tree binfo; int i;
-{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int unmarked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
-static int bfs_unmarked_new_vtablep (binfo, i) tree binfo; int i;
-{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-
-static int dfs_search_slot_nonempty_p (binfo) tree binfo;
-{ return CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) != 0; }
-
-static int dfs_debug_unmarkedp (binfo) tree binfo;
-{ return CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) == 0; }
-
-/* The worker functions for `dfs_walk'. These do not need to
- test anything (vis a vis marking) if they are paired with
- a predicate function (above). */
-
-/* Assign each type within the lattice a number which is unique
- in the lattice. The first number assigned is 1. */
-
-static void
-dfs_number (binfo)
- tree binfo;
-{
- BINFO_CID (binfo) = ++cid;
-}
-
-static void
-dfs_unnumber (binfo)
- tree binfo;
-{
- BINFO_CID (binfo) = 0;
-}
-
-static void
-dfs_mark (binfo) tree binfo;
-{ SET_BINFO_MARKED (binfo); }
-
-static void
-dfs_unmark (binfo) tree binfo;
-{ CLEAR_BINFO_MARKED (binfo); }
-
-static void
-dfs_mark_vtable_path (binfo) tree binfo;
-{ SET_BINFO_VTABLE_PATH_MARKED (binfo); }
-
-static void
-dfs_unmark_vtable_path (binfo) tree binfo;
-{ CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); }
-
-static void
-dfs_mark_new_vtable (binfo) tree binfo;
-{ SET_BINFO_NEW_VTABLE_MARKED (binfo); }
-
-static void
-dfs_unmark_new_vtable (binfo) tree binfo;
-{ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); }
-
-static void
-dfs_clear_search_slot (binfo) tree binfo;
-{ CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
-
-static void
-dfs_debug_mark (binfo)
- tree binfo;
-{
- tree t = BINFO_TYPE (binfo);
-
- /* Use heuristic that if there are virtual functions,
- ignore until we see a non-inline virtual function. */
- tree methods = CLASSTYPE_METHOD_VEC (t);
-
- CLASSTYPE_DEBUG_REQUESTED (t) = 1;
-
- /* If interface info is known, the value of (?@@?) is correct. */
- if (methods == 0
- || ! CLASSTYPE_INTERFACE_UNKNOWN (t)
- || (write_virtuals == 2 && TYPE_VIRTUAL_P (t)))
- return;
-
- /* If debug info is requested from this context for this type, supply it.
- If debug info is requested from another context for this type,
- see if some third context can supply it. */
- if (current_function_decl == NULL_TREE
- || DECL_CLASS_CONTEXT (current_function_decl) != t)
- {
- if (TREE_VEC_ELT (methods, 0))
- methods = TREE_VEC_ELT (methods, 0);
- else
- methods = TREE_VEC_ELT (methods, 1);
- while (methods)
- {
- if (DECL_VINDEX (methods)
- && DECL_SAVED_INSNS (methods) == 0
- && DECL_PENDING_INLINE_INFO (methods) == 0
- && DECL_ABSTRACT_VIRTUAL_P (methods) == 0)
- {
- /* Somebody, somewhere is going to have to define this
- virtual function. When they do, they will provide
- the debugging info. */
- return;
- }
- methods = TREE_CHAIN (methods);
- }
- }
- /* We cannot rely on some alien method to solve our problems,
- so we must write out the debug info ourselves. */
- DECL_IGNORED_P (TYPE_NAME (t)) = 0;
- if (! TREE_ASM_WRITTEN (TYPE_NAME (t)))
- rest_of_type_compilation (t, global_bindings_p ());
-}
-
-/* Attach to the type of the virtual base class, the pointer to the
- virtual base class, given the global pointer vbase_decl_ptr. */
-static void
-dfs_find_vbases (binfo)
- tree binfo;
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = n_baselinks-1; i >= 0; i--)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (TREE_VIA_VIRTUAL (base_binfo)
- && CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo)) == 0)
- {
- tree vbase = BINFO_TYPE (base_binfo);
- tree binfo = binfo_member (vbase, vbase_types);
-
- CLASSTYPE_SEARCH_SLOT (vbase)
- = (char *) build (PLUS_EXPR, TYPE_POINTER_TO (vbase),
- vbase_decl_ptr, BINFO_OFFSET (binfo));
- }
- }
- SET_BINFO_VTABLE_PATH_MARKED (binfo);
- SET_BINFO_NEW_VTABLE_MARKED (binfo);
-}
-
-static void
-dfs_init_vbase_pointers (binfo)
- tree binfo;
-{
- tree type = BINFO_TYPE (binfo);
- tree fields = TYPE_FIELDS (type);
- tree path, this_vbase_ptr;
- int distance;
-
- CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
-
- /* If there is a dossier, it is the first field, though perhaps from
- the base class. Otherwise, the first fields are virtual base class
- pointer fields. */
- if (CLASSTYPE_DOSSIER (type) && VFIELD_NAME_P (DECL_NAME (fields)))
- /* Get past vtable for the object. */
- fields = TREE_CHAIN (fields);
-
- if (fields == NULL_TREE
- || DECL_NAME (fields) == NULL_TREE
- || ! VBASE_NAME_P (DECL_NAME (fields)))
- return;
-
-#if NEW_CONVERT
- this_vbase_ptr = vbase_decl_ptr_intermediate;
-
- if (TYPE_POINTER_TO (type) != TREE_TYPE (this_vbase_ptr))
- my_friendly_abort (125);
-#endif
-
-#if NEW_CONVERT == 0
- distance = get_base_distance (type, TREE_TYPE (vbase_decl), 0, &path);
- if (distance == -2)
- {
- error ("inheritance lattice too complex below");
- }
- while (path)
- {
- if (TREE_VIA_VIRTUAL (path))
- break;
- distance -= 1;
- path = BINFO_INHERITANCE_CHAIN (path);
- }
-
- if (distance > 0)
- this_vbase_ptr = convert_pointer_to (type, (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (path)));
- else
- this_vbase_ptr = convert_pointer_to (type, vbase_decl_ptr);
-
- /* This happens when it is ambiguous. */
- if (this_vbase_ptr == error_mark_node)
- return;
-#endif
-
- while (fields && DECL_NAME (fields)
- && VBASE_NAME_P (DECL_NAME (fields)))
- {
- tree ref = build (COMPONENT_REF, TREE_TYPE (fields),
- build_indirect_ref (this_vbase_ptr, 0), fields);
- tree init = (tree)CLASSTYPE_SEARCH_SLOT (TREE_TYPE (TREE_TYPE (fields)));
- vbase_init_result = tree_cons (binfo_member (TREE_TYPE (TREE_TYPE (fields)),
- vbase_types),
- build_modify_expr (ref, NOP_EXPR, init),
- vbase_init_result);
- fields = TREE_CHAIN (fields);
- }
-}
-
-/* Sometimes this needs to clear both VTABLE_PATH and NEW_VTABLE. Other
- times, just NEW_VTABLE, but optimizer should make both with equal
- efficiency (though it does not currently). */
-static void
-dfs_clear_vbase_slots (binfo)
- tree binfo;
-{
- tree type = BINFO_TYPE (binfo);
- CLASSTYPE_SEARCH_SLOT (type) = 0;
- CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
-}
-
-tree
-init_vbase_pointers (type, decl_ptr)
- tree type;
- tree decl_ptr;
-{
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- {
- int old_flag = flag_this_is_variable;
- tree binfo = TYPE_BINFO (type);
- flag_this_is_variable = -2;
- vbase_types = CLASSTYPE_VBASECLASSES (type);
- vbase_decl_ptr = decl_ptr;
- vbase_decl = build_indirect_ref (decl_ptr, 0);
- vbase_decl_ptr_intermediate = vbase_decl_ptr;
- vbase_init_result = NULL_TREE;
- dfs_walk (binfo, dfs_find_vbases, unmarked_vtable_pathp);
- dfs_walk (binfo, dfs_init_vbase_pointers, marked_vtable_pathp);
- dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
- flag_this_is_variable = old_flag;
- return vbase_init_result;
- }
- return 0;
-}
-
-/* Build a COMPOUND_EXPR which when expanded will generate the code
- needed to initialize all the virtual function table slots of all
- the virtual baseclasses. FOR_TYPE is the type which determines the
- virtual baseclasses to use; TYPE is the type of the object to which
- the initialization applies. TRUE_EXP is the true object we are
- initializing, and DECL_PTR is the pointer to the sub-object we
- are initializing.
-
- CTOR_P is non-zero if the caller of this function is a top-level
- constructor. It is zero when called from a destructor. When
- non-zero, we can use computed offsets to store the vtables. When
- zero, we must store new vtables through virtual baseclass pointers. */
-
-tree
-build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr, ctor_p)
- tree main_binfo, binfo;
- tree true_exp, decl_ptr;
- int ctor_p;
-{
- tree for_type = BINFO_TYPE (main_binfo);
- tree type = BINFO_TYPE (binfo);
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- {
- int old_flag = flag_this_is_variable;
- tree vtable_init_result = NULL_TREE;
- tree vbases = CLASSTYPE_VBASECLASSES (type);
-
- vbase_types = CLASSTYPE_VBASECLASSES (for_type);
- vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
- vbase_decl = true_exp ? true_exp : build_indirect_ref (decl_ptr, 0);
-
- if (ctor_p)
- {
- /* This is an object of type IN_TYPE, */
- flag_this_is_variable = -2;
- dfs_walk (main_binfo, dfs_find_vbases, unmarked_new_vtablep);
- }
-
- /* Initialized with vtables of type TYPE. */
- while (vbases)
- {
- /* This time through, not every class's vtable
- is going to be initialized. That is, we only initialize
- the "last" vtable pointer. */
-
- if (CLASSTYPE_VSIZE (BINFO_TYPE (vbases)))
- {
- tree addr;
- tree vtbl = BINFO_VTABLE (vbases);
- tree init = build_unary_op (ADDR_EXPR, vtbl, 0);
- assemble_external (vtbl);
- TREE_USED (vtbl) = 1;
-
- if (ctor_p == 0)
- addr = convert_pointer_to (vbases, vbase_decl_ptr);
- else
- addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
-
- if (addr)
- {
- tree ref = build_vfield_ref (build_indirect_ref (addr, 0),
- BINFO_TYPE (vbases));
- init = convert_force (TREE_TYPE (ref), init);
- vtable_init_result = tree_cons (NULL_TREE, build_modify_expr (ref, NOP_EXPR, init),
- vtable_init_result);
- }
- }
- vbases = TREE_CHAIN (vbases);
- }
-
- dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
-
- flag_this_is_variable = old_flag;
- if (vtable_init_result)
- return build_compound_expr (vtable_init_result);
- }
- return error_mark_node;
-}
-
-void
-clear_search_slots (type)
- tree type;
-{
- dfs_walk (TYPE_BINFO (type),
- dfs_clear_search_slot, dfs_search_slot_nonempty_p);
-}
-
-static void
-dfs_get_vbase_types (binfo)
- tree binfo;
-{
- int i;
- tree binfos = BINFO_BASETYPES (binfo);
- tree type = BINFO_TYPE (binfo);
- tree these_vbase_types = CLASSTYPE_VBASECLASSES (type);
-
- if (these_vbase_types)
- {
- while (these_vbase_types)
- {
- tree this_type = BINFO_TYPE (these_vbase_types);
-
- /* We really need to start from a fresh copy of this
- virtual basetype! CLASSTYPE_MARKED2 is the shortcut
- for BINFO_VBASE_MARKED. */
- if (! CLASSTYPE_MARKED2 (this_type))
- {
- vbase_types = make_binfo (integer_zero_node,
- this_type,
- TYPE_BINFO_VTABLE (this_type),
- TYPE_BINFO_VIRTUALS (this_type),
- vbase_types);
- TREE_VIA_VIRTUAL (vbase_types) = 1;
- SET_CLASSTYPE_MARKED2 (this_type);
- }
- these_vbase_types = TREE_CHAIN (these_vbase_types);
- }
- }
- else for (i = binfos ? TREE_VEC_LENGTH (binfos)-1 : -1; i >= 0; i--)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TREE_VIA_VIRTUAL (base_binfo) && ! BINFO_VBASE_MARKED (base_binfo))
- {
- vbase_types = make_binfo (integer_zero_node, BINFO_TYPE (base_binfo),
- BINFO_VTABLE (base_binfo),
- BINFO_VIRTUALS (base_binfo), vbase_types);
- TREE_VIA_VIRTUAL (vbase_types) = 1;
- SET_BINFO_VBASE_MARKED (base_binfo);
- }
- }
- SET_BINFO_MARKED (binfo);
-}
-
-/* Some virtual baseclasses might be virtual baseclasses for
- other virtual baseclasses. We sort the virtual baseclasses
- topologically: in the list returned, the first virtual base
- classes have no virtual baseclasses themselves, and any entry
- on the list has no dependency on virtual base classes later in the
- list. */
-tree
-get_vbase_types (type)
- tree type;
-{
- tree ordered_vbase_types = NULL_TREE, prev, next;
- tree vbases;
-
- vbase_types = NULL_TREE;
- dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp);
- dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp);
-
- while (vbase_types)
- {
- /* Now sort these types. This is essentially a bubble merge. */
-
- /* Farm out virtual baseclasses which have no marked ancestors. */
- for (vbases = vbase_types, prev = NULL_TREE;
- vbases; vbases = next)
- {
- next = TREE_CHAIN (vbases);
- /* If VBASES does not have any vbases itself, or it's
- topologically safe, it goes into the sorted list. */
- if (! CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbases))
- || BINFO_VBASE_MARKED (vbases) == 0)
- {
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (vbases);
- else
- vbase_types = TREE_CHAIN (vbases);
- TREE_CHAIN (vbases) = NULL_TREE;
- ordered_vbase_types = chainon (ordered_vbase_types, vbases);
- CLEAR_BINFO_VBASE_MARKED (vbases);
- }
- else
- prev = vbases;
- }
-
- /* Now unmark types all of whose ancestors are now on the
- `ordered_vbase_types' list. */
- for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
- {
- /* If all our virtual baseclasses are unmarked, ok. */
- tree t = CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbases));
- while (t && (BINFO_VBASE_MARKED (t) == 0
- || ! CLASSTYPE_VBASECLASSES (BINFO_TYPE (t))))
- t = TREE_CHAIN (t);
- if (t == NULL_TREE)
- CLEAR_BINFO_VBASE_MARKED (vbases);
- }
- }
-
- return ordered_vbase_types;
-}
-
-static void
-dfs_record_inheritance (binfo)
- tree binfo;
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- mi_boolean *derived_row = BINFO_DERIVES_FROM_STAR (binfo);
-
- for (i = n_baselinks-1; i >= 0; i--)
- {
- int j;
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree baseclass = BINFO_TYPE (base_binfo);
- mi_boolean *base_row = BINFO_DERIVES_FROM_STAR (base_binfo);
-
- /* Don't search if there's nothing there! MI_SIZE can be
- zero as a result of parse errors. */
- if (TYPE_BINFO_BASETYPES (baseclass) && mi_size > 0)
- for (j = mi_size*(CLASSTYPE_CID (baseclass)-1); j >= 0; j -= mi_size)
- derived_row[j] |= base_row[j];
- TYPE_DERIVES_FROM (baseclass, BINFO_TYPE (binfo)) = 1;
- }
-
- SET_BINFO_MARKED (binfo);
-}
-
-/* Given a _CLASSTYPE node in a multiple inheritance lattice,
- convert the lattice into a simple relation such that,
- given to CIDs, C1 and C2, one can determine if C1 <= C2
- or C2 <= C1 or C1 <> C2.
-
- Once constructed, we walk the lattice depth fisrt,
- applying various functions to elements as they are encountered.
-
- We use xmalloc here, in case we want to randomly free these tables. */
-
-#define SAVE_MI_MATRIX
-
-void
-build_mi_matrix (type)
- tree type;
-{
- tree binfo = TYPE_BINFO (type);
- cid = 0;
-
-#ifdef SAVE_MI_MATRIX
- if (CLASSTYPE_MI_MATRIX (type))
- {
- mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
- mi_matrix = CLASSTYPE_MI_MATRIX (type);
- mi_type = type;
- dfs_walk (binfo, dfs_number, unnumberedp);
- return;
- }
-#endif
-
- mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
- mi_matrix = (char *)xmalloc ((mi_size+1) * (mi_size+1));
- mi_type = type;
- bzero (mi_matrix, mi_size * mi_size);
- dfs_walk (binfo, dfs_number, unnumberedp);
- dfs_walk (binfo, dfs_record_inheritance, unmarkedp);
- dfs_walk (binfo, dfs_unmark, markedp);
-}
-
-void
-free_mi_matrix ()
-{
- dfs_walk (TYPE_BINFO (mi_type), dfs_unnumber, numberedp);
-
-#ifdef SAVE_MI_MATRIX
- CLASSTYPE_MI_MATRIX (mi_type) = mi_matrix;
-#else
- free (mi_matrix);
- mi_size = 0;
- cid = 0;
-#endif
-}
-
-/* Local variables for detecting ambiguities of virtual functions
- when two or more classes are joined at a multiple inheritance
- seam. */
-typedef struct
-{
- tree decl;
- tree args;
- tree ptr;
-} mi_ventry;
-static mi_ventry *mi_vmatrix;
-static int *mi_vmax;
-static int mi_vrows, mi_vcols;
-#define MI_VMATRIX(ROW,COL) ((mi_vmatrix + (ROW)*mi_vcols)[COL])
-
-/* Build a table of virtual functions for a multiple-inheritance
- structure. Here, there are N base classes, and at most
- M entries per class.
-
- This function does nothing if N is 0 or 1. */
-void
-build_mi_virtuals (rows, cols)
- int rows, cols;
-{
- if (rows < 2 || cols == 0)
- return;
- mi_vrows = rows;
- mi_vcols = cols;
- mi_vmatrix = (mi_ventry *)xmalloc ((rows+1) * cols * sizeof (mi_ventry));
- mi_vmax = (int *)xmalloc ((rows+1) * sizeof (int));
-
- bzero (mi_vmax, rows * sizeof (int));
-
- /* Row indices start at 1, so adjust this. */
- mi_vmatrix -= cols;
- mi_vmax -= 1;
-}
-
-/* Comparison function for ordering virtual function table entries. */
-static int
-rank_mi_virtuals (v1, v2)
- mi_ventry *v1, *v2;
-{
- tree p1, p2;
- int i;
-
- i = (long) (DECL_NAME (v1->decl)) - (long) (DECL_NAME (v2->decl));
- if (i)
- return i;
- p1 = v1->args;
- p2 = v2->args;
-
- if (p1 == p2)
- return 0;
-
- while (p1 && p2)
- {
- i = ((long) (TREE_VALUE (p1)) - (long) (TREE_VALUE (p2)));
- if (i)
- return i;
-
- if (TREE_CHAIN (p1))
- {
- if (! TREE_CHAIN (p2))
- return 1;
- p1 = TREE_CHAIN (p1);
- p2 = TREE_CHAIN (p2);
- }
- else if (TREE_CHAIN (p2))
- return -1;
- else
- {
- /* When matches of argument lists occur, pick lowest
- address to keep searching time to a minimum on
- later passes--like hashing, only different.
- *MUST BE STABLE*. */
- if ((long) (v2->args) < (long) (v1->args))
- v1->args = v2->args;
- else
- v2->args = v1->args;
- return 0;
- }
- }
- return 0;
-}
-
-/* Install the virtuals functions got from the initializer VIRTUALS to
- the table at index ROW. */
-void
-add_mi_virtuals (row, virtuals)
- int row;
- tree virtuals;
-{
- int col = 0;
-
- if (mi_vmatrix == 0)
- return;
- while (virtuals)
- {
- tree decl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
- MI_VMATRIX (row, col).decl = decl;
- MI_VMATRIX (row, col).args = FUNCTION_ARG_CHAIN (decl);
- MI_VMATRIX (row, col).ptr = TREE_VALUE (virtuals);
- virtuals = TREE_CHAIN (virtuals);
- col += 1;
- }
- mi_vmax[row] = col;
-
- qsort (mi_vmatrix + row * mi_vcols,
- col,
- sizeof (mi_ventry),
- rank_mi_virtuals);
-}
-
-/* If joining two types results in an ambiguity in the virtual
- function table, report such here. */
-void
-report_ambiguous_mi_virtuals (rows, type)
- int rows;
- tree type;
-{
- int *mi_vmin;
- int row1, col1, row, col;
-
- if (mi_vmatrix == 0)
- return;
-
- /* Now virtuals are all sorted, so we merge to find ambiguous cases. */
- mi_vmin = (int *)alloca ((rows+1) * sizeof (int));
- bzero (mi_vmin, rows * sizeof (int));
-
- /* adjust. */
- mi_vmin -= 1;
-
- /* For each base class with virtual functions (and this includes views
- of the virtual baseclasses from different base classes), see that
- each virtual function in that base class has a unique meet.
-
- When the column loop is finished, THIS_DECL is in fact the meet.
- If that value does not appear in the virtual function table for
- the row, install it. This happens when that virtual function comes
- from a virtual baseclass, or a non-leftmost baseclass. */
-
- for (row1 = 1; row1 < rows; row1++)
- {
- tree this_decl = 0;
-
- for (col1 = mi_vmax[row1]-1; col1 >= mi_vmin[row1]; col1--)
- {
- tree these_args = MI_VMATRIX (row1, col1).args;
- tree this_context;
-
- this_decl = MI_VMATRIX (row1, col1).decl;
- if (this_decl == 0)
- continue;
- this_context = TYPE_BINFO (DECL_CLASS_CONTEXT (this_decl));
-
- if (this_context != TYPE_BINFO (type))
- this_context = get_binfo (this_context, type, 0);
-
- for (row = row1+1; row <= rows; row++)
- for (col = mi_vmax[row]-1; col >= mi_vmin[row]; col--)
- {
- mi_ventry this_entry;
-
- if (MI_VMATRIX (row, col).decl == 0)
- continue;
-
- this_entry.decl = this_decl;
- this_entry.args = these_args;
- this_entry.ptr = MI_VMATRIX (row1, col1).ptr;
- if (rank_mi_virtuals (&this_entry, &MI_VMATRIX (row, col)) == 0)
- {
- /* They are equal. There are four possibilities:
-
- (1) Derived class is defining this virtual function.
- (2) Two paths to the same virtual function in the
- same base class.
- (3) A path to a virtual function declared in one base
- class, and another path to a virtual function in a
- base class of the base class.
- (4) Two paths to the same virtual function in different
- base classes.
-
- The first three cases are ok (non-ambiguous). */
-
- tree that_context, tmp;
- int this_before_that;
-
- if (type == BINFO_TYPE (this_context))
- /* case 1. */
- goto ok;
- that_context = get_binfo (DECL_CLASS_CONTEXT (MI_VMATRIX (row, col).decl), type, 0);
- if (that_context == this_context)
- /* case 2. */
- goto ok;
- if (that_context != NULL_TREE)
- {
- tmp = get_binfo (that_context, this_context, 0);
- this_before_that = (that_context != tmp);
- if (this_before_that == 0)
- /* case 3a. */
- goto ok;
- tmp = get_binfo (this_context, that_context, 0);
- this_before_that = (this_context == tmp);
- if (this_before_that != 0)
- /* case 3b. */
- goto ok;
-
- /* case 4. */
- /* These two are not hard errors, but could be
- symptoms of bad code. The resultant code
- the compiler generates needs to be checked.
- (mrs) */
-#if 0
- error_with_decl (MI_VMATRIX (row, col).decl, "ambiguous virtual function `%s'");
- error_with_decl (this_decl, "ambiguating function `%s' (joined by type `%s')", IDENTIFIER_POINTER (current_class_name));
-#endif
- }
- ok:
- MI_VMATRIX (row, col).decl = 0;
-
- /* Let zeros propagate. */
- if (col == mi_vmax[row]-1)
- {
- int i = col;
- while (i >= mi_vmin[row]
- && MI_VMATRIX (row, i).decl == 0)
- i--;
- mi_vmax[row] = i+1;
- }
- else if (col == mi_vmin[row])
- {
- int i = col;
- while (i < mi_vmax[row]
- && MI_VMATRIX (row, i).decl == 0)
- i++;
- mi_vmin[row] = i;
- }
- }
- }
- }
- }
- free (mi_vmatrix + mi_vcols);
- mi_vmatrix = 0;
- free (mi_vmax + 1);
- mi_vmax = 0;
-}
-
-/* If we want debug info for a type TYPE, make sure all its base types
- are also marked as being potentially interesting. This avoids
- the problem of not writing any debug info for intermediate basetypes
- that have abstract virtual functions. */
-
-void
-note_debug_info_needed (type)
- tree type;
-{
- dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
-}
-
-/* Subroutines of push_class_decls (). */
-
-/* Add the instance variables which this class contributed to the
- current class binding contour. When a redefinition occurs,
- if the redefinition is strictly within a single inheritance path,
- we just overwrite (in the case of a data field) or
- cons (in the case of a member function) the old declaration with
- the new. If the fields are not within a single inheritance path,
- we must cons them in either case. */
-
-static void
-dfs_pushdecls (binfo)
- tree binfo;
-{
- tree type = BINFO_TYPE (binfo);
- tree fields, *methods, *end;
- tree method_vec;
-
- for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- {
- /* Unmark 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. */
- if (TREE_CODE (fields) == FIELD_DECL)
- TREE_USED (fields) = 0;
-
- if (DECL_NAME (fields) == NULL_TREE
- && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
- {
- dfs_pushdecls (TYPE_BINFO (TREE_TYPE (fields)));
- continue;
- }
- if (TREE_CODE (fields) != TYPE_DECL)
- {
- DECL_PUBLIC (fields) = 0;
- DECL_PROTECTED (fields) = 0;
- DECL_PRIVATE (fields) = 0;
- }
-
- if (DECL_NAME (fields))
- {
- tree value = IDENTIFIER_CLASS_VALUE (DECL_NAME (fields));
- if (value)
- {
- tree context;
-
- /* Possible ambiguity. If its defining type(s)
- is (are all) derived from us, no problem. */
-
- if (TREE_CODE (value) != TREE_LIST)
- {
- context = DECL_CLASS_CONTEXT (value);
-
- if (context && (context == type
- || TYPE_DERIVES_FROM (context, type)))
- value = fields;
- else
- value = tree_cons (NULL_TREE, fields,
- build_tree_list (NULL_TREE, value));
- }
- else
- {
- /* All children may derive from us, in which case
- there is no problem. Otherwise, we have to
- keep lists around of what the ambiguities might be. */
- tree values;
- int problem = 0;
-
- for (values = value; values; values = TREE_CHAIN (values))
- {
- tree sub_values = TREE_VALUE (values);
-
- if (TREE_CODE (sub_values) == TREE_LIST)
- {
- for (; sub_values; sub_values = TREE_CHAIN (sub_values))
- {
- context = DECL_CLASS_CONTEXT (TREE_VALUE (sub_values));
-
- if (! TYPE_DERIVES_FROM (context, type))
- {
- value = tree_cons (NULL_TREE, TREE_VALUE (values), value);
- problem = 1;
- break;
- }
- }
- }
- else
- {
- context = DECL_CLASS_CONTEXT (sub_values);
-
- if (! TYPE_DERIVES_FROM (context, type))
- {
- value = tree_cons (NULL_TREE, values, value);
- problem = 1;
- break;
- }
- }
- }
- if (! problem) value = fields;
- }
-
- /* Mark this as a potentially ambiguous member. */
- if (TREE_CODE (value) == TREE_LIST)
- {
- /* Leaving TREE_TYPE blank is intentional.
- We cannot use `error_mark_node' (lookup_name)
- or `unknown_type_node' (all member functions use this). */
- TREE_NONLOCAL_FLAG (value) = 1;
- }
-
- IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) = value;
- }
- else IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) = fields;
- }
- }
-
- method_vec = CLASSTYPE_METHOD_VEC (type);
- if (method_vec != 0)
- {
- /* Farm out constructors and destructors. */
- methods = &TREE_VEC_ELT (method_vec, 1);
- end = TREE_VEC_END (method_vec);
-
- /* This does not work for multiple inheritance yet. */
- while (methods != end)
- {
- /* This will cause lookup_name to return a pointer
- to the tree_list of possible methods of this name.
- If the order is a problem, we can nreverse them. */
- tree tmp;
- tree old = IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods));
-
- if (old && TREE_CODE (old) == TREE_LIST)
- tmp = tree_cons (DECL_NAME (*methods), *methods, old);
- else
- {
- /* Only complain if we shadow something we can access. */
- if (old && (DECL_CLASS_CONTEXT (old) == current_class_type
- || ! TREE_PRIVATE (old)))
- /* Should figure out visibility more accurately. */
- warning ("shadowing member `%s' with member function",
- IDENTIFIER_POINTER (DECL_NAME (*methods)));
- tmp = build_tree_list (DECL_NAME (*methods), *methods);
- }
-
- TREE_TYPE (tmp) = unknown_type_node;
-#if 0
- TREE_OVERLOADED (tmp) = DECL_OVERLOADED (*methods);
-#endif
- TREE_NONLOCAL_FLAG (tmp) = 1;
- IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods)) = tmp;
-
- tmp = *methods;
- while (tmp != 0)
- {
- DECL_PUBLIC (tmp) = 0;
- DECL_PROTECTED (tmp) = 0;
- DECL_PRIVATE (tmp) = 0;
- tmp = DECL_CHAIN (tmp);
- }
-
- methods++;
- }
- }
- SET_BINFO_MARKED (binfo);
-}
-
-/* Consolidate unique (by name) member functions. */
-static void
-dfs_compress_decls (binfo)
- tree binfo;
-{
- tree type = BINFO_TYPE (binfo);
- tree method_vec = CLASSTYPE_METHOD_VEC (type);
-
- if (method_vec != 0)
- {
- /* Farm out constructors and destructors. */
- tree *methods = &TREE_VEC_ELT (method_vec, 1);
- tree *end = TREE_VEC_END (method_vec);
-
- for (; methods != end; methods++)
- {
- tree tmp = IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods));
-
- /* This was replaced in scope by somebody else. Just leave it
- alone. */
- if (TREE_CODE (tmp) != TREE_LIST)
- continue;
-
- if (TREE_CHAIN (tmp) == NULL_TREE
- && TREE_VALUE (tmp)
- && DECL_CHAIN (TREE_VALUE (tmp)) == NULL_TREE)
- {
- IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods)) = TREE_VALUE (tmp);
- }
- }
- }
- CLEAR_BINFO_MARKED (binfo);
-}
-
-/* When entering the scope of a class, we cache all of the
- fields that that class provides within its inheritance
- lattice. Where ambiguities result, we mark them
- with `error_mark_node' so that if they are encountered
- without explicit qualification, we can emit an error
- message. */
-void
-push_class_decls (type)
- tree type;
-{
- tree id;
- struct obstack *ambient_obstack = current_obstack;
-
-#if 0
- tree tags = CLASSTYPE_TAGS (type);
-
- while (tags)
- {
- tree code_type_node;
- tree tag;
-
- switch (TREE_CODE (TREE_VALUE (tags)))
- {
- case ENUMERAL_TYPE:
- code_type_node = enum_type_node;
- break;
- case RECORD_TYPE:
- code_type_node = record_type_node;
- break;
- case CLASS_TYPE:
- code_type_node = class_type_node;
- break;
- case UNION_TYPE:
- code_type_node = union_type_node;
- break;
- default:
- my_friendly_abort (297);
- }
- tag = xref_tag (code_type_node, TREE_PURPOSE (tags),
- TYPE_BINFO_BASETYPE (TREE_VALUE (tags), 0));
-#if 0 /* not yet, should get fixed properly later */
- pushdecl (make_type_decl (TREE_PURPOSE (tags), TREE_VALUE (tags)));
-#else
- pushdecl (build_decl (TYPE_DECL, TREE_PURPOSE (tags), TREE_VALUE (tags)));
-#endif
- }
-#endif
-
- current_obstack = &bridge_obstack;
- search_stack = push_search_level (search_stack, &bridge_obstack);
-
- id = TYPE_IDENTIFIER (type);
- if (IDENTIFIER_TEMPLATE (id) != 0)
- {
-#if 0
- tree tmpl = IDENTIFIER_TEMPLATE (id);
- push_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)),
- TREE_VALUE (tmpl), 1);
-#endif
- overload_template_name (id, 0);
- }
-
- /* Push class fields into CLASS_VALUE scope, and mark. */
- dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
-
- /* Compress fields which have only a single entry
- by a given name, and unmark. */
- dfs_walk (TYPE_BINFO (type), dfs_compress_decls, markedp);
- current_obstack = ambient_obstack;
-}
-
-static void
-dfs_popdecls (binfo)
- tree binfo;
-{
- tree type = BINFO_TYPE (binfo);
- tree fields = TYPE_FIELDS (type);
- tree method_vec = CLASSTYPE_METHOD_VEC (type);
-
- while (fields)
- {
- if (DECL_NAME (fields) == NULL_TREE
- && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
- {
- dfs_popdecls (TYPE_BINFO (TREE_TYPE (fields)));
- }
- else if (DECL_NAME (fields))
- IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) = NULL_TREE;
- fields = TREE_CHAIN (fields);
- }
- if (method_vec != 0)
- {
- tree *methods = &TREE_VEC_ELT (method_vec, 0);
- tree *end = TREE_VEC_END (method_vec);
-
- /* Clear out ctors and dtors. */
- if (*methods)
- IDENTIFIER_CLASS_VALUE (TYPE_IDENTIFIER (type)) = NULL_TREE;
-
- for (methods += 1; methods != end; methods++)
- IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods)) = NULL_TREE;
- }
-
- SET_BINFO_MARKED (binfo);
-}
-
-void
-pop_class_decls (type)
- tree type;
-{
- tree binfo = TYPE_BINFO (type);
-
- /* Clear out the IDENTIFIER_CLASS_VALUE which this
- class may have occupied, and mark. */
- dfs_walk (binfo, dfs_popdecls, unmarkedp);
-
- /* Unmark. */
- dfs_walk (binfo, dfs_unmark, markedp);
-
-#if 0
- tmpl = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (type));
- if (tmpl != 0)
- pop_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)),
- TREE_VALUE (tmpl), 1);
-#endif
-
- search_stack = pop_search_level (search_stack);
-}
-
-/* Given a base type PARENT, and a derived type TYPE, build
- a name which distinguishes exactly the PARENT member of TYPE's type.
-
- FORMAT is a string which controls how sprintf formats the name
- we have generated.
-
- For example, given
-
- class A; class B; class C : A, B;
-
- it is possible to distinguish "A" from "C's A". And given
-
- class L;
- class A : L; class B : L; class C : A, B;
-
- it is possible to distinguish "L" from "A's L", and also from
- "C's L from A".
-
- Make sure to use the DECL_ASSEMBLER_NAME of the TYPE_NAME of the
- type, as template have DECL_NAMEs like: X<int>, whereas the
- DECL_ASSEMBLER_NAME is set to be something the assembler can handle.
- */
-tree
-build_type_pathname (format, parent, type)
- char *format;
- tree parent, type;
-{
- extern struct obstack temporary_obstack;
- char *first, *base, *name;
- int i;
- tree id;
-
- parent = TYPE_MAIN_VARIANT (parent);
-
- /* Remember where to cut the obstack to. */
- first = obstack_base (&temporary_obstack);
-
- /* Put on TYPE+PARENT. */
- obstack_grow (&temporary_obstack,
- TYPE_ASSEMBLER_NAME_STRING (type),
- TYPE_ASSEMBLER_NAME_LENGTH (type));
-#ifdef JOINER
- obstack_1grow (&temporary_obstack, JOINER);
-#else
- obstack_1grow (&temporary_obstack, '_');
-#endif
- obstack_grow0 (&temporary_obstack,
- TYPE_ASSEMBLER_NAME_STRING (parent),
- TYPE_ASSEMBLER_NAME_LENGTH (parent));
- i = obstack_object_size (&temporary_obstack);
- base = obstack_base (&temporary_obstack);
- obstack_finish (&temporary_obstack);
-
- /* Put on FORMAT+TYPE+PARENT. */
- obstack_blank (&temporary_obstack, strlen (format) + i + 1);
- name = obstack_base (&temporary_obstack);
- sprintf (name, format, base);
- id = get_identifier (name);
- obstack_free (&temporary_obstack, first);
-
- return id;
-}
-
-static int
-bfs_unmark_finished_struct (binfo, i)
- tree binfo;
- int i;
-{
- if (i >= 0)
- binfo = BINFO_BASETYPE (binfo, i);
-
- if (BINFO_NEW_VTABLE_MARKED (binfo))
- {
- tree decl, context;
-
- if (TREE_VIA_VIRTUAL (binfo))
- binfo = binfo_member (BINFO_TYPE (binfo),
- CLASSTYPE_VBASECLASSES (current_class_type));
-
- decl = BINFO_VTABLE (binfo);
- context = DECL_CONTEXT (decl);
- DECL_CONTEXT (decl) = 0;
- if (write_virtuals >= 0
- && DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
- DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
- BINFO_VIRTUALS (binfo));
- finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
- DECL_CONTEXT (decl) = context;
- }
- CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
- return 0;
-}
-
-void
-unmark_finished_struct (type)
- tree type;
-{
- tree binfo = TYPE_BINFO (type);
- bfs_unmark_finished_struct (binfo, -1);
- breadth_first_search (binfo, bfs_unmark_finished_struct, bfs_marked_vtable_pathp);
-}
-
-void
-print_search_statistics ()
-{
-#ifdef GATHER_STATISTICS
- if (flag_memoize_lookups)
- {
- fprintf (stderr, "%d memoized contexts saved\n",
- n_contexts_saved);
- fprintf (stderr, "%d local tree nodes made\n", my_tree_node_counter);
- fprintf (stderr, "%d local hash nodes made\n", my_memoized_entry_counter);
- fprintf (stderr, "fields statistics:\n");
- fprintf (stderr, " memoized finds = %d; rejects = %d; (searches = %d)\n",
- memoized_fast_finds[0], memoized_fast_rejects[0],
- memoized_fields_searched[0]);
- fprintf (stderr, " memoized_adds = %d\n", memoized_adds[0]);
- fprintf (stderr, "fnfields statistics:\n");
- fprintf (stderr, " memoized finds = %d; rejects = %d; (searches = %d)\n",
- memoized_fast_finds[1], memoized_fast_rejects[1],
- memoized_fields_searched[1]);
- fprintf (stderr, " memoized_adds = %d\n", memoized_adds[1]);
- }
- fprintf (stderr, "%d fields searched in %d[%d] calls to lookup_field[_1]\n",
- n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1);
- fprintf (stderr, "%d fnfields searched in %d calls to lookup_fnfields\n",
- n_outer_fields_searched, n_calls_lookup_fnfields);
- fprintf (stderr, "%d calls to get_base_type\n", n_calls_get_base_type);
-#else
- fprintf (stderr, "no search statistics\n");
-#endif
-}
-
-void
-init_search_processing ()
-{
- gcc_obstack_init (&search_obstack);
- gcc_obstack_init (&type_obstack);
- gcc_obstack_init (&type_obstack_entries);
- gcc_obstack_init (&bridge_obstack);
-
- /* This gives us room to build our chains of basetypes,
- whether or not we decide to memoize them. */
- type_stack = push_type_level (0, &type_obstack);
- _vptr_name = get_identifier ("_vptr");
-}
-
-void
-reinit_search_statistics ()
-{
- my_memoized_entry_counter = 0;
- memoized_fast_finds[0] = 0;
- memoized_fast_finds[1] = 0;
- memoized_adds[0] = 0;
- memoized_adds[1] = 0;
- memoized_fast_rejects[0] = 0;
- memoized_fast_rejects[1] = 0;
- memoized_fields_searched[0] = 0;
- memoized_fields_searched[1] = 0;
- n_fields_searched = 0;
- n_calls_lookup_field = 0, n_calls_lookup_field_1 = 0;
- n_calls_lookup_fnfields = 0, n_calls_lookup_fnfields_1 = 0;
- n_calls_get_base_type = 0;
- n_outer_fields_searched = 0;
- n_contexts_saved = 0;
-}
diff --git a/gnu/gcc2/cc1plus/cp-spew.c b/gnu/gcc2/cc1plus/cp-spew.c
deleted file mode 100644
index 92f8e618832a..000000000000
--- a/gnu/gcc2/cc1plus/cp-spew.c
+++ /dev/null
@@ -1,1086 +0,0 @@
-/* Type Analyzer for GNU C++.
- Copyright (C) 1987, 1989, 1992, 1993 Free Software Foundation, Inc.
- Hacked... nay, bludgeoned... by Mark Eichin (eichin@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. */
-
-
-/* This file is the type analyzer for GNU C++. To debug it, define SPEW_DEBUG
- when compiling cp-parse.c and cp-spew.c. */
-
-#include "config.h"
-#include <stdio.h>
-#include "input.h"
-#include "tree.h"
-#include "cp-lex.h"
-#include "cp-parse.h"
-#include "cp-tree.h"
-#include "flags.h"
-#include "obstack.h"
-
-/* This takes a token stream that hasn't decided much about types and
- tries to figure out as much as it can, with excessive lookahead and
- backtracking. */
-
-/* fifo of tokens recognized and available to parser. */
-struct token {
- /* The values for YYCHAR will fit in a short. */
- short yychar;
- short end_of_file;
- YYSTYPE yylval;
-};
-
-static int do_aggr ();
-static struct token frob_identifier ();
-static struct token hack_scope ();
-static tree hack_ptype ();
-static tree hack_more_ids ();
-
-/* From cp-lex.c: */
-/* the declaration found for the last IDENTIFIER token read in.
- yylex must look this up to detect typedefs, which get token type TYPENAME,
- so it is left around in case the identifier is not a typedef but is
- used in a context which makes it a reference to a variable. */
-extern tree lastiddecl; /* let our brains leak out here too */
-extern int yychar; /* the lookahead symbol */
-extern YYSTYPE yylval; /* the semantic value of the */
- /* lookahead symbol */
-extern int end_of_file;
-
-struct obstack token_obstack;
-int first_token;
-
-#ifdef SPEW_DEBUG
-int spew_debug = 0;
-static unsigned int yylex_ctr = 0;
-static int debug_yychar ();
-#endif
-
-static char follows_typename[END_OF_SAVED_INPUT+1];
-static char follows_identifier[END_OF_SAVED_INPUT+1];
-
-/* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name
- * of the last template_type parsed in cp-parse.y if it is followed by a
- * scope operator. It will be reset inside the next invocation of yylex().
- * This is used for recognizing nested types inside templates.
- * - niklas@appli.se */
-tree template_type_seen_before_scope;
-
-/* Initialize token_obstack. Called once, from init_lex. */
-void
-init_spew ()
-{
- static char *chars_following_identifier = ".+-|/%^!?:";
- short *ps;
- static short toks_follow_ids[] =
- { POINTSAT_LEFT_RIGHT, ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE,
- ARITHCOMPARE, LSHIFT, RSHIFT, UNARY, PLUSPLUS, MINUSMINUS, POINTSAT,
- POINTSAT_STAR, DOT_STAR, CONSTANT, STRING, SIZEOF, ENUM, IF,
- ELSE, WHILE, DO, FOR, SWITCH, CASE, DEFAULT, BREAK, CONTINUE,
- RETURN, GOTO, ASM_KEYWORD, GCC_ASM_KEYWORD, TYPEOF, ALIGNOF, HEADOF,
- CLASSOF, ATTRIBUTE, AGGR, VISSPEC, DELETE, RAISE, RERAISE, TRY, EXCEPT,
- CATCH, THROW, ANSI_TRY, ANSI_THROW, EXTERN_LANG_STRING, ALL,
- END_OF_SAVED_INPUT, -1 };
- static short toks_follow_types[] =
- { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCSPEC, TYPESPEC, TYPE_QUAL,
- ELLIPSIS, THIS, OPERATOR, DYNAMIC, TEMPLATE, SCOPE, START_DECLARATOR,
- TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME,
- PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 };
-
- gcc_obstack_init(&token_obstack);
-
- /* Initialize the arrays saying what tokens are definitely
- (or possibly) valid following typenames and identifiers. */
- while (*chars_following_identifier)
- follows_identifier[*chars_following_identifier++] = 1;
- for (ps = toks_follow_ids; *ps != -1; ps++)
- follows_identifier[*ps] = 1;
- for (ps = toks_follow_types; *ps != -1; ps++)
- follows_typename[*ps] = 1;
-}
-
-#ifdef SPEW_DEBUG
-/* Use functions for debugging... */
-
-/* Return the number of tokens available on the fifo. */
-static int
-num_tokens ()
-{
- return (obstack_object_size(&token_obstack)/sizeof(struct token))
- - first_token;
-}
-
-/* Fetch the token N down the line from the head of the fifo. */
-static struct token*
-nth_token (n)
- int n;
-{
- /* could just have this do slurp_ implicitly, but this way is easier
- * to debug... */
- my_friendly_assert (n < num_tokens(), 298);
- return ((struct token*)obstack_base(&token_obstack))+n+first_token;
-}
-
-/* Add a token to the token fifo. */
-static void
-add_token (t)
- struct token* t;
-{
- obstack_grow(&token_obstack,t,sizeof (struct token));
-}
-
-/* Consume the next token out of the fifo. */
-static void
-consume_token()
-{
- if (num_tokens() == 1)
- {
- obstack_free(&token_obstack, obstack_base (&token_obstack));
- first_token = 0;
- }
- else
- first_token++;
-}
-
-#else
-/* ...otherwise use macros. */
-
-#define num_tokens() \
- ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token)
-
-#define nth_token(N) \
- (((struct token*)obstack_base(&token_obstack))+(N)+first_token)
-
-#define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token))
-
-#define consume_token() \
- (num_tokens() == 1 \
- ? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \
- (first_token = 0)) \
- : first_token++)
-#endif
-
-/* Pull in enough tokens from real_yylex that the queue is N long. */
-
-static void
-scan_tokens (n)
- int n;
-{
- int i;
- struct token *tmp;
-
- /* We cannot read past certain tokens, so make sure we don't. */
- i = num_tokens ();
- if (i > n)
- return;
- while (i-- > 0)
- {
- tmp = nth_token (i);
- /* Never read past these characters: they might separate
- the current input stream from one we save away later. */
- if (tmp->yychar == '{' || tmp->yychar == ':')
- goto pad_tokens;
- }
-
- while (num_tokens() <= n)
- {
- obstack_blank(&token_obstack,sizeof (struct token));
- tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
- tmp->yychar = real_yylex();
- tmp->end_of_file = end_of_file;
- tmp->yylval = yylval;
- end_of_file = 0;
- if (tmp->yychar == '{'
- || tmp->yychar == ':'
- || tmp->yychar == ';')
- {
- pad_tokens:
- while (num_tokens () <= n)
- {
- obstack_blank(&token_obstack,sizeof (struct token));
- tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
- tmp->yychar = EMPTY;
- tmp->end_of_file = 0;
- }
- }
- }
-}
-
-/* Create room for N tokens at the front of the fifo. This is used
- to insert new tokens into the stream ahead of the current token. */
-
-static void
-shift_tokens (n)
- int n;
-{
- if (first_token >= n)
- first_token -= n;
- else
- {
- int old_token_count = num_tokens ();
- char *tmp;
-
- obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token));
- if (old_token_count)
- {
- tmp = (char *)alloca ((num_tokens () + (n-first_token))
- * sizeof (struct token));
- /* This move does not rely on the system being able to handle
- overlapping moves. */
- bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token));
- bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token));
- }
- first_token = 0;
- }
-}
-
-static int
-probe_obstack (h, obj, nlevels)
- struct obstack *h;
- tree obj;
- unsigned int nlevels;
-{
- register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk* plp; /* point to previous chunk if any */
-
- lp = (h)->chunk;
- /* We use >= rather than > since the object cannot be exactly at
- the beginning of the chunk but might be an empty object exactly
- at the end of an adjacent chunk. */
- for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
- nlevels -= 1)
- {
- plp = lp->prev;
- lp = plp;
- }
- return nlevels != 0 && lp != 0;
-}
-
-/* from cp-lex.c: */
-/* Value is 1 if we should try to make the next identifier look like a
- typename (when it may be a local variable or a class variable).
- Value is 0 if we treat this name in a default fashion.
- Value is -1 if we must not see a type name. */
-extern int looking_for_typename;
-
-extern struct obstack *current_obstack, *saveable_obstack;
-
-int
-yylex()
-{
- struct token tmp_token;
- tree trrr;
-
- retry:
-#ifdef SPEW_DEBUG
- if (spew_debug)
- {
- yylex_ctr ++;
- fprintf(stderr, "\t\t## %d ##",yylex_ctr);
- }
-#endif
-
- /* This is a kludge for recognizing nested types in templates */
- if (template_type_seen_before_scope)
- {
- shift_tokens (2); /* Sync in hack_more_ids (yes, it's ugly) */
- nth_token (1)->yychar = SCOPE;
- yylval.ttype = hack_more_ids (0, template_type_seen_before_scope);
- template_type_seen_before_scope = 0;
- if (!yylval.ttype)
- {
- /* Sync back again, leaving SCOPE on the token stream, because we
- * failed to substitute the original SCOPE token with a
- * SCOPED_TYPENAME. See rule "template_type" in cp-parse.y */
- consume_token ();
- }
- else
- {
- yychar = SCOPED_TYPENAME;
-#ifdef SPEW_DEBUG
- if (spew_debug)
- debug_yychar(yychar);
-#endif
- return yychar;
- }
- }
-
- /* if we've got tokens, send them */
- if (num_tokens())
- {
- tmp_token= *nth_token(0);
-
- /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
- If we don't find it in CURRENT_OBSTACK's current or immediately
- previous chunk, assume it was and copy it to the current obstack. */
- if ((tmp_token.yychar == CONSTANT
- || tmp_token.yychar == STRING)
- && ! TREE_PERMANENT (tmp_token.yylval.ttype)
- && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)
- && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))
- tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);
- }
- else
- {
- /* if not, grab the next one and think about it */
- tmp_token.yychar = real_yylex ();
- tmp_token.yylval = yylval;
- tmp_token.end_of_file = end_of_file;
- add_token(&tmp_token);
- }
-
- /* many tokens just need to be returned. At first glance, all we
- * have to do is send them back up, but some of them are needed to
- * figure out local context. */
- switch(tmp_token.yychar)
- {
- case EMPTY:
- /* This is a lexical no-op. */
- consume_token ();
-#ifdef SPEW_DEBUG
- if (spew_debug)
- debug_yychar (tmp_token.yychar);
-#endif
- goto retry;
-
- case IDENTIFIER:
- /* Note: this calls arbitrate_lookup. */
- trrr = lookup_name (tmp_token.yylval.ttype, -2);
- if (trrr)
- {
- tmp_token.yychar = identifier_type (trrr);
- switch (tmp_token.yychar)
- {
- case TYPENAME:
- lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
- if (lastiddecl == NULL_TREE)
- lastiddecl = trrr;
- break;
- case IDENTIFIER:
- lastiddecl = trrr;
- break;
- case PTYPENAME:
- /* This is for cases like
- template<class A> X<A>::operator[] ...
- since "X" is (presumably) a PTYPENAME; we might want to
- avoid seeing the entire thing as a type name, but X<A>
- must be one.
-
- It might not work right if the thing after the ::
- can be a typename nested in X<A>, but I don't think the
- PT code would be up to dealing with that anyways. --KR */
- if (looking_for_typename == -1)
- {
- scan_tokens (2);
- if (nth_token(1)->yychar == '<')
- looking_for_typename = 0;
- }
- break;
- default:
- my_friendly_abort (101);
- }
- }
- else
- lastiddecl = trrr;
- /* and fall through to... */
- case TYPENAME:
- case PTYPENAME:
- /* if (new_token) add_token (&tmp_token); */
- *nth_token(0) = tmp_token;
- tmp_token = frob_identifier ();
- if (looking_for_typename < 0)
- {
- tmp_token.yychar = IDENTIFIER;
- lastiddecl = 0;
- looking_for_typename = 0;
- }
- else if (lastiddecl && TREE_CODE (lastiddecl) == TYPE_DECL)
- {
- scan_tokens (2);
- if (nth_token(0)->yychar == IDENTIFIER
- && nth_token (1)->yychar != SCOPE)
- looking_for_typename = -1;
- else
- looking_for_typename = 0;
- goto finish_typename_processing;
- }
- else
- looking_for_typename = 0;
- break;
-
- case TYPESPEC:
- case SCSPEC:
- consume_token ();
- finish_typename_processing:
- /* Now see if we should insert a START_DECLARATOR token.
- Here are the cases caught:
-
- typespec ( * ID ) ( // ptr to function
- typespec ( & ID ) ( // ref to function
- typespec ( * ID ) [ // array of pointers
- typespec ( & ID ) [ // array of references
-
- This is a terrible kludge. */
-
- scan_tokens (2);
- if (nth_token (0)->yychar == '('
- && (nth_token (1)->yychar == '*'
- || nth_token (1)->yychar == '&'))
- {
- scan_tokens (5);
- if (nth_token (3)->yychar == ')'
- && (nth_token (4)->yychar == '('
- || nth_token (4)->yychar == '['
- || nth_token (4)->yychar == LEFT_RIGHT)
- && (nth_token (2)->yychar == IDENTIFIER
- || nth_token (2)->yychar == TYPENAME))
- {
- shift_tokens (1);
- nth_token (0)->yychar = START_DECLARATOR;
- }
- }
- /* Extend to handle:
-
- typespec (ID::* qf)( // ptr to member function
- typespec (ID::* qf)[ // array of ptr to member functions
-
- */
- if (nth_token (0)->yychar == '('
- && (nth_token (1)->yychar == IDENTIFIER
- || nth_token (1)->yychar == TYPENAME))
- {
- scan_tokens (7);
- if (nth_token (2)->yychar == SCOPE
- && nth_token (3)->yychar == '*'
- && (nth_token (4)->yychar == IDENTIFIER
- || nth_token (4)->yychar == TYPENAME)
- && nth_token (5)->yychar == ')'
- && (nth_token (6)->yychar == '('
- || nth_token (6)->yychar == '['
- || nth_token (6)->yychar == LEFT_RIGHT))
- {
- shift_tokens (1);
- nth_token (0)->yychar = START_DECLARATOR;
- }
- }
- break;
-
-#if 0
- case '(':
- /* Handle casts. We are looking for one of:
- `( TYPENAME' followed by `)', or
- `( TYPENAME *' followed by one of `[,*,&,)', or
- `( TYPENAME &' followed by one of `[,*,&,)', or
- `( TYPENAME [' followed by `]'. We are punting
- generality on scanning casts to array types. */
- scan_tokens (4);
- if (nth_token (1)->yychar == IDENTIFIER)
- {
- tree type = identifier_typedecl_value (nth_token (1)->yylval.ttype);
- if (type)
- switch (nth_token (2)->yychar)
- {
- default:
- break;
- }
- }
- break;
-
- case SCOPE:
- /* if (new_token) add_token (&tmp_token); */
- *nth_token(0) = tmp_token;
- tmp_token = hack_scope ();
- break;
-#endif
-
- case AGGR:
- *nth_token(0) = tmp_token;
- do_aggr ();
- /* fall through to output... */
- case ENUM:
- /* Set this again, in case we are rescanning. */
- looking_for_typename = 1;
- /* fall through... */
- default:
-#ifdef SPEW_DEBUG
- if (spew_debug)
- debug_yychar(tmp_token.yychar);
-#endif
- consume_token();
- yylval = tmp_token.yylval;
- yychar = tmp_token.yychar;
- end_of_file = tmp_token.end_of_file;
- return tmp_token.yychar;
- }
-
- if (tmp_token.yychar == SCOPED_TYPENAME)
- {
-#if 0
- tree t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype);
- if (t2 != NULL_TREE)
- {
- tmp_token.yylval.ttype = t2;
- tmp_token.yychar = TYPENAME;
- }
- else
- {
- /* unwind? */
- }
- }
- else
- {
- /* couldn't get here, as is... */
-#endif
- tmp_token.yychar = TYPENAME;
- }
-
- yylval = tmp_token.yylval;
- yychar = tmp_token.yychar;
- end_of_file = tmp_token.end_of_file;
-#ifdef SPEW_DEBUG
- if (spew_debug)
- debug_yychar(yychar);
-#endif
-/* consume_token(); */ /* already eaten by frob_identifier?... */
- return yychar;
-}
-
-/* token[0] == AGGR (struct/union/enum)
- * thus, token[1] is either a TYPENAME or a TYPENAME_DEFN
- * if token[2] == '{' or ':' then it's TYPENAME_DEFN
- */
-static int
-do_aggr ()
-{
- int yc1, yc2;
-
- scan_tokens (2);
- yc1 = nth_token (1)->yychar;
- if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
- return 0;
- yc2 = nth_token (2)->yychar;
- if (yc2 == '{' || yc2 == ':')
- {
- switch (yc1)
- {
- case TYPENAME:
- nth_token (1)->yychar = TYPENAME_DEFN;
- break;
- case PTYPENAME:
- nth_token (1)->yychar = PTYPENAME_DEFN;
- break;
- case IDENTIFIER:
- nth_token (1)->yychar = IDENTIFIER_DEFN;
- break;
- default:
- my_friendly_abort (102);
- }
- }
- return 0;
-}
-
-static struct token
-frob_identifier ()
-{
- /* we could have a type, if it is followed by :: (if so, suck it all up); */
- /* we could have a ptypename; */
- /* we could have a normal identifier. */
- tree t1;
- struct token rt;
-
- scan_tokens(1);
- rt = *nth_token(0);
-
-#if 0
- if (nth_token(1)->yychar == '<')
- {
- t1 = hack_ptype(); /* suck up the whole thing */
- if (t1)
- {
- rt.yylval.ttype = t1;
- rt.yychar = TYPENAME;
- *nth_token(0) = rt;
- }
- /* else fall out bottom */
- }
-#endif
-
- if (nth_token(1)->yychar == SCOPE)
- {
-#if 0
- t1 = hack_more_ids(0);
- if (t1 && TREE_CODE(t1) == SCOPE_REF)
-#else
- t1 = hack_more_ids(0, nth_token (0)->yylval.ttype);
- if (t1)
-#endif
- {
- rt.yylval.ttype = t1;
- rt.yychar = SCOPED_TYPENAME ;
- return rt;
- }
- else
- {
- /* deal with types (enums?) in classes... */
- struct token *tok;
- tree ta, tb;
- scan_tokens(3);
-
- /* Have to check for a type conversion operator
- to a nested type. */
- if (nth_token (2)->yychar == OPERATOR)
- tok = nth_token (3);
- else
- tok = nth_token(2);
-
- if (tok->yychar == IDENTIFIER || tok->yychar == TYPENAME)
- {
- ta = build_parse_node (SCOPE_REF,
- nth_token(0)->yylval.ttype,
- tok->yylval.ttype);
- tb = resolve_scope_to_name (NULL_TREE, ta);
-
- if (tb != NULL_TREE)
- {
- if (nth_token (2)->yychar == OPERATOR)
- {
- /* Have to keep these tokens around
- so we can finish parsing the declaration.
- What do we do for
-
- int foo::operator bar::baz ();
-
- where bar is a nested class in foo? */
- nth_token (3)->yychar = TYPENAME;
- nth_token (3)->yylval.ttype = tb;
- }
- else
- {
- consume_token (); /* base type */
- consume_token (); /* SCOPE */
- consume_token (); /* member type */
- rt.yychar = TYPENAME;
- rt.yylval.ttype = tb;
- rt.end_of_file = tok->end_of_file;
- return rt;
- }
-
- }
- }
- /* else fall out bottom */
- }
- }
-
- consume_token();
- return rt;
-}
-
-/* When this function is called, nth_token(0) is the current
- token we are scanning. This means that the next token we'll
- scan is nth_token (1). Usually the next token we'll scan
- is nth_token (0) (and the current token is in [yylval,yychar]). */
-tree
-arbitrate_lookup (name, exp_decl, type_decl)
- tree name, exp_decl, type_decl;
-{
- int ch;
-
- scan_tokens (3);
- ch = nth_token (1)->yychar;
-
- switch (ch)
- {
- case '(':
- case LEFT_RIGHT:
- /* If we guessed wrong here, `build_functional_cast' can fix it. */
- return type_decl;
-
- case '=':
- if (global_bindings_p ())
- /* Probably a default parameter. */
- return type_decl;
- /* Probably not an initialization. */
- return exp_decl;
-
- case '[':
- /* This needs special help because an expression inside the
- brackets means nothing. */
- {
- int i;
-
- for (i = 0; i < 42; i++)
- {
- int ith_yychar;
-
- scan_tokens (3+i);
- ith_yychar = nth_token (2+i)->yychar;
-
- /* If we hit an undefined identifier, assume
- the decl in arbitration is its type specifier. */
- if (ith_yychar == IDENTIFIER
- && lookup_name (nth_token (2+i)->yylval.ttype, 0) == 0)
- return type_decl;
- else if (ith_yychar == ']')
- {
- /* There are only a few things we expect after a ']'
- in a declarator. */
- i += 1;
- scan_tokens (4+i);
- ith_yychar = nth_token (2+i)->yychar;
-
- /* These are inconclusive. */
- if (ith_yychar == LEFT_RIGHT
- || ith_yychar == '('
- || ith_yychar == '['
- || ith_yychar == ',')
- continue;
- /* stmt or decl? We'll probably never know. */
- else if (ith_yychar == ';')
- goto warn_ambiguous;
-
- if (ith_yychar == '=')
- {
- if (nth_token (3+i)->yychar == '{')
- return type_decl;
- continue;
- }
-
- /* Whatever it is, it looks like we're processing an expr. */
- return exp_decl;
- }
- }
- goto warn_ambiguous;
- }
-
- case ',':
- case ';':
- case '&':
- case '<':
- case '*':
- case ']':
- case ')':
- case '>':
- /* see if the next token looks like it wants to be part
- of a declaration list or an expression list. */
- {
- int i;
-
- /* Some heuristics: if we are inside a function definition,
- prefer the local declaration. */
- if (! global_bindings_p ())
- {
- if (IDENTIFIER_LOCAL_VALUE (name) == exp_decl)
- return exp_decl;
- if (IDENTIFIER_LOCAL_VALUE (name) != type_decl
- && IDENTIFIER_CLASS_VALUE (name) == exp_decl)
- return exp_decl;
- }
- /* If these symbols follow in a list, we know it's a list of
- expressions. */
- if (follows_identifier[nth_token (2)->yychar])
- return exp_decl;
-
- /* If we see a id&, or id&) the we are probably in an argument list. */
- if (ch=='&'
- && (nth_token (2)->yychar == ',' || nth_token (2)->yychar == ')'))
- return type_decl;
-
- /* Look for the first identifier or other distinguishing token
- we find in the next several tokens. */
- for (i = 0; i < 42; i++)
- {
- int ith_yychar;
-
- scan_tokens (3+i);
- ith_yychar = nth_token (2+i)->yychar;
-
- if (ith_yychar == IDENTIFIER)
- {
- tree as_type = lookup_name (nth_token (2+i)->yylval.ttype, 1);
- if (as_type && TREE_CODE (as_type) != TYPE_DECL)
- return exp_decl;
- /* An undeclared identifier or a typename means we're
- probably looking at a typename. */
- return type_decl;
- }
- else if (ith_yychar == EMPTY
- || follows_identifier[ith_yychar])
- return exp_decl;
- else if (follows_typename[ith_yychar])
- return type_decl;
- /* stmt or decl? We'll probably never know. */
- else if (ith_yychar == ';')
- goto warn_ambiguous;
- }
- goto warn_ambiguous;
- }
-
- default:
- if (follows_identifier[ch])
- return exp_decl;
- if (follows_typename[ch])
- return type_decl;
-
- /* Fall through... */
- warn_ambiguous:
- warning ("name `%s' could be type or expression; compiler assuming type",
- IDENTIFIER_POINTER (DECL_NAME (type_decl)));
- return type_decl;
- }
-}
-
-/* now returns decl_node */
-
-#if 0
-static tree
-hack_ptype()
-{
- /* when we get here, we know that [0] is a ptype and [1] is '<'.
- * now we loop over simple parameters. */
- struct token this_param;
- int n = 2;
- tree tplist = 0;
- tree tc;
- scan_tokens(n+1);
-
- while((this_param = *nth_token(n)).yychar != '>')
- {
- /* if it is a type, add it to the list */
- tree thistype;
-
- switch(this_param.yychar)
- {
- case IDENTIFIER:
- case TYPENAME:
- case TYPESPEC:
- break;
- default:
- return 0;
- }
-
- thistype = this_param.yylval.ttype;
- thistype = lookup_name(thistype, 1);
- thistype = TREE_TYPE (thistype);
-
- if (tplist)
- tplist = chainon (tplist, build_tree_list (NULL_TREE, thistype));
- else
- tplist = build_tree_list(NULL_TREE, thistype);
-
-
- /* then suck up the comma */
- n++;
- scan_tokens(n+1);
- this_param = *nth_token(n);
- if (this_param.yychar == ',')
- {
- n++;
- scan_tokens(n+1);
- continue;
- }
- if (this_param.yychar == '>')
- break;
- return 0;
- }
-
- /* once we're done, lookup_template_class -> identifier */
- tc = lookup_template_class (nth_token(0)->yylval.ttype,tplist);
- /* then lookup_name on that to get a type, if there is one */
- tc = lookup_name (tc, 1);
- if (tc)
- {
- int i;
- /* don't actually eat the trailing '>'... we can replace it! */
- for (i=0; i<n; i++)
- consume_token();
- /* IDENTIFIER_TYPE_VALUE (DECL_NAME (tc)) = */
- return DECL_NAME (tc);
- }
- return NULL_TREE;
-}
-#endif
-
-#if 0
-static tree
-hack_more_ids (n)
- int n;
-{
- /*
- * The recursion should probably do consume_tokens(), since once we've started
- * down an IDENTIFIER SCOPE ... chain, we don't need to back-track - we just
- * get as much as we can, make SCOPE_REF's out of it, and return it.
- */
- struct token this_iter, this2_iter;
- int tmp_y;
-
- scan_tokens(n+1);
- this_iter = *nth_token(n);
-
- tmp_y = nth_token(n)->yychar;
- if (tmp_y == IDENTIFIER || tmp_y == TYPENAME)
- {
- scan_tokens(n+2+2);
- if (nth_token(n+1)->yychar == SCOPE)
- {
- if (nth_token(n+1+2)->yychar == SCOPE)
- {
- tree hmi;
-
- consume_token(); /* last IDENTIFIER (this_iter) */
- consume_token(); /* last SCOPE */
- this2_iter = *nth_token(n);
-
- hmi = hack_more_ids (n);
-
- if (hmi)
- return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, hmi);
- consume_token(); /* last IDENTIFIER (this2_iter) */
- return build_parse_node (SCOPE_REF, this_iter.yylval.ttype,
- this2_iter.yylval.ttype);
- }
- else
- {
- /* consume_token(); */ /* last IDENTIFIER */
- /* leave whatever else we got */
- /* return this_iter.yylval.ttype; */
- return NULL_TREE;
- }
- }
- }
- return NULL_TREE; /* @@ may need to backtrack */
-}
-#else
-/* niklas@appli.se says: I didn't understand how the code above was intended
- * to work, so I rewrote it (also changed the interface a bit). This code
- * dives down an IDENTIFIER/TYPENAME SCOPE ... chain as long as the parsed
- * type prefix constitutes recognizable (by resolve_scope_to_name) types.
- * Interface changed like this:
- * 1. Takes an extra argument containing the name of the the type recognized
- * so far.
- * 2. Now returns the name of the type instead of a SCOPE_REF. */
-static tree
-hack_more_ids(n, outer)
- int n;
- tree outer;
-{
- int ch;
- tree type, val;
-
- scan_tokens (n + 2);
- if (nth_token (n + 1)->yychar != SCOPE
- || ((ch = nth_token (n + 2)->yychar) != IDENTIFIER && ch != TYPENAME))
- return NULL_TREE;
- val = build_parse_node (SCOPE_REF, outer, nth_token (n + 2)->yylval.ttype);
- type = resolve_scope_to_name (NULL_TREE, val);
- if (type == NULL_TREE)
- return NULL_TREE;
- consume_token ();
- consume_token ();
- val = hack_more_ids (n, type);
- if (! val)
- consume_token ();
- return val ? val : type;
-}
-#endif
-
-#if 0
-static struct token
-hack_scope ()
-{
- /* we've got a :: - what follows is either a global var or a type. */
- /* hmm, template names can be in the global scope too... */
- tree t1;
- struct token rt;
-
- scan_tokens(1);
- if (nth_token(1)->yychar == IDENTIFIER)
- {
- /* @@ this is probably not right, but doesn't get hit yet */
- t1 = build_parse_node (SCOPE_REF,
- NULL_TREE, /* to get "global" scope */
- hack_more_ids(0)); /* do some prefetching */
- rt.yylval.ttype = t1;
- rt.yychar = /*SCOPED_*/TYPENAME;
- return rt;
- }
- else
- {
- rt = *nth_token(0);
- consume_token();
- return rt;
- }
-}
-#endif
-
-/*
- * Generations:
- *
- * PINST: PTYPE { saved_arg_count = arg_count($1) }
- * '<' { arg_c = 0; } PARGS '>'
- * ;
- * PARG: TYPE
- * | VALUE
- * ;
- * (of course the arg counting doesn't work for recursion... Do it right.)
- * PARGS: PARG { assert(arg_c == saved_arg_count); }
- * | PARG ',' PARGS { arg_c++; }
- * ;
- * ATYPE: PINST
- * | TYPEID
- * ;
- * TYPE: ATYPE
- * | ATYPE { basetype = $1; } '::' TYPEKIDS
- * ;
- * TYPEKIDS: TYPE { assert ($1 is a member of basetype); }
- * | TYPEKIDS { basetype += $1} TYPE { assert( $3 is in basetype ); }
- * ;
- *
- *
- * state0: ; ATYPE
- * TYPE '<': ac = args($0), base = CALL state1, state3
- * TYPE '::': base=$0, state3
- * else return TYPE
- * state1: ; begin PARGS
- * if(ac < list length) punt
- * PARG ",": add to list, state1
- * PARG ">": add to list, return
- * else unravel
- * state3: ; begin TYPEKIDS
- * TYPE:
- */
-
-
-#ifdef SPEW_DEBUG
-/* debug_yychar takes a yychar (token number) value and prints its name. */
-static int
-debug_yychar (yy)
- int yy;
-{
- /* In cp-parse.y: */
- extern char *debug_yytranslate ();
-
- int i;
-
- if(yy<256) {
- fprintf (stderr, "<%d: %c >\n", yy, yy);
- return 0;
- }
- fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
- return 1;
-}
-
-#endif
diff --git a/gnu/gcc2/cc1plus/cp-tree.c b/gnu/gcc2/cc1plus/cp-tree.c
deleted file mode 100644
index 8728d645997a..000000000000
--- a/gnu/gcc2/cc1plus/cp-tree.c
+++ /dev/null
@@ -1,1706 +0,0 @@
-/* Language-dependent node constructors for parse phase of GNU compiler.
- Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-#include "config.h"
-#include <stdio.h>
-#include "obstack.h"
-#include "tree.h"
-#include "cp-tree.h"
-#include "flags.h"
-
-#define CEIL(x,y) (((x) + (y) - 1) / (y))
-
-/* Return nonzero if REF is an lvalue valid for this language.
- Lvalues can be assigned, unless they have TREE_READONLY.
- Lvalues can have their address taken, unless they have DECL_REGISTER. */
-
-int
-lvalue_p (ref)
- tree ref;
-{
- register enum tree_code code = TREE_CODE (ref);
-
- if (language_lvalue_valid (ref))
- switch (code)
- {
- /* preincrements and predecrements are valid lvals, provided
- what they refer to are valid lvals. */
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case COMPONENT_REF:
- return lvalue_p (TREE_OPERAND (ref, 0));
-
- case STRING_CST:
- return 1;
-
- case VAR_DECL:
- if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
- && DECL_LANG_SPECIFIC (ref)
- && DECL_IN_AGGR_P (ref))
- return 0;
- case INDIRECT_REF:
- case ARRAY_REF:
- case PARM_DECL:
- case RESULT_DECL:
- case ERROR_MARK:
- if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
- return 1;
- break;
-
- case TARGET_EXPR:
- case WITH_CLEANUP_EXPR:
- return 1;
-
- case CALL_EXPR:
- if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE
- /* unary_complex_lvalue knows how to deal with this case. */
- || TREE_ADDRESSABLE (TREE_TYPE (ref)))
- return 1;
- break;
-
- /* A currently unresolved scope ref. */
- case SCOPE_REF:
- my_friendly_abort (103);
- case OFFSET_REF:
- if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
- return 1;
- if (TREE_CODE (TREE_OPERAND (ref, 1)) == VAR_DECL)
- if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
- && DECL_LANG_SPECIFIC (ref)
- && DECL_IN_AGGR_P (ref))
- return 0;
- else
- return 1;
- break;
-
- case ADDR_EXPR:
- /* ANSI C++ June 5 1992 WP 5.4.14. The result of a cast to a
- reference is an lvalue. */
- if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
- return 1;
- break;
- }
- return 0;
-}
-
-/* Return nonzero if REF is an lvalue valid for this language;
- otherwise, print an error message and return zero. */
-
-int
-lvalue_or_else (ref, string)
- tree ref;
- char *string;
-{
- int win = lvalue_p (ref);
- if (! win)
- error ("invalid lvalue in %s", string);
- return win;
-}
-
-/* INIT is a CALL_EXPR which needs info about its target.
- TYPE is the type that this initialization should appear to have.
-
- Build an encapsulation of the initialization to perform
- and return it so that it can be processed by language-independent
- and language-specific expression expanders.
-
- If WITH_CLEANUP_P is nonzero, we build a cleanup for this expression.
- Otherwise, cleanups are not built here. For example, when building
- an initialization for a stack slot, since the called function handles
- the cleanup, we would not want to do it here. */
-tree
-build_cplus_new (type, init, with_cleanup_p)
- tree type;
- tree init;
- int with_cleanup_p;
-{
- tree slot = build (VAR_DECL, type);
- tree rval = build (NEW_EXPR, type,
- TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
- TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
- rval = build (TARGET_EXPR, type, slot, rval, 0);
- TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
-
- if (with_cleanup_p && TYPE_NEEDS_DESTRUCTOR (type))
- {
- rval = build (WITH_CLEANUP_EXPR, type, rval, 0,
- build_delete (TYPE_POINTER_TO (type),
- build_unary_op (ADDR_EXPR, slot, 0),
- integer_two_node,
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0));
- TREE_SIDE_EFFECTS (rval) = 1;
- }
- return rval;
-}
-
-/* Recursively search EXP for CALL_EXPRs that need cleanups and replace
- these CALL_EXPRs with tree nodes that will perform the cleanups. */
-
-tree
-break_out_cleanups (exp)
- tree exp;
-{
- tree tmp = exp;
-
- if (TREE_CODE (tmp) == CALL_EXPR
- && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp)))
- return build_cplus_new (TREE_TYPE (tmp), tmp, 1);
-
- while (TREE_CODE (tmp) == NOP_EXPR
- || TREE_CODE (tmp) == CONVERT_EXPR
- || TREE_CODE (tmp) == NON_LVALUE_EXPR)
- {
- if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR
- && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0))))
- {
- TREE_OPERAND (tmp, 0)
- = build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),
- TREE_OPERAND (tmp, 0), 1);
- break;
- }
- else
- tmp = TREE_OPERAND (tmp, 0);
- }
- return exp;
-}
-
-/* Recursively perform a preorder search EXP for CALL_EXPRs, making
- copies where they are found. Returns a deep copy all nodes transitively
- containing CALL_EXPRs. */
-
-tree
-break_out_calls (exp)
- tree exp;
-{
- register tree t1, t2;
- register enum tree_code code;
- register int changed = 0;
- register int i;
-
- if (exp == NULL_TREE)
- return exp;
-
- code = TREE_CODE (exp);
-
- if (code == CALL_EXPR)
- return copy_node (exp);
-
- /* Don't try and defeat a save_expr, as it should only be done once. */
- if (code == SAVE_EXPR)
- return exp;
-
- switch (TREE_CODE_CLASS (code))
- {
- default:
- abort ();
-
- case 'c': /* a constant */
- case 't': /* a type node */
- case 'x': /* something random, like an identifier or an ERROR_MARK. */
- return exp;
-
- case 'd': /* A decl node */
- t1 = break_out_calls (DECL_INITIAL (exp));
- if (t1 != DECL_INITIAL (exp))
- {
- exp = copy_node (exp);
- DECL_INITIAL (exp) = t1;
- }
- return exp;
-
- case 'b': /* A block node */
- {
- /* Don't know how to handle these correctly yet. Must do a
- break_out_calls on all DECL_INITIAL values for local variables,
- and also break_out_calls on all sub-blocks and sub-statements. */
- abort ();
- }
- return exp;
-
- case 'e': /* an expression */
- case 'r': /* a reference */
- case 's': /* an expression with side effects */
- for (i = tree_code_length[(int) code] - 1; i >= 0; i--)
- {
- t1 = break_out_calls (TREE_OPERAND (exp, i));
- if (t1 != TREE_OPERAND (exp, i))
- {
- if (changed++ == 0)
- exp = copy_node (exp);
- TREE_OPERAND (exp, i) = t1;
- }
- }
- return exp;
-
- case '<': /* a comparison expression */
- case '2': /* a binary arithmetic expression */
- t2 = break_out_calls (TREE_OPERAND (exp, 1));
- if (t2 != TREE_OPERAND (exp, 1))
- changed = 1;
- case '1': /* a unary arithmetic expression */
- t1 = break_out_calls (TREE_OPERAND (exp, 0));
- if (t1 != TREE_OPERAND (exp, 0))
- changed = 1;
- if (changed)
- {
- if (tree_code_length[(int) code] == 1)
- return build1 (code, TREE_TYPE (exp), t1);
- else
- return build (code, TREE_TYPE (exp), t1, t2);
- }
- return exp;
- }
-
-}
-
-extern struct obstack *current_obstack;
-extern struct obstack permanent_obstack, class_obstack;
-extern struct obstack *saveable_obstack;
-
-/* Here is how primitive or already-canonicalized types' hash
- codes are made. MUST BE CONSISTENT WITH tree.c !!! */
-#define TYPE_HASH(TYPE) ((HOST_WIDE_INT) (TYPE) & 0777777)
-
-/* Construct, lay out and return the type of methods belonging to class
- BASETYPE and whose arguments are described by ARGTYPES and whose values
- are described by RETTYPE. If each type exists already, reuse it. */
-tree
-build_cplus_method_type (basetype, rettype, argtypes)
- tree basetype, rettype, argtypes;
-{
- register tree t;
- tree ptype = build_pointer_type (basetype);
- int hashcode;
-
- /* Make a node of the sort we want. */
- t = make_node (METHOD_TYPE);
-
- TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
- TREE_TYPE (t) = rettype;
-#if 0
- /* it is wrong to flag the object the pointer points to as readonly
- when flag_this_is_variable is 0. */
- ptype = build_type_variant (ptype, flag_this_is_variable <= 0, 0);
-#else
- ptype = build_type_variant (ptype, 0, 0);
-#endif
- /* The actual arglist for this function includes a "hidden" argument
- which is "this". Put it into the list of argument types. */
-
- TYPE_ARG_TYPES (t) = tree_cons (NULL, ptype, argtypes);
-
- /* If we already have such a type, use the old one and free this one.
- Note that it also frees up the above cons cell if found. */
- hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);
- t = type_hash_canon (hashcode, t);
-
- if (TYPE_SIZE (t) == 0)
- layout_type (t);
-
- return t;
-}
-
-tree
-build_cplus_staticfn_type (basetype, rettype, argtypes)
- tree basetype, rettype, argtypes;
-{
- register tree t;
- int hashcode;
-
- /* Make a node of the sort we want. */
- t = make_node (FUNCTION_TYPE);
-
- TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
- TREE_TYPE (t) = rettype;
-
- /* The actual arglist for this function includes a "hidden" argument
- which is "this". Put it into the list of argument types. */
-
- TYPE_ARG_TYPES (t) = argtypes;
-
- /* If we already have such a type, use the old one and free this one.
- Note that it also frees up the above cons cell if found. */
- hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);
- t = type_hash_canon (hashcode, t);
-
- if (TYPE_SIZE (t) == 0)
- layout_type (t);
-
- return t;
-}
-
-tree
-build_cplus_array_type (elt_type, index_type)
- tree elt_type;
- tree index_type;
-{
- register struct obstack *ambient_obstack = current_obstack;
- register struct obstack *ambient_saveable_obstack = saveable_obstack;
- tree t;
-
- /* We need a new one. If both ELT_TYPE and INDEX_TYPE are permanent,
- make this permanent too. */
- if (TREE_PERMANENT (elt_type)
- && (index_type == 0 || TREE_PERMANENT (index_type)))
- {
- current_obstack = &permanent_obstack;
- saveable_obstack = &permanent_obstack;
- }
-
- t = build_array_type (elt_type, index_type);
-
- /* Push these needs up so that initialization takes place
- more easily. */
- TYPE_NEEDS_CONSTRUCTING (t) = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
- TYPE_NEEDS_DESTRUCTOR (t) = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
- current_obstack = ambient_obstack;
- saveable_obstack = ambient_saveable_obstack;
- return t;
-}
-
-/* Add OFFSET to all base types of T.
-
- OFFSET, which is a type offset, is number of bytes.
-
- Note that we don't have to worry about having two paths to the
- same base type, since this type owns its association list. */
-void
-propagate_binfo_offsets (binfo, offset)
- tree binfo;
- tree offset;
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; /* note increment is done in the loop. */)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (TREE_VIA_VIRTUAL (base_binfo))
- i += 1;
- else
- {
- int j;
- tree base_binfos = BINFO_BASETYPES (base_binfo);
- tree delta;
-
- for (j = i+1; j < n_baselinks; j++)
- if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j)))
- {
- /* The next basetype offset must take into account the space
- between the classes, not just the size of each class. */
- delta = size_binop (MINUS_EXPR,
- BINFO_OFFSET (TREE_VEC_ELT (binfos, j)),
- BINFO_OFFSET (base_binfo));
- break;
- }
-
-#if 0
- if (BINFO_OFFSET_ZEROP (base_binfo))
- BINFO_OFFSET (base_binfo) = offset;
- else
- BINFO_OFFSET (base_binfo)
- = size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), offset);
-#else
- BINFO_OFFSET (base_binfo) = offset;
-#endif
- if (base_binfos)
- {
- int k;
- tree chain = NULL_TREE;
-
- /* Now unshare the structure beneath BASE_BINFO. */
- for (k = TREE_VEC_LENGTH (base_binfos)-1;
- k >= 0; k--)
- {
- tree base_base_binfo = TREE_VEC_ELT (base_binfos, k);
- if (! TREE_VIA_VIRTUAL (base_base_binfo))
- TREE_VEC_ELT (base_binfos, k)
- = make_binfo (BINFO_OFFSET (base_base_binfo),
- BINFO_TYPE (base_base_binfo),
- BINFO_VTABLE (base_base_binfo),
- BINFO_VIRTUALS (base_base_binfo),
- chain);
- chain = TREE_VEC_ELT (base_binfos, k);
- TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
- TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
- }
- /* Now propagate the offset to the base types. */
- propagate_binfo_offsets (base_binfo, offset);
- }
-
- /* Go to our next class that counts for offset propagation. */
- i = j;
- if (i < n_baselinks)
- offset = size_binop (PLUS_EXPR, offset, delta);
- }
- }
-}
-
-/* Compute the actual offsets that our virtual base classes
- will have *for this type*. This must be performed after
- the fields are laid out, since virtual baseclasses must
- lay down at the end of the record.
-
- Returns the maximum number of virtual functions any of the virtual
- baseclasses provide. */
-int
-layout_vbasetypes (rec, max)
- tree rec;
- int max;
-{
- /* Get all the virtual base types that this type uses.
- The TREE_VALUE slot holds the virtual baseclass type. */
- tree vbase_types = get_vbase_types (rec);
-
-#ifdef STRUCTURE_SIZE_BOUNDARY
- unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));
-#else
- unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
-#endif
-
- /* Record size so far is CONST_SIZE + VAR_SIZE bits,
- where CONST_SIZE is an integer
- and VAR_SIZE is a tree expression.
- If VAR_SIZE is null, the size is just CONST_SIZE.
- Naturally we try to avoid using VAR_SIZE. */
- register unsigned const_size = 0;
- register tree var_size = 0;
- int nonvirtual_const_size;
- tree nonvirtual_var_size;
-
- CLASSTYPE_VBASECLASSES (rec) = vbase_types;
-
- if (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST)
- const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec));
- else
- var_size = TYPE_SIZE (rec);
-
- nonvirtual_const_size = const_size;
- nonvirtual_var_size = var_size;
-
- while (vbase_types)
- {
- tree basetype = BINFO_TYPE (vbase_types);
- tree offset;
-
- if (const_size == 0)
- offset = integer_zero_node;
- else
- offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
-
- if (CLASSTYPE_VSIZE (basetype) > max)
- max = CLASSTYPE_VSIZE (basetype);
- BINFO_OFFSET (vbase_types) = offset;
-
- if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST)
- const_size += MAX (record_align,
- TREE_INT_CST_LOW (TYPE_SIZE (basetype))
- - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
- else if (var_size == 0)
- var_size = TYPE_SIZE (basetype);
- else
- var_size = size_binop (PLUS_EXPR, var_size, TYPE_SIZE (basetype));
-
- vbase_types = TREE_CHAIN (vbase_types);
- }
-
- if (const_size != nonvirtual_const_size)
- {
- CLASSTYPE_VBASE_SIZE (rec)
- = size_int (const_size - nonvirtual_const_size);
- TYPE_SIZE (rec) = size_int (const_size);
- }
-
- /* Now propagate offset information throughout the lattice
- under the vbase type. */
- for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types;
- vbase_types = TREE_CHAIN (vbase_types))
- {
- tree base_binfos = BINFO_BASETYPES (vbase_types);
-
- if (base_binfos)
- {
- tree chain = NULL_TREE;
- int j;
- /* Now unshare the structure beneath BASE_BINFO. */
-
- for (j = TREE_VEC_LENGTH (base_binfos)-1;
- j >= 0; j--)
- {
- tree base_base_binfo = TREE_VEC_ELT (base_binfos, j);
- if (! TREE_VIA_VIRTUAL (base_base_binfo))
- TREE_VEC_ELT (base_binfos, j)
- = make_binfo (BINFO_OFFSET (base_base_binfo),
- BINFO_TYPE (base_base_binfo),
- BINFO_VTABLE (base_base_binfo),
- BINFO_VIRTUALS (base_base_binfo),
- chain);
- chain = TREE_VEC_ELT (base_binfos, j);
- TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
- TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
- }
-
- propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
- }
- }
-
- return max;
-}
-
-/* Lay out the base types of a record type, REC.
- Tentatively set the size and alignment of REC
- according to the base types alone.
-
- Offsets for immediate nonvirtual baseclasses are also computed here.
-
- Returns list of virtual base classes in a FIELD_DECL chain. */
-tree
-layout_basetypes (rec, binfos)
- tree rec, binfos;
-{
- /* Chain to hold all the new FIELD_DECLs which point at virtual
- base classes. */
- tree vbase_decls = NULL_TREE;
-
-#ifdef STRUCTURE_SIZE_BOUNDARY
- unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));
-#else
- unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
-#endif
-
- /* Record size so far is CONST_SIZE + VAR_SIZE bits,
- where CONST_SIZE is an integer
- and VAR_SIZE is a tree expression.
- If VAR_SIZE is null, the size is just CONST_SIZE.
- Naturally we try to avoid using VAR_SIZE. */
- register unsigned const_size = 0;
- register tree var_size = 0;
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Handle basetypes almost like fields, but record their
- offsets differently. */
-
- for (i = 0; i < n_baseclasses; i++)
- {
- int inc, desired_align, int_vbase_size;
- register tree base_binfo = TREE_VEC_ELT (binfos, i);
- register tree basetype = BINFO_TYPE (base_binfo);
- tree decl, offset;
-
- if (TYPE_SIZE (basetype) == 0)
- {
-#if 0
- /* This error is now reported in xref_tag, thus giving better
- location information. */
- error_with_aggr_type (base_binfo,
- "base class `%s' has incomplete type");
-
- TREE_VIA_PUBLIC (base_binfo) = 1;
- TREE_VIA_PROTECTED (base_binfo) = 0;
- TREE_VIA_VIRTUAL (base_binfo) = 0;
-
- /* Should handle this better so that
-
- class A;
- class B: private A { virtual void F(); };
-
- does not dump core when compiled. */
- my_friendly_abort (121);
-#endif
- continue;
- }
-
- /* All basetypes are recorded in the association list of the
- derived type. */
-
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- int j;
- char *name = (char *)alloca (TYPE_NAME_LENGTH (basetype)
- + sizeof (VBASE_NAME) + 1);
-
- /* The offset for a virtual base class is only used in computing
- virtual function tables and for initializing virtual base
- pointers. It is built once `get_vbase_types' is called. */
-
- /* If this basetype can come from another vbase pointer
- without an additional indirection, we will share
- that pointer. If an indirection is involved, we
- make our own pointer. */
- for (j = 0; j < n_baseclasses; j++)
- {
- tree other_base_binfo = TREE_VEC_ELT (binfos, j);
- if (! TREE_VIA_VIRTUAL (other_base_binfo)
- && binfo_member (basetype,
- CLASSTYPE_VBASECLASSES (BINFO_TYPE (other_base_binfo))))
- goto got_it;
- }
- sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype));
- decl = build_lang_decl (FIELD_DECL, get_identifier (name),
- build_pointer_type (basetype));
- /* If you change any of the below, take a look at all the
- other VFIELD_BASEs and VTABLE_BASEs in the code, and change
- them too. */
- DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE);
- DECL_VIRTUAL_P (decl) = 1;
- DECL_FIELD_CONTEXT (decl) = rec;
- DECL_CLASS_CONTEXT (decl) = rec;
- DECL_FCONTEXT (decl) = basetype;
- DECL_FIELD_SIZE (decl) = 0;
- DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node);
- TREE_CHAIN (decl) = vbase_decls;
- BINFO_VPTR_FIELD (base_binfo) = decl;
- vbase_decls = decl;
-
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE)
- {
- warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0),
- "destructor `%s' non-virtual");
- warning ("in inheritance relationship `%s: virtual %s'",
- TYPE_NAME_STRING (rec),
- TYPE_NAME_STRING (basetype));
- }
- got_it:
- /* The space this decl occupies has already been accounted for. */
- continue;
- }
-
- if (const_size == 0)
- offset = integer_zero_node;
- else
- {
- /* Give each base type the alignment it wants. */
- const_size = CEIL (const_size, TYPE_ALIGN (basetype))
- * TYPE_ALIGN (basetype);
- offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
-
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE)
- {
- warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0),
- "destructor `%s' non-virtual");
- warning ("in inheritance relationship `%s:%s %s'",
- TYPE_NAME_STRING (rec),
- TREE_VIA_VIRTUAL (base_binfo) ? " virtual" : "",
- TYPE_NAME_STRING (basetype));
- }
- }
- BINFO_OFFSET (base_binfo) = offset;
- if (CLASSTYPE_VSIZE (basetype))
- {
- BINFO_VTABLE (base_binfo) = TYPE_BINFO_VTABLE (basetype);
- BINFO_VIRTUALS (base_binfo) = TYPE_BINFO_VIRTUALS (basetype);
- }
- TREE_CHAIN (base_binfo) = TYPE_BINFO (rec);
- TYPE_BINFO (rec) = base_binfo;
-
- /* Add only the amount of storage not present in
- the virtual baseclasses. */
-
- int_vbase_size = TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype));
- if (TREE_INT_CST_LOW (TYPE_SIZE (basetype)) > int_vbase_size)
- {
- inc = MAX (record_align,
- (TREE_INT_CST_LOW (TYPE_SIZE (basetype))
- - int_vbase_size));
-
- /* Record must have at least as much alignment as any field. */
- desired_align = TYPE_ALIGN (basetype);
- record_align = MAX (record_align, desired_align);
-
- const_size += inc;
- }
- }
-
- if (const_size)
- CLASSTYPE_SIZE (rec) = size_int (const_size);
- else
- CLASSTYPE_SIZE (rec) = integer_zero_node;
- CLASSTYPE_ALIGN (rec) = record_align;
-
- return vbase_decls;
-}
-
-/* Hashing of lists so that we don't make duplicates.
- The entry point is `list_hash_canon'. */
-
-/* Each hash table slot is a bucket containing a chain
- of these structures. */
-
-struct list_hash
-{
- struct list_hash *next; /* Next structure in the bucket. */
- int hashcode; /* Hash code of this list. */
- tree list; /* The list recorded here. */
-};
-
-/* Now here is the hash table. When recording a list, it is added
- to the slot whose index is the hash code mod the table size.
- Note that the hash table is used for several kinds of lists.
- While all these live in the same table, they are completely independent,
- and the hash code is computed differently for each of these. */
-
-#define TYPE_HASH_SIZE 59
-struct list_hash *list_hash_table[TYPE_HASH_SIZE];
-
-/* Compute a hash code for a list (chain of TREE_LIST nodes
- with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the
- TREE_COMMON slots), by adding the hash codes of the individual entries. */
-
-int
-list_hash (list)
- tree list;
-{
- register int hashcode = 0;
-
- if (TREE_CHAIN (list))
- hashcode += TYPE_HASH (TREE_CHAIN (list));
-
- if (TREE_VALUE (list))
- hashcode += TYPE_HASH (TREE_VALUE (list));
- else
- hashcode += 1007;
- if (TREE_PURPOSE (list))
- hashcode += TYPE_HASH (TREE_PURPOSE (list));
- else
- hashcode += 1009;
- return hashcode;
-}
-
-/* Look in the type hash table for a type isomorphic to TYPE.
- If one is found, return it. Otherwise return 0. */
-
-tree
-list_hash_lookup (hashcode, list)
- int hashcode;
- tree list;
-{
- register struct list_hash *h;
- for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
- if (h->hashcode == hashcode
- && TREE_VIA_VIRTUAL (h->list) == TREE_VIA_VIRTUAL (list)
- && TREE_VIA_PUBLIC (h->list) == TREE_VIA_PUBLIC (list)
- && TREE_VIA_PROTECTED (h->list) == TREE_VIA_PROTECTED (list)
- && TREE_PURPOSE (h->list) == TREE_PURPOSE (list)
- && TREE_VALUE (h->list) == TREE_VALUE (list)
- && TREE_CHAIN (h->list) == TREE_CHAIN (list))
- {
- my_friendly_assert (TREE_TYPE (h->list) == TREE_TYPE (list), 299);
- return h->list;
- }
- return 0;
-}
-
-/* Add an entry to the list-hash-table
- for a list TYPE whose hash code is HASHCODE. */
-
-void
-list_hash_add (hashcode, list)
- int hashcode;
- tree list;
-{
- register struct list_hash *h;
-
- h = (struct list_hash *) obstack_alloc (&class_obstack, sizeof (struct list_hash));
- h->hashcode = hashcode;
- h->list = list;
- h->next = list_hash_table[hashcode % TYPE_HASH_SIZE];
- list_hash_table[hashcode % TYPE_HASH_SIZE] = h;
-}
-
-/* Given TYPE, and HASHCODE its hash code, return the canonical
- object for an identical list if one already exists.
- Otherwise, return TYPE, and record it as the canonical object
- if it is a permanent object.
-
- To use this function, first create a list of the sort you want.
- Then compute its hash code from the fields of the list that
- make it different from other similar lists.
- Then call this function and use the value.
- This function frees the list you pass in if it is a duplicate. */
-
-/* Set to 1 to debug without canonicalization. Never set by program. */
-int debug_no_list_hash = 0;
-
-tree
-list_hash_canon (hashcode, list)
- int hashcode;
- tree list;
-{
- tree t1;
-
- if (debug_no_list_hash)
- return list;
-
- t1 = list_hash_lookup (hashcode, list);
- if (t1 != 0)
- {
- obstack_free (&class_obstack, list);
- return t1;
- }
-
- /* If this is a new list, record it for later reuse. */
- list_hash_add (hashcode, list);
-
- return list;
-}
-
-tree
-hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
- int via_public, via_virtual, via_protected;
- tree purpose, value, chain;
-{
- struct obstack *ambient_obstack = current_obstack;
- tree t;
- int hashcode;
-
- current_obstack = &class_obstack;
- t = tree_cons (purpose, value, chain);
- TREE_VIA_PUBLIC (t) = via_public;
- TREE_VIA_PROTECTED (t) = via_protected;
- TREE_VIA_VIRTUAL (t) = via_virtual;
- hashcode = list_hash (t);
- t = list_hash_canon (hashcode, t);
- current_obstack = ambient_obstack;
- return t;
-}
-
-/* Constructor for hashed lists. */
-tree
-hash_tree_chain (value, chain)
- tree value, chain;
-{
- struct obstack *ambient_obstack = current_obstack;
- tree t;
- int hashcode;
-
- current_obstack = &class_obstack;
- t = tree_cons (NULL_TREE, value, chain);
- hashcode = list_hash (t);
- t = list_hash_canon (hashcode, t);
- current_obstack = ambient_obstack;
- return t;
-}
-
-/* Similar, but used for concatenating two lists. */
-tree
-hash_chainon (list1, list2)
- tree list1, list2;
-{
- if (list2 == 0)
- return list1;
- if (list1 == 0)
- return list2;
- if (TREE_CHAIN (list1) == NULL_TREE)
- return hash_tree_chain (TREE_VALUE (list1), list2);
- return hash_tree_chain (TREE_VALUE (list1),
- hash_chainon (TREE_CHAIN (list1), list2));
-}
-
-tree
-get_decl_list (value)
- tree value;
-{
- tree list = NULL_TREE;
-
- if (TREE_CODE (value) == IDENTIFIER_NODE)
- {
- list = IDENTIFIER_AS_LIST (value);
- if (list != NULL_TREE
- && (TREE_CODE (list) != TREE_LIST
- || TREE_VALUE (list) != value))
- list = NULL_TREE;
- else if (IDENTIFIER_HAS_TYPE_VALUE (value)
- && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
- {
- tree type = IDENTIFIER_TYPE_VALUE (value);
- if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
- CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE, value, NULL_TREE);
- list = CLASSTYPE_ID_AS_LIST (type);
- }
- }
- else if (TREE_CODE (value) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (value))
- list = CLASSTYPE_AS_LIST (value);
-
- if (list != NULL_TREE)
- {
- my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 301);
- return list;
- }
-
- return build_decl_list (NULL_TREE, value);
-}
-
-/* Look in the type hash table for a type isomorphic to
- `build_tree_list (NULL_TREE, VALUE)'.
- If one is found, return it. Otherwise return 0. */
-
-tree
-list_hash_lookup_or_cons (value)
- tree value;
-{
- register int hashcode = TYPE_HASH (value);
- register struct list_hash *h;
- struct obstack *ambient_obstack;
- tree list = NULL_TREE;
-
- if (TREE_CODE (value) == IDENTIFIER_NODE)
- {
- list = IDENTIFIER_AS_LIST (value);
- if (list != NULL_TREE
- && (TREE_CODE (list) != TREE_LIST
- || TREE_VALUE (list) != value))
- list = NULL_TREE;
- else if (IDENTIFIER_HAS_TYPE_VALUE (value)
- && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
- {
- /* If the type name and constructor name are different, don't
- write constructor name into type. */
- if (identifier_typedecl_value (value)
- && identifier_typedecl_value (value) != constructor_name (value))
- list = tree_cons (NULL_TREE, value, NULL_TREE);
- else
- {
- tree type = IDENTIFIER_TYPE_VALUE (value);
- if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
- CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE, value,
- NULL_TREE);
- list = CLASSTYPE_ID_AS_LIST (type);
- }
- }
- }
- else if (TREE_CODE (value) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (TREE_TYPE (value)))
- list = CLASSTYPE_ID_AS_LIST (TREE_TYPE (value));
- else if (TREE_CODE (value) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (value))
- list = CLASSTYPE_AS_LIST (value);
-
- if (list != NULL_TREE)
- {
- my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 302);
- return list;
- }
-
- if (debug_no_list_hash)
- return hash_tree_chain (value, NULL_TREE);
-
- for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
- if (h->hashcode == hashcode
- && TREE_VIA_VIRTUAL (h->list) == 0
- && TREE_VIA_PUBLIC (h->list) == 0
- && TREE_VIA_PROTECTED (h->list) == 0
- && TREE_PURPOSE (h->list) == 0
- && TREE_VALUE (h->list) == value)
- {
- my_friendly_assert (TREE_TYPE (h->list) == 0, 303);
- my_friendly_assert (TREE_CHAIN (h->list) == 0, 304);
- return h->list;
- }
-
- ambient_obstack = current_obstack;
- current_obstack = &class_obstack;
- list = build_tree_list (NULL_TREE, value);
- list_hash_add (hashcode, list);
- current_obstack = ambient_obstack;
- return list;
-}
-
-/* Build an association between TYPE and some parameters:
-
- OFFSET is the offset added to `this' to convert it to a pointer
- of type `TYPE *'
-
- VTABLE is the virtual function table with which to initialize
- sub-objects of type TYPE.
-
- VIRTUALS are the virtual functions sitting in VTABLE.
-
- CHAIN are more associations we must retain. */
-
-tree
-make_binfo (offset, type, vtable, virtuals, chain)
- tree offset, type;
- tree vtable, virtuals;
- tree chain;
-{
- tree binfo = make_tree_vec (6);
- tree old_binfo = TYPE_BINFO (type);
- tree last;
-
- TREE_CHAIN (binfo) = chain;
- if (chain)
- TREE_USED (binfo) = TREE_USED (chain);
-
- TREE_TYPE (binfo) = TYPE_MAIN_VARIANT (type);
- BINFO_OFFSET (binfo) = offset;
- BINFO_VTABLE (binfo) = vtable;
- BINFO_VIRTUALS (binfo) = virtuals;
- BINFO_VPTR_FIELD (binfo) = NULL_TREE;
-
- last = binfo;
- if (old_binfo != NULL_TREE
- && BINFO_BASETYPES (old_binfo) != NULL_TREE)
- {
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
- tree binfos = TYPE_BINFO_BASETYPES (type);
-
- BINFO_BASETYPES (binfo) = make_tree_vec (n_baseclasses);
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree old_base_binfo = old_binfo ? BINFO_BASETYPE (old_binfo, i) : 0;
- BINFO_BASETYPE (binfo, i) = base_binfo;
- if (old_binfo)
- {
- TREE_VIA_PUBLIC (base_binfo) = TREE_VIA_PUBLIC (old_base_binfo);
- TREE_VIA_PROTECTED (base_binfo) = TREE_VIA_PROTECTED (old_base_binfo);
- TREE_VIA_VIRTUAL (base_binfo) = TREE_VIA_VIRTUAL (old_base_binfo);
- }
- }
- }
- return binfo;
-}
-
-tree
-copy_binfo (list)
- tree list;
-{
- tree binfo = copy_list (list);
- tree rval = binfo;
- while (binfo)
- {
- TREE_USED (binfo) = 0;
- if (BINFO_BASETYPES (binfo))
- BINFO_BASETYPES (binfo) = copy_node (BINFO_BASETYPES (binfo));
- binfo = TREE_CHAIN (binfo);
- }
- return rval;
-}
-
-/* Return the binfo value for ELEM in TYPE. */
-
-tree
-binfo_value (elem, type)
- tree elem;
- tree type;
-{
- if (get_base_distance (elem, type, 0, (tree *)0) == -2)
- compiler_error ("base class `%s' ambiguous in binfo_value",
- TYPE_NAME_STRING (elem));
- if (elem == type)
- return TYPE_BINFO (type);
- return get_binfo (elem, type, 0);
-}
-
-tree
-reverse_path (path)
- tree path;
-{
- register tree prev = 0, tmp, next;
- for (tmp = path; tmp; tmp = next)
- {
- next = BINFO_INHERITANCE_CHAIN (tmp);
- BINFO_INHERITANCE_CHAIN (tmp) = prev;
- prev = tmp;
- }
- return prev;
-}
-
-tree
-virtual_member (elem, list)
- tree elem;
- tree list;
-{
- tree t;
- tree rval, nval;
-
- for (t = list; t; t = TREE_CHAIN (t))
- if (elem == BINFO_TYPE (t))
- return t;
- rval = 0;
- for (t = list; t; t = TREE_CHAIN (t))
- {
- tree binfos = BINFO_BASETYPES (t);
- int i;
-
- if (binfos != NULL_TREE)
- for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
- {
- nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
- if (nval)
- {
- if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval))
- my_friendly_abort (104);
- rval = nval;
- }
- }
- }
- return rval;
-}
-
-/* Return the offset (as an INTEGER_CST) for ELEM in LIST.
- INITIAL_OFFSET is the value to add to the offset that ELEM's
- binfo entry in LIST provides.
-
- Returns NULL if ELEM does not have an binfo value in LIST. */
-
-tree
-virtual_offset (elem, list, initial_offset)
- tree elem;
- tree list;
- tree initial_offset;
-{
- tree vb, offset;
- tree rval, nval;
-
- for (vb = list; vb; vb = TREE_CHAIN (vb))
- if (elem == BINFO_TYPE (vb))
- return size_binop (PLUS_EXPR, initial_offset, BINFO_OFFSET (vb));
- rval = 0;
- for (vb = list; vb; vb = TREE_CHAIN (vb))
- {
- tree binfos = BINFO_BASETYPES (vb);
- int i;
-
- if (binfos == NULL_TREE)
- continue;
-
- for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
- {
- nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
- if (nval)
- {
- if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval))
- my_friendly_abort (105);
- offset = BINFO_OFFSET (vb);
- rval = nval;
- }
- }
- }
- if (rval == NULL_TREE)
- return rval;
- return size_binop (PLUS_EXPR, offset, BINFO_OFFSET (rval));
-}
-
-void
-debug_binfo (elem)
- tree elem;
-{
- int i;
- tree virtuals;
-
- fprintf (stderr, "type \"%s\"; offset = %d\n",
- TYPE_NAME_STRING (BINFO_TYPE (elem)),
- TREE_INT_CST_LOW (BINFO_OFFSET (elem)));
- fprintf (stderr, "vtable type:\n");
- debug_tree (BINFO_TYPE (elem));
- if (BINFO_VTABLE (elem))
- fprintf (stderr, "vtable decl \"%s\"\n", IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem))));
- else
- fprintf (stderr, "no vtable decl yet\n");
- fprintf (stderr, "virtuals:\n");
- virtuals = BINFO_VIRTUALS (elem);
- if (virtuals != 0)
- {
- virtuals = TREE_CHAIN (virtuals);
- if (flag_dossier)
- virtuals = TREE_CHAIN (virtuals);
- }
- i = 1;
- while (virtuals)
- {
- tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
- fprintf (stderr, "%s [%d =? %d]\n",
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
- i, TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
- virtuals = TREE_CHAIN (virtuals);
- i += 1;
- }
-}
-
-/* Return the length of a chain of nodes chained through DECL_CHAIN.
- We expect a null pointer to mark the end of the chain.
- This is the Lisp primitive `length'. */
-
-int
-decl_list_length (t)
- tree t;
-{
- register tree tail;
- register int len = 0;
-
- my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL, 300);
- for (tail = t; tail; tail = DECL_CHAIN (tail))
- len++;
-
- return len;
-}
-
-tree
-fnaddr_from_vtable_entry (entry)
- tree entry;
-{
- return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
-}
-
-void
-set_fnaddr_from_vtable_entry (entry, value)
- tree entry, value;
-{
- TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))) = value;
-}
-
-tree
-function_arg_chain (t)
- tree t;
-{
- return TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (t)));
-}
-
-int
-promotes_to_aggr_type (t, code)
- tree t;
- enum tree_code code;
-{
- if (TREE_CODE (t) == code)
- t = TREE_TYPE (t);
- return IS_AGGR_TYPE (t);
-}
-
-int
-is_aggr_type_2 (t1, t2)
- tree t1, t2;
-{
- if (TREE_CODE (t1) != TREE_CODE (t2))
- return 0;
- return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
-}
-
-/* Give message using types TYPE1 and TYPE2 as arguments.
- PFN is the function which will print the message;
- S is the format string for PFN to use. */
-void
-message_2_types (pfn, s, type1, type2)
- void (*pfn) ();
- char *s;
- tree type1, type2;
-{
- tree name1 = TYPE_NAME (type1);
- tree name2 = TYPE_NAME (type2);
- if (TREE_CODE (name1) == TYPE_DECL)
- name1 = DECL_NAME (name1);
- if (TREE_CODE (name2) == TYPE_DECL)
- name2 = DECL_NAME (name2);
- (*pfn) (s, IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2));
-}
-
-#define PRINT_RING_SIZE 4
-
-char *
-lang_printable_name (decl)
- tree decl;
-{
- static tree decl_ring[PRINT_RING_SIZE];
- static char *print_ring[PRINT_RING_SIZE];
- static int ring_counter;
- int i;
-
- if (TREE_CODE (decl) != FUNCTION_DECL
- || DECL_LANG_SPECIFIC (decl) == 0)
- {
- if (DECL_NAME (decl))
- {
- if (THIS_NAME_P (DECL_NAME (decl)))
- return "this";
- return IDENTIFIER_POINTER (DECL_NAME (decl));
- }
- return "((anonymous))";
- }
-
- /* See if this print name is lying around. */
- for (i = 0; i < PRINT_RING_SIZE; i++)
- if (decl_ring[i] == decl)
- /* yes, so return it. */
- return print_ring[i];
-
- if (++ring_counter == PRINT_RING_SIZE)
- ring_counter = 0;
-
- if (current_function_decl != NULL_TREE)
- {
- if (decl_ring[ring_counter] == current_function_decl)
- ring_counter += 1;
- if (ring_counter == PRINT_RING_SIZE)
- ring_counter = 0;
- if (decl_ring[ring_counter] == current_function_decl)
- my_friendly_abort (106);
- }
-
- if (print_ring[ring_counter])
- free (print_ring[ring_counter]);
-
- {
- int print_ret_type_p
- = (!DECL_CONSTRUCTOR_P (decl)
- && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
-
- char *name = (char *)fndecl_as_string (0, decl, print_ret_type_p);
- print_ring[ring_counter] = (char *)malloc (strlen (name) + 1);
- strcpy (print_ring[ring_counter], name);
- decl_ring[ring_counter] = decl;
- }
- return print_ring[ring_counter];
-}
-
-/* Comparison function for sorting identifiers in RAISES lists.
- Note that because IDENTIFIER_NODEs are unique, we can sort
- them by address, saving an indirection. */
-static int
-id_cmp (p1, p2)
- tree *p1, *p2;
-{
- return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2);
-}
-
-/* Build the FUNCTION_TYPE or METHOD_TYPE which may raise exceptions
- listed in RAISES. */
-tree
-build_exception_variant (ctype, type, raises)
- tree ctype, type;
- tree raises;
-{
- int i;
- tree v = TYPE_MAIN_VARIANT (type);
- tree t, t2, cname;
- tree *a = (tree *)alloca ((list_length (raises)+1) * sizeof (tree));
- int constp = TYPE_READONLY (type);
- int volatilep = TYPE_VOLATILE (type);
-
- if (raises && TREE_CHAIN (raises))
- {
- for (i = 0, t = raises; t; t = TREE_CHAIN (t), i++)
- a[i] = t;
- /* NULL terminator for list. */
- a[i] = NULL_TREE;
- qsort (a, i, sizeof (tree), id_cmp);
- while (i--)
- TREE_CHAIN (a[i]) = a[i+1];
- raises = a[0];
- }
- else if (raises)
- /* do nothing. */;
- else
- return build_type_variant (v, constp, volatilep);
-
- if (ctype)
- {
- cname = TYPE_NAME (ctype);
- if (TREE_CODE (cname) == TYPE_DECL)
- cname = DECL_NAME (cname);
- }
- else
- cname = NULL_TREE;
-
- for (t = raises; t; t = TREE_CHAIN (t))
- {
- /* See that all the exceptions we are thinking about
- raising have been declared. */
- tree this_cname = lookup_exception_cname (ctype, cname, t);
- tree decl = lookup_exception_object (this_cname, TREE_VALUE (t), 1);
-
- if (decl == NULL_TREE)
- decl = lookup_exception_object (this_cname, TREE_VALUE (t), 0);
- /* Place canonical exception decl into TREE_TYPE of RAISES list. */
- TREE_TYPE (t) = decl;
- }
-
- for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v))
- {
- if (TYPE_READONLY (v) != constp
- || TYPE_VOLATILE (v) != volatilep)
- continue;
-
- t = raises;
- t2 = TYPE_RAISES_EXCEPTIONS (v);
- while (t && t2)
- {
- if (TREE_TYPE (t) == TREE_TYPE (t2))
- {
- t = TREE_CHAIN (t);
- t2 = TREE_CHAIN (t2);
- }
- else break;
- }
- if (t || t2)
- continue;
- /* List of exceptions raised matches previously found list.
-
- @@ Nice to free up storage used in consing up the
- @@ list of exceptions raised. */
- return v;
- }
-
- /* Need to build a new variant. */
- v = copy_node (type);
- TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type);
- TYPE_NEXT_VARIANT (type) = v;
- if (raises && ! TREE_PERMANENT (raises))
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- raises = copy_list (raises);
- pop_obstacks ();
- }
- TYPE_RAISES_EXCEPTIONS (v) = raises;
- return v;
-}
-
-/* Subroutine of copy_to_permanent
-
- Assuming T is a node build bottom-up, make it all exist on
- permanent obstack, if it is not permanent already. */
-static tree
-make_deep_copy (t)
- tree t;
-{
- enum tree_code code;
-
- if (t == NULL_TREE || TREE_PERMANENT (t))
- return t;
-
- switch (code = TREE_CODE (t))
- {
- case ERROR_MARK:
- return error_mark_node;
-
- case VAR_DECL:
- case FUNCTION_DECL:
- case CONST_DECL:
- break;
-
- case PARM_DECL:
- {
- tree chain = TREE_CHAIN (t);
- t = copy_node (t);
- TREE_CHAIN (t) = make_deep_copy (chain);
- TREE_TYPE (t) = make_deep_copy (TREE_TYPE (t));
- DECL_INITIAL (t) = make_deep_copy (DECL_INITIAL (t));
- DECL_SIZE (t) = make_deep_copy (DECL_SIZE (t));
- return t;
- }
-
- case TREE_LIST:
- {
- tree chain = TREE_CHAIN (t);
- t = copy_node (t);
- TREE_PURPOSE (t) = make_deep_copy (TREE_PURPOSE (t));
- TREE_VALUE (t) = make_deep_copy (TREE_VALUE (t));
- TREE_CHAIN (t) = make_deep_copy (chain);
- return t;
- }
-
- case TREE_VEC:
- {
- int len = TREE_VEC_LENGTH (t);
-
- t = copy_node (t);
- while (len--)
- TREE_VEC_ELT (t, len) = make_deep_copy (TREE_VEC_ELT (t, len));
- return t;
- }
-
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- return copy_node (t);
-
- case COND_EXPR:
- case TARGET_EXPR:
- case NEW_EXPR:
- t = copy_node (t);
- TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0));
- TREE_OPERAND (t, 1) = make_deep_copy (TREE_OPERAND (t, 1));
- TREE_OPERAND (t, 2) = make_deep_copy (TREE_OPERAND (t, 2));
- return t;
-
- case SAVE_EXPR:
- t = copy_node (t);
- TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0));
- return t;
-
- case MODIFY_EXPR:
- case PLUS_EXPR:
- case MINUS_EXPR:
- case MULT_EXPR:
- case TRUNC_DIV_EXPR:
- case TRUNC_MOD_EXPR:
- case MIN_EXPR:
- case MAX_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- case BIT_AND_EXPR:
- case BIT_ANDTC_EXPR:
- case TRUTH_ANDIF_EXPR:
- case TRUTH_ORIF_EXPR:
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case CEIL_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case ROUND_MOD_EXPR:
- case COMPOUND_EXPR:
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- case CALL_EXPR:
- t = copy_node (t);
- TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0));
- TREE_OPERAND (t, 1) = make_deep_copy (TREE_OPERAND (t, 1));
- return t;
-
- case CONVERT_EXPR:
- case ADDR_EXPR:
- case INDIRECT_REF:
- case NEGATE_EXPR:
- case BIT_NOT_EXPR:
- case TRUTH_NOT_EXPR:
- case NOP_EXPR:
- case COMPONENT_REF:
- t = copy_node (t);
- TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0));
- return t;
-
- /* This list is incomplete, but should suffice for now.
- It is very important that `sorry' does not call
- `report_error_function'. That could cause an infinite loop. */
- default:
- sorry ("initializer contains unrecognized tree code");
- return error_mark_node;
-
- }
- my_friendly_abort (107);
- /* NOTREACHED */
- return NULL_TREE;
-}
-
-/* Assuming T is a node built bottom-up, make it all exist on
- permanent obstack, if it is not permanent already. */
-tree
-copy_to_permanent (t)
- tree t;
-{
- register struct obstack *ambient_obstack = current_obstack;
- register struct obstack *ambient_saveable_obstack = saveable_obstack;
-
- if (t == NULL_TREE || TREE_PERMANENT (t))
- return t;
-
- saveable_obstack = &permanent_obstack;
- current_obstack = saveable_obstack;
-
- t = make_deep_copy (t);
-
- current_obstack = ambient_obstack;
- saveable_obstack = ambient_saveable_obstack;
-
- return t;
-}
-
-void
-print_lang_statistics ()
-{
- extern struct obstack maybepermanent_obstack;
- print_obstack_statistics ("class_obstack", &class_obstack);
- print_obstack_statistics ("permanent_obstack", &permanent_obstack);
- print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
- print_search_statistics ();
- print_class_statistics ();
-}
-
-/* This is used by the `assert' macro. It is provided in libgcc.a,
- which `cc' doesn't know how to link. Note that the C++ front-end
- no longer actually uses the `assert' macro (instead, it calls
- my_friendly_assert). But all of the back-end files still need this. */
-void
-__eprintf (string, expression, line, filename)
-#ifdef __STDC__
- const char *string;
- const char *expression;
- unsigned line;
- const char *filename;
-#else
- char *string;
- char *expression;
- unsigned line;
- char *filename;
-#endif
-{
- fprintf (stderr, string, expression, line, filename);
- fflush (stderr);
- abort ();
-}
-
-/* Return, as an INTEGER_CST node, the number of elements for
- TYPE (which is an ARRAY_TYPE). This counts only elements of the top array. */
-
-tree
-array_type_nelts_top (type)
- tree type;
-{
- return fold (build (PLUS_EXPR, integer_type_node,
- array_type_nelts (type),
- integer_one_node));
-}
-
-/* Return, as an INTEGER_CST node, the number of elements for
- TYPE (which is an ARRAY_TYPE). This one is a recursive count of all
- ARRAY_TYPEs that are clumped together. */
-
-tree
-array_type_nelts_total (type)
- tree type;
-{
- tree sz = array_type_nelts_top (type);
- type = TREE_TYPE (type);
- while (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree n = array_type_nelts_top (type);
- sz = fold (build (MULT_EXPR, integer_type_node, sz, n));
- type = TREE_TYPE (type);
- }
- return sz;
-}
diff --git a/gnu/gcc2/cc1plus/cp-tree.def b/gnu/gcc2/cc1plus/cp-tree.def
deleted file mode 100644
index b1a9b3855cd2..000000000000
--- a/gnu/gcc2/cc1plus/cp-tree.def
+++ /dev/null
@@ -1,85 +0,0 @@
-/* This file contains the definitions and documentation for the
- additional tree codes used in the GNU C++ compiler (see tree.def
- for the standard codes).
- Copyright (C) 1987, 1988, 1990, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-
-/* For DELETE_EXPR, operand 0 is the store to be destroyed.
- Operand 1 is the value to pass to the destroying function
- saying whether the store should be deallocated as well. */
-DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2)
-
-/* Value is reference to particular overloaded class method.
- Operand 0 is the class name (an IDENTIFIER_NODE);
- operand 1 is the field (also an IDENTIFIER_NODE).
- The COMPLEXITY field holds the class level (usually 0). */
-DEFTREECODE (SCOPE_REF, "scope_ref", "r", 2)
-
-/* When composing an object with a member, this is the result.
- Operand 0 is the object. Operand 1 is the member (usually
- a dereferenced pointer to member). */
-DEFTREECODE (MEMBER_REF, "member_ref", "r", 2)
-
-/* Type conversion operator in C++. TREE_TYPE is type that this
- operator converts to. Operand is expression to be converted. */
-DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1)
-
-/* For CPLUS_NEW_EXPR, operand 0 is function which performs initialization,
- operand 1 is argument list to initialization function,
- and operand 2 is the slot which was allocated for this expression. */
-DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3)
-
-/* Distinguish variables that are only used to identify exceptions
- that were caught. Only the DECL_NAME (and TREE_CHAIN)
- is really used. */
-DEFTREECODE (CPLUS_CATCH_DECL, "catch_decl", "d", 0)
-
-/* Template definition. The following fields have the specified uses,
- although there are other macros in cp-tree.h that should be used for
- accessing this data.
- DECL_ARGUMENTS template parm vector
- DECL_TEMPLATE_INFO template text &c
- DECL_VINDEX list of instantiations already produced;
- only done for functions so far
- For class template:
- DECL_INITIAL associated templates (methods &c)
- DECL_RESULT null
- For non-class templates:
- TREE_TYPE type of object to be constructed
- DECL_RESULT decl for object to be created
- (e.g., FUNCTION_DECL with tmpl parms used)
- */
-DEFTREECODE (TEMPLATE_DECL, "template_decl", "d", 0)
-
-/* Index into a template parameter list. This parameter must be a type.
- Use TYPE_FIELDS to find parmlist and index. */
-DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", "t", 0)
-
-/* Index into a template parameter list. This parameter must not be a
- type. */
-DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 2)
-
-/* For uninstantiated parameterized types.
- TYPE_VALUES tree list:
- TREE_PURPOSE template decl
- TREE_VALUE parm vector
- TREE_CHAIN null
- Other useful fields to be defined later. */
-DEFTREECODE (UNINSTANTIATED_P_TYPE, "uninstantiated_p_type", "t", 0)
diff --git a/gnu/gcc2/cc1plus/cp-tree.h b/gnu/gcc2/cc1plus/cp-tree.h
deleted file mode 100644
index fa55b655b2f8..000000000000
--- a/gnu/gcc2/cc1plus/cp-tree.h
+++ /dev/null
@@ -1,2006 +0,0 @@
-/* Definitions for C++ parsing and type checking.
- Copyright (C) 1987, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-#include "cp-class.h"
-
-/* Borrow everything that is C from c-tree.h,
- but do so by copy, not by inclusion, since c-tree.h defines
- lang_identifier. */
-
-#ifndef PARANOID
-#define PARANOID 0
-#endif
-
-/* Language-dependent contents of an identifier. */
-
-struct lang_identifier
-{
- struct tree_identifier ignore;
- tree global_value, local_value;
- tree class_value;
- tree class_template_info;
- struct lang_id2 *x;
-};
-
-struct lang_id2
-{
- tree label_value, implicit_decl;
- tree type_desc, as_list, error_locus;
-};
-
-/* To identify to the debug emitters if it should pay attention to the
- flag `-Wtemplate-debugging'. */
-#define HAVE_TEMPLATES 1
-
-/* Macros for access to language-specific slots in an identifier. */
-
-#if !PARANOID
-#define IDENTIFIER_GLOBAL_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->global_value)
-#define IDENTIFIER_CLASS_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->class_value)
-#define IDENTIFIER_LOCAL_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->local_value)
-#define IDENTIFIER_TEMPLATE(NODE) \
- (((struct lang_identifier *)(NODE))->class_template_info)
-#else
-#define IDENTIFIER_LANG_SPECIFIC_PTR(NODE) \
- (my_friendly_assert (TREE_CODE (NODE) == IDENTIFIER_NODE, 325), \
- (struct lang_identifier *) (NODE))
-#define IDENTIFIER_GLOBAL_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->global_value)
-#define IDENTIFIER_CLASS_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->class_value)
-#define IDENTIFIER_LOCAL_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->local_value)
-#define IDENTIFIER_TEMPLATE(NODE) \
- (IDENTIFIER_LANG_SPECIFIC_PTR (NODE) -> class_template_info)
-#endif
-
-#if !PARANOID
-#define IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (NODE))
-#define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (TREE_TYPE (NODE) = TYPE)
-#else
-#define IDENTIFIER_TYPE_VALUE(NODE) (*IDENTIFIER_TYPE_VALUE_PTR(NODE))
-#ifdef __GNUC__
-__inline
-#endif
-static tree * IDENTIFIER_TYPE_VALUE_PTR(NODE) tree NODE; { return
- (my_friendly_assert (TREE_CODE (NODE) == IDENTIFIER_NODE, 326),
- &TREE_TYPE (NODE)) ;}
-#define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (IDENTIFIER_TYPE_VALUE(NODE)=TYPE)
-#endif
-#define IDENTIFIER_HAS_TYPE_VALUE(NODE) (TREE_TYPE (NODE) ? 1 : 0)
-
-#define IDENTIFIER_LABEL_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->x \
- ? ((struct lang_identifier *)(NODE))->x->label_value : 0)
-#define SET_IDENTIFIER_LABEL_VALUE(NODE,VALUE) \
- (((struct lang_identifier *)(NODE))->x == 0 ? ((struct lang_identifier *)(NODE))->x = (struct lang_id2 *)perm_calloc (1, sizeof (struct lang_id2)) : 0, \
- ((struct lang_identifier *)(NODE))->x->label_value = (VALUE))
-#define IDENTIFIER_IMPLICIT_DECL(NODE) \
- (((struct lang_identifier *)(NODE))->x \
- ? ((struct lang_identifier *)(NODE))->x->implicit_decl : 0)
-#define SET_IDENTIFIER_IMPLICIT_DECL(NODE,VALUE) \
- (((struct lang_identifier *)(NODE))->x == 0 ? ((struct lang_identifier *)(NODE))->x = (struct lang_id2 *)perm_calloc (1, sizeof (struct lang_id2)) : 0, \
- ((struct lang_identifier *)(NODE))->x->implicit_decl = (VALUE))
-#define IDENTIFIER_AS_DESC(NODE) \
- (((struct lang_identifier *)(NODE))->x \
- ? ((struct lang_identifier *)(NODE))->x->type_desc : 0)
-#define SET_IDENTIFIER_AS_DESC(NODE,DESC) \
- (((struct lang_identifier *)(NODE))->x == 0 ? ((struct lang_identifier *)(NODE))->x = (struct lang_id2 *)perm_calloc (1, sizeof (struct lang_id2)) : 0, \
- ((struct lang_identifier *)(NODE))->x->type_desc = (DESC))
-#define IDENTIFIER_AS_LIST(NODE) \
- (((struct lang_identifier *)(NODE))->x \
- ? ((struct lang_identifier *)(NODE))->x->as_list : 0)
-#define SET_IDENTIFIER_AS_LIST(NODE,LIST) \
- (((struct lang_identifier *)(NODE))->x == 0 ? ((struct lang_identifier *)(NODE))->x = (struct lang_id2 *)perm_calloc (1, sizeof (struct lang_id2)) : 0, \
- ((struct lang_identifier *)(NODE))->x->as_list = (LIST))
-#define IDENTIFIER_ERROR_LOCUS(NODE) \
- (((struct lang_identifier *)(NODE))->x \
- ? ((struct lang_identifier *)(NODE))->x->error_locus : 0)
-#define SET_IDENTIFIER_ERROR_LOCUS(NODE,VALUE) \
- (((struct lang_identifier *)(NODE))->x == 0 ? ((struct lang_identifier *)(NODE))->x = (struct lang_id2 *)perm_calloc (1, sizeof (struct lang_id2)) : 0, \
- ((struct lang_identifier *)(NODE))->x->error_locus = (VALUE))
-
-#define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1(NODE)
-
-/* Nonzero if this identifier is the prefix for a mangled C++ operator name. */
-#define IDENTIFIER_OPNAME_P(NODE) TREE_LANG_FLAG_2(NODE)
-
-#define IDENTIFIER_TYPENAME_P(NODE) \
- (! strncmp (IDENTIFIER_POINTER (NODE), \
- IDENTIFIER_POINTER (ansi_opname[(int) TYPE_EXPR]), \
- IDENTIFIER_LENGTH (ansi_opname[(int) TYPE_EXPR])))
-
-/* Nonzero means reject anything that ANSI standard C forbids. */
-extern int pedantic;
-
-/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */
-#define C_TYPE_FIELDS_READONLY(type) TYPE_LANG_FLAG_0 (type)
-
-/* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
- next exception handler. */
-extern tree exception_throw_decl;
-
-extern tree double_type_node, long_double_type_node, float_type_node;
-extern tree char_type_node, unsigned_char_type_node, signed_char_type_node;
-extern tree ptrdiff_type_node;
-
-extern tree short_integer_type_node, short_unsigned_type_node;
-extern tree long_integer_type_node, long_unsigned_type_node;
-extern tree long_long_integer_type_node, long_long_unsigned_type_node;
-extern tree unsigned_type_node;
-extern tree string_type_node, char_array_type_node, int_array_type_node;
-extern tree wchar_array_type_node;
-extern tree wchar_type_node, signed_wchar_type_node, unsigned_wchar_type_node;
-extern tree intQI_type_node, unsigned_intQI_type_node;
-extern tree intHI_type_node, unsigned_intHI_type_node;
-extern tree intSI_type_node, unsigned_intSI_type_node;
-extern tree intDI_type_node, unsigned_intDI_type_node;
-
-extern int current_function_returns_value;
-extern int current_function_returns_null;
-extern tree current_function_return_value;
-
-extern tree ridpointers[];
-extern tree ansi_opname[];
-extern tree ansi_assopname[];
-
-/* Nonzero means `$' can be in an identifier. */
-
-extern int dollars_in_ident;
-
-/* Nonzero means allow type mismatches in conditional expressions;
- just make their values `void'. */
-
-extern int flag_cond_mismatch;
-
-/* Nonzero means don't recognize the keyword `asm'. */
-
-extern int flag_no_asm;
-
-/* For cross referencing. */
-
-extern int flag_gnu_xref;
-
-/* For environments where you can use GNU binutils (as, ld in particular). */
-
-extern int flag_gnu_binutils;
-
-/* Nonzero means ignore `#ident' directives. */
-
-extern int flag_no_ident;
-
-/* Nonzero means warn about implicit declarations. */
-
-extern int warn_implicit;
-
-/* Nonzero means warn about function definitions that default the return type
- or that use a null return and have a return-type other than void. */
-
-extern int warn_return_type, explicit_warn_return_type;
-
-/* Nonzero means give string constants the type `const char *'
- to get extra warnings from them. These warnings will be too numerous
- to be useful, except in thoroughly ANSIfied programs. */
-
-extern int warn_write_strings;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
- of function pointers. */
-
-extern int warn_pointer_arith;
-
-/* Nonzero means warn for all old-style non-prototype function decls. */
-
-extern int warn_strict_prototypes;
-
-/* Nonzero means warn about suggesting putting in ()'s. */
-
-extern int warn_parentheses;
-
-/* Warn about a subscript that has type char. */
-
-extern int warn_char_subscripts;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-extern int warn_cast_qual;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C. */
-
-extern int warn_traditional;
-
-/* Nonzero means warn about non virtual destructors in classes that have
- virtual functions. */
-
-extern int warn_nonvdtor;
-
-/* Nonzero means do some things the same way PCC does. */
-
-extern int flag_traditional;
-
-/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */
-
-extern int flag_signed_bitfields;
-
-/* 3 means write out only virtuals function tables `defined'
- in this implementation file.
- 2 means write out only specific virtual function tables
- and give them (C) public visibility.
- 1 means write out virtual function tables and give them
- (C) public visibility.
- 0 means write out virtual function tables and give them
- (C) static visibility (default).
- -1 means declare virtual function tables extern. */
-
-extern int write_virtuals;
-
-/* INTERFACE_ONLY nonzero means that we are in an "interface"
- section of the compiler. INTERFACE_UNKNOWN nonzero means
- we cannot trust the value of INTERFACE_ONLY. If INTERFACE_UNKNOWN
- is zero and INTERFACE_ONLY is zero, it means that we are responsible
- for exporting definitions that others might need. */
-extern int interface_only, interface_unknown;
-
-/* Nonzero means we should attempt to elide constructors when possible. */
-
-extern int flag_elide_constructors;
-
-/* Nonzero means recognize and handle exception handling constructs. */
-
-extern int flag_handle_exceptions;
-
-/* Nonzero means recognize and handle ansi-style exception handling constructs. */
-
-extern int flag_ansi_exceptions;
-
-/* Nonzero means that member functions defined in class scope are
- inline by default. */
-
-extern int flag_default_inline;
-
-/* Nonzero means emit cadillac protocol. */
-
-extern int flag_cadillac;
-
-/* C++ language-specific tree codes. */
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
-enum cplus_tree_code {
- __DUMMY = LAST_AND_UNUSED_TREE_CODE,
-#include "cp-tree.def"
- LAST_CPLUS_TREE_CODE
-};
-#undef DEFTREECODE
-
-enum languages { lang_c, lang_cplusplus };
-
-/* Macros to make error reporting functions' lives easier. */
-#if !PARANOID
-#define TYPE_IDENTIFIER(NODE) (DECL_NAME (TYPE_NAME (NODE)))
-#else
-#define TYPE_IDENTIFIER(NODE) (*TYPE_IDENTIFIER_PTR (NODE))
-#ifdef __GNUC__
-__inline
-#endif
-static tree *
-TYPE_IDENTIFIER_PTR(NODE) tree NODE; { return
- (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 327),
- &DECL_NAME (TYPE_NAME (NODE))) ;}
-#endif
-
-#define TYPE_NAME_STRING(NODE) (IDENTIFIER_POINTER (TYPE_IDENTIFIER (NODE)))
-#define TYPE_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (TYPE_IDENTIFIER (NODE)))
-
-#define TYPE_ASSEMBLER_NAME_STRING(NODE) (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE))))
-#define TYPE_ASSEMBLER_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE))))
-
-#define IS_AGGR_TYPE_2(TYPE1,TYPE2) \
- (TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \
- && IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2))
-
-/* Macros which might want to be replaced by function calls. */
-
-#if 1
-/* Virtual function addresses can be gotten from a virtual function
- table entry using this macro. */
-#define FNADDR_FROM_VTABLE_ENTRY(ENTRY) \
- TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY))))
-#define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \
- (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) = (VALUE))
-
-#define FUNCTION_ARG_CHAIN(NODE) (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE))))
-#define PROMOTES_TO_AGGR_TYPE(NODE,CODE) \
- (((CODE) == TREE_CODE (NODE) \
- && IS_AGGR_TYPE (TREE_TYPE (NODE))) \
- || IS_AGGR_TYPE (NODE))
-
-#else
-#define FNADDR_FROM_VTABLE_ENTRY(ENTRY) (fnaddr_from_vtable_entry (ENTRY))
-#define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \
- (set_fnaddr_from_vtable_entry (ENTRY, VALUE))
-/* #define TYPE_NAME_STRING(NODE) (type_name_string (NODE)) */
-#define FUNCTION_ARG_CHAIN(NODE) (function_arg_chain (NODE))
-#define PROMOTES_TO_AGGR_TYPE(NODE,CODE) (promotes_to_aggr_type (NODE, CODE))
-/* #define IS_AGGR_TYPE_2(TYPE1, TYPE2) (is_aggr_type_2 (TYPE1, TYPE2)) */
-#endif
-/* Nonzero iff TYPE is uniquely derived from PARENT. Under MI, PARENT can be an
- ambiguous base class of TYPE, and this macro will be false. */
-#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) >= 0)
-
-enum conversion_type { ptr_conv, constptr_conv, int_conv, real_conv, last_conversion_type };
-
-/* Statistics show that while the GNU C++ compiler may generate
- thousands of different types during a compilation run, it
- generates relatively few (tens) of classtypes. Because of this,
- it is not costly to store a generous amount of information
- in classtype nodes. This struct must fill out to a multiple of 4 bytes. */
-struct lang_type
-{
- struct
- {
- unsigned has_type_conversion : 1;
- unsigned has_int_conversion : 1;
- unsigned has_float_conversion : 1;
- unsigned has_init_ref : 1;
- unsigned gets_init_ref : 1;
- unsigned gets_init_aggr : 1;
- unsigned has_assignment : 1;
- unsigned gets_assignment : 1;
-
- unsigned needs_constructor : 1;
- unsigned has_default_ctor : 1;
- unsigned uses_multiple_inheritance : 1;
- unsigned const_needs_init : 1;
- unsigned ref_needs_init : 1;
- unsigned gets_const_init_ref : 1;
- unsigned has_const_assign_ref : 1;
- unsigned gets_const_assign_ref : 1;
-
- unsigned vtable_needs_writing : 1;
- unsigned has_assign_ref : 1;
- unsigned gets_assign_ref : 1;
- unsigned gets_new : 1;
- unsigned gets_delete : 1;
- unsigned has_call_overloaded : 1;
- unsigned has_array_ref_overloaded : 1;
- unsigned has_arrow_overloaded : 1;
-
- unsigned local_typedecls : 1;
- unsigned interface_only : 1;
- unsigned interface_unknown : 1;
- unsigned needs_virtual_reinit : 1;
- unsigned declared_exception : 1;
- unsigned declared_class : 1;
- unsigned being_defined : 1;
- unsigned redefined : 1;
-
- unsigned marked : 1;
- unsigned marked2 : 1;
- unsigned marked3 : 1;
- unsigned marked4 : 1;
- unsigned marked5 : 1;
- unsigned marked6 : 1;
- unsigned use_template : 2;
-
- unsigned debug_requested : 1;
- unsigned dynamic : 1;
- unsigned has_method_call_overloaded : 1;
- unsigned private_attr : 1;
- unsigned alters_visibilities : 1;
- unsigned got_semicolon : 1;
- unsigned dummy : 1;
-
- /* The MIPS compiler gets it wrong if this struct also
- does not fill out to a multiple of 4 bytes. */
- unsigned n_vancestors : 16;
- } type_flags;
-
- int cid;
- int n_ancestors;
- int vsize;
- int max_depth;
-
- union tree_node *vbinfo[2];
- union tree_node *baselink_vec;
- union tree_node *vfields;
- union tree_node *vbases;
- union tree_node *vbase_size;
-
- union tree_node *tags;
- char *memoized_table_entry;
-
- char *search_slot;
-
-#ifdef ONLY_INT_FIELDS
- unsigned int mode : 8;
-#else
- enum machine_mode mode : 8;
-#endif
-
- unsigned char size_unit;
- unsigned char align;
- unsigned char sep_unit;
-
- union tree_node *sep;
- union tree_node *size;
-
- union tree_node *base_init_list;
- union tree_node *abstract_virtuals;
- union tree_node *as_list;
- union tree_node *id_as_list;
- union tree_node *binfo_as_list;
- union tree_node *vtbl_ptr;
- union tree_node *instance_variable;
- union tree_node *friend_classes;
-
- char *mi_matrix;
- union tree_node *conversions[last_conversion_type];
-
- union tree_node *dossier;
-};
-
-/* Indicates whether a template should be (or has been) expanded for this
- class definition. 0=do, 1=did, 2=don't, 3=didn't. */
-#define CLASSTYPE_USE_TEMPLATE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.use_template)
-
-/* Fields used for storing information before the class is defined.
- After the class is defined, these fields hold other information. */
-
-/* List of friends which were defined inline in this class definition. */
-#define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE))
-
-/* Nonzero for _CLASSTYPE means that the _CLASSTYPE either has
- a special meaning for the assignment operator ("operator="),
- or one of its fields (or base members) has a special meaning
- defined. */
-#define TYPE_HAS_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_assignment)
-#define TYPE_GETS_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_assignment)
-
-/* Nonzero for _CLASSTYPE means that operator new and delete are defined,
- respectively. */
-#define TREE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new)
-#define TREE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_delete)
-
-/* Nonzero for TREE_LIST or _TYPE node means that this node is class-local. */
-#define TREE_NONLOCAL_FLAG(NODE) (TREE_LANG_FLAG_0 (NODE))
-
-/* Nonzero for a _CLASSTYPE node which we know to be private. */
-#define TYPE_PRIVATE_P(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.private_attr)
-
-/* Nonzero means that this _CLASSTYPE node defines ways of converting
- itself to other types. */
-#define TYPE_HAS_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_type_conversion)
-
-/* Nonzero means that this _CLASSTYPE node can convert itself to an
- INTEGER_TYPE. */
-#define TYPE_HAS_INT_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_int_conversion)
-
-/* Nonzero means that this _CLASSTYPE node can convert itself to an
- REAL_TYPE. */
-#define TYPE_HAS_REAL_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_float_conversion)
-
-/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */
-#define TYPE_HAS_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_assign_ref)
-#define TYPE_GETS_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_assign_ref)
-#define TYPE_HAS_CONST_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_const_assign_ref)
-#define TYPE_GETS_CONST_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_const_assign_ref)
-
-/* Nonzero means that this _CLASSTYPE node has an X(X&) constructor. */
-#define TYPE_HAS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_init_ref)
-#define TYPE_GETS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_init_ref)
-#define TYPE_GETS_CONST_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_const_init_ref)
-
-/* Nonzero means that this _CLASSTYPE node has an X(X ...) constructor.
- Note that there must be other arguments, or this constructor is flagged
- as being erroneous. */
-#define TYPE_GETS_INIT_AGGR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_init_aggr)
-
-/* Nonzero means that this type is being defined. I.e., the left brace
- starting the definition of this type has been seen. */
-#define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.being_defined)
-/* Nonzero means that this type has been redefined. In this case, if
- convenient, don't reprocess any methods that appear in its redefinition. */
-#define TYPE_REDEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.redefined)
-
-/* Nonzero means that this _CLASSTYPE node overloads the method call
- operator. In this case, all method calls go through `operator->()(...). */
-#define TYPE_OVERLOADS_METHOD_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_method_call_overloaded)
-
-/* The is the VAR_DECL that contains NODE's dossier. */
-#define CLASSTYPE_DOSSIER(NODE) (TYPE_LANG_SPECIFIC(NODE)->dossier)
-
-/* Nonzero means that this _CLASSTYPE node overloads operator(). */
-#define TYPE_OVERLOADS_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_call_overloaded)
-
-/* Nonzero means that this _CLASSTYPE node overloads operator[]. */
-#define TYPE_OVERLOADS_ARRAY_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_array_ref_overloaded)
-
-/* Nonzero means that this _CLASSTYPE node overloads operator->. */
-#define TYPE_OVERLOADS_ARROW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_arrow_overloaded)
-
-/* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses
- multiple inheritance. If this is 0 for the root of a type
- hierarchy, then we can use more efficient search techniques. */
-#define TYPE_USES_MULTIPLE_INHERITANCE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.uses_multiple_inheritance)
-
-/* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses
- virtual base classes. If this is 0 for the root of a type
- hierarchy, then we can use more efficient search techniques. */
-#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE))
-
-/* List of lists of member functions defined in this class. */
-#define CLASSTYPE_METHOD_VEC(NODE) TYPE_METHODS(NODE)
-
-/* Pointer from any member function to the head of the list of
- member functions of the type that member function belongs to. */
-#define CLASSTYPE_BASELINK_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->baselink_vec)
-
-/* Mark bits for depth-first and breath-first searches. */
-#if !PARANOID
-#define CLASSTYPE_MARKED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked)
-#define CLASSTYPE_MARKED2(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked2)
-#define CLASSTYPE_MARKED3(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked3)
-#define CLASSTYPE_MARKED4(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked4)
-#define CLASSTYPE_MARKED5(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked5)
-#define CLASSTYPE_MARKED6(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked6)
-/* Macros to modify the above flags */
-#define SET_CLASSTYPE_MARKED(NODE) (CLASSTYPE_MARKED(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED(NODE) (CLASSTYPE_MARKED(NODE) = 0)
-#define SET_CLASSTYPE_MARKED2(NODE) (CLASSTYPE_MARKED2(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED2(NODE) (CLASSTYPE_MARKED2(NODE) = 0)
-#define SET_CLASSTYPE_MARKED3(NODE) (CLASSTYPE_MARKED3(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED3(NODE) (CLASSTYPE_MARKED3(NODE) = 0)
-#define SET_CLASSTYPE_MARKED4(NODE) (CLASSTYPE_MARKED4(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED4(NODE) (CLASSTYPE_MARKED4(NODE) = 0)
-#define SET_CLASSTYPE_MARKED5(NODE) (CLASSTYPE_MARKED5(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED5(NODE) (CLASSTYPE_MARKED5(NODE) = 0)
-#define SET_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 0)
-#else
-#define CLASSTYPE_MARKED(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 328), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked)
-#define CLASSTYPE_MARKED2(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 329), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked2)
-#define CLASSTYPE_MARKED3(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 330), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked3)
-#define CLASSTYPE_MARKED4(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 331), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked4)
-#define CLASSTYPE_MARKED5(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 332), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked5)
-#define CLASSTYPE_MARKED6(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 333), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked6)
-/* Macros to modify the above flags */
-#define SET_CLASSTYPE_MARKED(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 334), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked = 1)
-#define CLEAR_CLASSTYPE_MARKED(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 335), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked = 0)
-#define SET_CLASSTYPE_MARKED2(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 336), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked2 = 1)
-#define CLEAR_CLASSTYPE_MARKED2(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 337), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked2 = 0)
-#define SET_CLASSTYPE_MARKED3(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 338), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked3 = 1)
-#define CLEAR_CLASSTYPE_MARKED3(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 339), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked3 = 0)
-#define SET_CLASSTYPE_MARKED4(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 340), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked4 = 1)
-#define CLEAR_CLASSTYPE_MARKED4(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 341), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked4 = 0)
-#define SET_CLASSTYPE_MARKED5(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 342), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked5 = 1)
-#define CLEAR_CLASSTYPE_MARKED5(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 343), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked5 = 0)
-#define SET_CLASSTYPE_MARKED6(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 344), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked6 = 1)
-#define CLEAR_CLASSTYPE_MARKED6(NODE) (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 't', 345), TYPE_LANG_SPECIFIC(NODE)->type_flags.marked6 = 0)
-#endif
-
-#define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC(NODE)->tags)
-
-/* Remove when done merging. */
-#define CLASSTYPE_VFIELD(NODE) TYPE_VFIELD(NODE)
-
-/* The number of virtual functions defined for this
- _CLASSTYPE node. */
-#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
-/* The virtual base classes that this type uses. */
-#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
-/* The virtual function pointer fields that this type contains. */
-#define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields)
-
-/* Number of baseclasses defined for this type.
- 0 means no base classes. */
-#define CLASSTYPE_N_BASECLASSES(NODE) \
- (TYPE_BINFO_BASETYPES (NODE) ? TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES(NODE)) : 0)
-
-/* Memoize the number of super classes (base classes) tha this node
- has. That way we can know immediately (albeit conservatively how
- large a multiple-inheritance matrix we need to build to find
- derivation information. */
-#define CLASSTYPE_N_SUPERCLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->n_ancestors)
-#define CLASSTYPE_N_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.n_vancestors)
-
-/* Record how deep the inheritance is for this class so `void*' conversions
- are less favorable than a conversion to the most base type. */
-#define CLASSTYPE_MAX_DEPTH(NODE) (TYPE_LANG_SPECIFIC(NODE)->max_depth)
-
-/* Used for keeping search-specific information. Any search routine
- which uses this must define what exactly this slot is used for. */
-#define CLASSTYPE_SEARCH_SLOT(NODE) (TYPE_LANG_SPECIFIC(NODE)->search_slot)
-
-/* Entry for keeping memoization tables for this type to
- hopefully speed up search routines. Since it is a pointer,
- it can mean almost anything. */
-#define CLASSTYPE_MTABLE_ENTRY(NODE) (TYPE_LANG_SPECIFIC(NODE)->memoized_table_entry)
-
-/* This is the total size of the baseclasses defined for this type.
- Needed because it is desirable to layout such information
- before beginning to process the class itself, and we
- don't want to compute it second time when actually laying
- out the type for real. */
-#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size)
-#define CLASSTYPE_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->size_unit)
-#define CLASSTYPE_MODE(NODE) (TYPE_LANG_SPECIFIC(NODE)->mode)
-#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align)
-
-/* This is the space needed for virtual base classes. NULL if
- there are no virtual basetypes. */
-#define CLASSTYPE_VBASE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbase_size)
-
-/* A cons list of structure elements which either have constructors
- to be called, or virtual function table pointers which
- need initializing. Depending on what is being initialized,
- the TREE_PURPOSE and TREE_VALUE fields have different meanings:
-
- Member initialization: <FIELD_DECL, TYPE>
- Base class construction: <NULL_TREE, BASETYPE>
- Base class initialization: <BASE_INITIALIZATION, THESE_INITIALIZATIONS>
- Whole type: <MEMBER_INIT, BASE_INIT>. */
-#define CLASSTYPE_BASE_INIT_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->base_init_list)
-
-/* A cons list of virtual functions which cannot be inherited by
- derived classes. When deriving from this type, the derived
- class must provide its own definition for each of these functions. */
-#define CLASSTYPE_ABSTRACT_VIRTUALS(NODE) (TYPE_LANG_SPECIFIC(NODE)->abstract_virtuals)
-
-#define CLASSTYPE_ALTERS_VISIBILITIES_P(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.alters_visibilities)
-
-/* Nonzero means that this aggr type has been `closed' by a semicolon. */
-#define CLASSTYPE_GOT_SEMICOLON(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.got_semicolon)
-
-/* Nonzero means that the main virtual function table pointer needs to be
- set because base constructors have placed the wrong value there.
- If this is zero, it means that they placed the right value there,
- and there is no need to change it. */
-#define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.needs_virtual_reinit)
-
-/* Nonzero means that if this type has virtual functions, that
- the virtual function table will be written out. */
-#define CLASSTYPE_VTABLE_NEEDS_WRITING(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.vtable_needs_writing)
-
-/* Nonzero means that this type defines its own local type declarations. */
-#define CLASSTYPE_LOCAL_TYPEDECLS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.local_typedecls)
-
-/* Nonzero means that this type has an X() constructor. */
-#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_default_ctor)
-
-/* Many routines need to cons up a list of basetypes for visibility
- checking. This field contains a TREE_LIST node whose TREE_VALUE
- is the main variant of the type, and whose TREE_VIA_PUBLIC
- and TREE_VIA_VIRTUAL bits are correctly set. */
-#define CLASSTYPE_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->as_list)
-/* Same, but cache a list whose value is the name of this type. */
-#define CLASSTYPE_ID_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->id_as_list)
-/* Same, but cache a list whose value is the binfo of this type. */
-#define CLASSTYPE_BINFO_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->binfo_as_list)
-
-/* Slot in which to cache a copy of the local vtable pointer. */
-#define CLASSTYPE_VTBL_PTR(NODE) (TYPE_LANG_SPECIFIC(NODE)->vtbl_ptr)
-
-/* Hold the instance object associated with this method. */
-#define CLASSTYPE_INST_VAR(NODE) (TYPE_LANG_SPECIFIC(NODE)->instance_variable)
-
-/* A list of class types with which this type is a friend. */
-#define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes)
-
-/* Keep an inheritance lattice around so we can quickly tell whether
- a type is derived from another or not. */
-#define CLASSTYPE_MI_MATRIX(NODE) (TYPE_LANG_SPECIFIC(NODE)->mi_matrix)
-
-/* If there is exactly one conversion to a non-void, non-const pointer type,
- remember that here. If there are more than one, put
- `error_mark_node' here. If there are none, this holds NULL_TREE. */
-#define CLASSTYPE_CONVERSION(NODE,KIND) \
- (TYPE_LANG_SPECIFIC(NODE)->conversions[(int) KIND])
-
-/* Say whether this node was declared as a "class" or a "struct". */
-#define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
-/* Say whether this node was declared as a "class" or a "struct". */
-#define CLASSTYPE_DECLARED_EXCEPTION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_exception)
-
-/* Nonzero if this class has const members which have no specified initialization. */
-#define CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.const_needs_init)
-
-/* Nonzero if this class has ref members which have no specified initialization. */
-#define CLASSTYPE_REF_FIELDS_NEED_INIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.ref_needs_init)
-
-/* Nonzero if this class is included from a header file which employs
- `#pragma interface', and it is not included in its implementation file. */
-#define CLASSTYPE_INTERFACE_ONLY(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.interface_only)
-
-/* Same as above, but for classes whose purpose we do not know. */
-#define CLASSTYPE_INTERFACE_UNKNOWN(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.interface_unknown)
-
-/* Nonzero if a _DECL node requires us to output debug info for this class. */
-#define CLASSTYPE_DEBUG_REQUESTED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.debug_requested)
-
-/* Additional macros for inheritance information. */
-
-#define CLASSTYPE_VBINFO(NODE,VIA_PUBLIC) \
- (TYPE_LANG_SPECIFIC (NODE)->vbinfo[VIA_PUBLIC])
-
-/* When following an binfo-specific chain, this is the cumulative
- via-public flag. */
-#define BINFO_VIA_PUBLIC(NODE) TREE_LANG_FLAG_5 (NODE)
-
-/* When building a matrix to determine by a single lookup
- whether one class is derived from another or not,
- this field is the index of the class in the table. */
-#define CLASSTYPE_CID(NODE) (TYPE_LANG_SPECIFIC(NODE)->cid)
-#define BINFO_CID(NODE) CLASSTYPE_CID(BINFO_TYPE(NODE))
-
-/* Nonzero means marked by DFS or BFS search, including searches
- by `get_binfo' and `get_base_distance'. */
-#define BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED(BINFO_TYPE(NODE)):TREE_LANG_FLAG_0(NODE))
-/* Macros needed because of C compilers that don't allow conditional
- expressions to be lvalues. Grr! */
-#define SET_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=1))
-#define CLEAR_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=0))
-
-/* Nonzero means marked in building initialization list. */
-#define BINFO_BASEINIT_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-/* Modifier macros */
-#define SET_BINFO_BASEINIT_MARKED(NODE) SET_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-#define CLEAR_BINFO_BASEINIT_MARKED(NODE) CLEAR_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-
-/* Nonzero means marked in search through virtual inheritance hierarchy. */
-#define BINFO_VBASE_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-/* Modifier macros */
-#define SET_BINFO_VBASE_MARKED(NODE) SET_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-#define CLEAR_BINFO_VBASE_MARKED(NODE) CLEAR_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-
-/* Nonzero means marked in search for members or member functions. */
-#define BINFO_FIELDS_MARKED(NODE) \
- (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED2 (BINFO_TYPE (NODE)):TREE_LANG_FLAG_2(NODE))
-#define SET_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=1))
-#define CLEAR_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=0))
-
-/* Nonzero means that this class is on a path leading to a new vtable. */
-#define BINFO_VTABLE_PATH_MARKED(NODE) \
- (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):TREE_LANG_FLAG_3(NODE))
-#define SET_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=1))
-#define CLEAR_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=0))
-
-/* Nonzero means that this class has a new vtable. */
-#define BINFO_NEW_VTABLE_MARKED(NODE) \
- (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):TREE_LANG_FLAG_4(NODE))
-#define SET_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=1))
-#define CLEAR_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=0))
-
-/* Nonzero means this class has initialized its virtual baseclasses. */
-#define BINFO_VBASE_INIT_MARKED(NODE) \
- (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED5(BINFO_TYPE(NODE)):TREE_LANG_FLAG_5(NODE))
-#define SET_BINFO_VBASE_INIT_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED5(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_5(NODE)=1))
-#define CLEAR_BINFO_VBASE_INIT_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED5(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_5(NODE)=0))
-
-/* Accessor macros for the vfield slots in structures. */
-
-/* Get the assoc info that caused this vfield to exist. */
-#define VF_BINFO_VALUE(NODE) TREE_PURPOSE (NODE)
-
-/* Get that same information as a _TYPE. */
-#define VF_BASETYPE_VALUE(NODE) TREE_VALUE (NODE)
-
-/* Get the value of the top-most type dominating the non-`normal' vfields. */
-#define VF_DERIVED_VALUE(NODE) (VF_BINFO_VALUE (NODE) ? BINFO_TYPE (VF_BINFO_VALUE (NODE)) : NULL_TREE)
-
-/* Get the value of the top-most type that's `normal' for the vfield. */
-#define VF_NORMAL_VALUE(NODE) TREE_TYPE (NODE)
-
-/* Nonzero for TREE_LIST node means that this list of things
- is a list of parameters, as opposed to a list of expressions. */
-#define TREE_PARMLIST(NODE) ((NODE)->common.unsigned_flag) /* overloaded! */
-
-/* Nonzero for FIELD_DECL node means that this FIELD_DECL is
- a member of an anonymous union construct. The name of the
- union is . */
-#define TREE_ANON_UNION_ELEM(NODE) ((NODE)->decl.regdecl_flag) /* overloaded! */
-
-/* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that
- this type can raise. */
-#define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE)
-
-struct lang_decl_flags
-{
-#ifdef ONLY_INT_FIELDS
- int language : 8;
-#else
- enum languages language : 8;
-#endif
-
- unsigned operator_attr : 1;
- unsigned constructor_attr : 1;
- unsigned returns_first_arg : 1;
- unsigned preserves_first_arg : 1;
- unsigned friend_attr : 1;
- unsigned static_function : 1;
- unsigned const_memfunc : 1;
- unsigned volatile_memfunc : 1;
-
- unsigned abstract_virtual : 1;
- unsigned permanent_attr : 1 ;
- unsigned constructor_for_vbase_attr : 1;
- unsigned dummy : 13;
-
- tree visibility;
- tree context;
-};
-
-struct lang_decl
-{
- struct lang_decl_flags decl_flags;
-
- struct template_info *template_info;
- tree main_decl_variant;
- struct pending_inline *pending_inline_info;
- tree vbase_init_list;
- tree chain;
-};
-
-/* Non-zero if NODE is a _DECL with TREE_READONLY set. */
-#define TREE_READONLY_DECL_P(NODE) \
- (TREE_READONLY (NODE) && TREE_CODE_CLASS (TREE_CODE (NODE)) == 'd')
-
-/* For FUNCTION_DECLs: return the language in which this decl
- was declared. */
-#define DECL_LANGUAGE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.language)
-
-/* For FUNCTION_DECLs: nonzero means that this function is a constructor. */
-#define DECL_CONSTRUCTOR_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_attr)
-/* For FUNCTION_DECLs: nonzero means that this function is a constructor
- for an object with virtual baseclasses. */
-#define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr)
-
-/* For FUNCTION_DECLs: nonzero means that the constructor
- is known to return a non-zero `this' unchanged. */
-#define DECL_RETURNS_FIRST_ARG(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.returns_first_arg)
-
-/* Nonzero for FUNCTION_DECL means that this constructor is known to
- not make any assignment to `this', and therefore can be trusted
- to return it unchanged. Otherwise, we must re-assign `current_class_decl'
- after performing base initializations. */
-#define DECL_PRESERVES_THIS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.preserves_first_arg)
-
-/* 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
- detecting circularity in case members are multiply defined. In the
- case of a VAR_DECL, it is also used to determine how program storage
- should be allocated. */
-#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3(NODE))
-
-/* Nonzero for FUNCTION_DECL means that this decl is just a
- friend declaration, and should not be added to the list of
- member functions for this class. */
-#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.friend_attr)
-
-/* Nonzero for FUNCTION_DECL means that this decl is a static
- member function. */
-#define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function)
-
-/* Nonzero for FUNCTION_DECL means that this member function
- has `this' as const X *const. */
-#define DECL_CONST_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.const_memfunc)
-
-/* Nonzero for FUNCTION_DECL means that this member function
- has `this' as volatile X *const. */
-#define DECL_VOLATILE_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.volatile_memfunc)
-
-/* Nonzero for FUNCTION_DECL means that this member function
- exists as part of an abstract class's interface. */
-#define DECL_ABSTRACT_VIRTUAL_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.abstract_virtual)
-
-/* Nonzero if allocated on permanent_obstack. */
-#define LANG_DECL_PERMANENT(LANGDECL) ((LANGDECL)->decl_flags.permanent_attr)
-
-/* The _TYPE context in which this _DECL appears. This field is used
- only to compute visibility information. */
-#define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context)
-
-/* For a FUNCTION_DECL: the chain through which the next method
- in the method chain is found. We now use TREE_CHAIN to
- link into the FIELD_DECL chain. */
-#if 1
-#define DECL_CHAIN(NODE) (DECL_LANG_SPECIFIC(NODE)->chain)
-#else
-#define DECL_CHAIN(NODE) (TREE_CHAIN (NODE))
-#endif
-
-/* Points back to the decl which caused this lang_decl to be allocated. */
-#define DECL_MAIN_VARIANT(NODE) (DECL_LANG_SPECIFIC(NODE)->main_decl_variant)
-
-/* For a FUNCTION_DECL: if this function was declared inline inside of
- a class declaration, this is where the text for the function is
- squirreled away. */
-#define DECL_PENDING_INLINE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->pending_inline_info)
-
-/* Holds information about how virtual base classes should be initialized
- by this constructor *if* this constructor is the one to perform
- such initialization. */
-#define DECL_VBASE_INIT_LIST(NODE) (DECL_LANG_SPECIFIC(NODE)->vbase_init_list)
-
-/* For a TEMPLATE_DECL: template-specific information. */
-#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->template_info)
-
-/* Nonzero in INT_CST means that this int is negative by dint of
- using a twos-complement negated operand. */
-#define TREE_NEGATED_INT(NODE) (TREE_LANG_FLAG_0 (NODE))
-
-/* Nonzero in any kind of _EXPR or _REF node means that it is a call
- to a storage allocation routine. If, later, alternate storage
- is found to hold the object, this call can be ignored. */
-#define TREE_CALLS_NEW(NODE) (TREE_LANG_FLAG_1 (NODE))
-
-/* Nonzero in any kind of _TYPE that uses multiple inheritance
- or virtual baseclasses. */
-#define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE))
-
-/* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
- should be looked up in a non-standard way. */
-#define TREE_OVERLOADED(NODE) (TREE_LANG_FLAG_0 (NODE))
-#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
-
-/* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
- For a FUNCTION_DECL, this is when the function is a virtual function.
- For a VAR_DECL, this is when the variable is a virtual function table.
- For a FIELD_DECL, when the field is the field for the virtual function table.
- For an IDENTIFIER_NODE, nonzero if any function with this name
- has been declared virtual.
-
- For a _TYPE if it uses virtual functions (or is derived from
- one that does). */
-#define TYPE_VIRTUAL_P(NODE) (TREE_LANG_FLAG_2 (NODE))
-
-/* Same, but tells if this field is private in current context. */
-#define DECL_PRIVATE(NODE) (DECL_LANG_FLAG_5 (NODE))
-
-/* Same, but tells if this field is private in current context. */
-#define DECL_PROTECTED(NODE) (DECL_LANG_FLAG_6(NODE))
-
-#define DECL_PUBLIC(NODE) (DECL_LANG_FLAG_7(NODE))
-
-/* Record whether a typedef for type `int' was actually `signed int'. */
-#define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp))
-
-/* Nonzero if the type T promotes to itself.
- ANSI C states explicitly the list of types that promote;
- in particular, short promotes to int even if they have the same width. */
-#define C_PROMOTING_INTEGER_TYPE_P(t) \
- (TREE_CODE ((t)) == INTEGER_TYPE \
- && (TYPE_MAIN_VARIANT (t) == char_type_node \
- || TYPE_MAIN_VARIANT (t) == signed_char_type_node \
- || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node \
- || TYPE_MAIN_VARIANT (t) == short_integer_type_node \
- || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node))
-
-/* Mark which labels are explicitly declared.
- These may be shadowed, and may be referenced from nested functions. */
-#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
-
-/* Record whether a type or decl was written with nonconstant size.
- Note that TYPE_SIZE may have simplified to a constant. */
-#define C_TYPE_VARIABLE_SIZE(type) TREE_LANG_FLAG_4 (type)
-#define C_DECL_VARIABLE_SIZE(type) DECL_LANG_FLAG_8 (type)
-
-/* Nonzero for _TYPE means that the _TYPE defines
- at least one constructor. */
-#define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1(NODE))
-
-/* When appearing in an INDIRECT_REF, it means that the tree structure
- underneath is actually a call to a constructor. This is needed
- when the constructor must initialize local storage (which can
- be automatically destroyed), rather than allowing it to allocate
- space from the heap.
-
- When appearing in a SAVE_EXPR, it means that underneath
- is a call to a constructor.
-
- When appearing in a CONSTRUCTOR, it means that it was
- a GNU C constructor expression.
-
- When appearing in a FIELD_DECL, it means that this field
- has been duly initialized in its constructor. */
-#define TREE_HAS_CONSTRUCTOR(NODE) (TREE_LANG_FLAG_4(NODE))
-
-/* Indicates that a NON_LVALUE_EXPR came from a C++ reference.
- Used to generate more helpful error message in case somebody
- tries to take its address. */
-#define TREE_REFERENCE_EXPR(NODE) (TREE_LANG_FLAG_3(NODE))
-
-/* Nonzero for _TYPE means that the _TYPE defines a destructor. */
-#define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE))
-
-/* Nonzero for _TYPE node means that creating an object of this type
- will involve a call to a constructor. This can apply to objects
- of ARRAY_TYPE if the type of the elements needs a constructor. */
-#define TYPE_NEEDS_CONSTRUCTING(NODE) (TYPE_LANG_FLAG_3(NODE))
-#define TYPE_NEEDS_CONSTRUCTOR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.needs_constructor)
-
-/* Nonzero for _TYPE node means that destroying an object of this type
- will involve a call to a destructor. This can apply to objects
- of ARRAY_TYPE is the type of the elements needs a destructor. */
-#define TYPE_NEEDS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_4(NODE))
-
-/* Nonzero for VAR_DECL node means that `external' was specified in
- its declaration. */
-#define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE))
-
-/* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */
-#define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE))
-
-/* Nonzero in FUNCTION_DECL means it is really an operator.
- Just used to communicate formatting information to dbxout.c. */
-#define DECL_OPERATOR(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.operator_attr)
-
-/* Define fields and accessors for nodes representing declared names. */
-
-#if 0
-/* C++: A derived class may be able to directly use the virtual
- function table of a base class. When it does so, it may
- still have a decl node used to access the virtual function
- table (so that variables of this type can initialize their
- virtual function table pointers by name). When such thievery
- is committed, know exactly which base class's virtual function
- table is the one being stolen. This effectively computes the
- transitive closure. */
-#define DECL_VPARENT(NODE) ((NODE)->decl.arguments)
-#endif
-
-/* Make a slot so we can implement nested types. This slot holds
- the IDENTIFIER_NODE that uniquely names the nested type. This
- is for TYPE_DECLs only. */
-#if !PARANOID
-#define DECL_NESTED_TYPENAME(NODE) ((NODE)->decl.arguments)
-#else
-#define DECL_NESTED_TYPENAME(NODE) (*DECL_NESTED_TYPENAME_PTR(NODE))
-#ifdef __GNUC__
-__inline
-#endif
-static tree * DECL_NESTED_TYPENAME_PTR(NODE) tree NODE; { return
- (my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (NODE)) == 'd', 346),
- &(NODE)->decl.arguments) ;}
-#endif
-
-/* C++: all of these are overloaded! These apply only to TYPE_DECLs. */
-#define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE))
-#define DECL_UNDEFINED_FRIENDS(NODE) ((NODE)->decl.result)
-#define DECL_WAITING_FRIENDS(NODE) ((tree)(NODE)->decl.rtl)
-#define SET_DECL_WAITING_FRIENDS(NODE,VALUE) ((NODE)->decl.rtl=(struct rtx_def*)VALUE)
-
-/* The DECL_VISIBILITY is used to record under which context
- special visibility rules apply. */
-#define DECL_VISIBILITY(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.visibility)
-
-/* C++: all of these are overloaded!
- These apply to PARM_DECLs and VAR_DECLs. */
-#define DECL_REFERENCE_SLOT(NODE) ((tree)(NODE)->decl.arguments)
-#define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL)
-
-/* For local VAR_DECLs, holds index into gc-protected obstack. */
-#define DECL_GC_OFFSET(NODE) ((NODE)->decl.result)
-
-/* Accessor macros for C++ template decl nodes. */
-#define DECL_TEMPLATE_IS_CLASS(NODE) (DECL_RESULT(NODE) == NULL_TREE)
-#define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
-/* For class templates. */
-#define DECL_TEMPLATE_MEMBERS(NODE) DECL_INITIAL(NODE)
-/* For function, method, class-data templates. */
-#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
-#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
-
-/* ...and for unexpanded-parameterized-type nodes. */
-#define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE))
-#define UPT_PARMS(NODE) TREE_VALUE(TYPE_VALUES(NODE))
-
-/* An enumeration of the kind of tags that C++ accepts. */
-enum tag_types { record_type, class_type, union_type, enum_type, exception_type };
-
-/* Zero means prototype weakly, as in ANSI C (no args means nothing).
- Each language context defines how this variable should be set. */
-extern int strict_prototype;
-extern int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus;
-
-/* Non-zero means that if a label exists, and no other identifier
- applies, use the value of the label. */
-extern int flag_labels_ok;
-
-/* Non-zero means to collect statistics which might be expensive
- and to print them when we are done. */
-extern int flag_detailed_statistics;
-
-/* Non-zero means warn in function declared in derived class has the
- same name as a virtual in the base class, but fails to match the
- type signature of any virtual function in the base class. */
-extern int warn_overloaded_virtual;
-
-/* in cp-decl{2}.c */
-extern tree void_list_node;
-extern tree void_zero_node;
-extern tree default_function_type;
-extern tree vtable_entry_type;
-extern tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node;
-extern tree class_star_type_node;
-
-/* A node that is a list (length 1) of error_mark_nodes. */
-extern tree error_mark_list;
-
-extern tree ptr_type_node;
-extern tree class_type_node, record_type_node, union_type_node, enum_type_node;
-extern tree exception_type_node, unknown_type_node;
-
-/* The largest size a virtual function table can be.
- Must be a (power of 2). */
-#ifndef VINDEX_MAX
-#define VINDEX_MAX ((unsigned)128)
-/* This is the integer ~ (vindex_max - 1). */
-#endif
-extern tree vtbl_mask;
-
-/* Array type `(void *)[]' */
-extern tree vtbl_type_node;
-
-extern tree long_long_integer_type_node, long_long_unsigned_type_node;
-/* For building calls to `delete'. */
-extern tree integer_two_node, integer_three_node;
-
-/* in cp-except.c */
-extern tree current_exception_type;
-extern tree current_exception_decl;
-extern tree current_exception_object;
-
-/* in cp-pt.c */
-/* PARM_VEC is a vector of template parameters, either IDENTIFIER_NODEs or
- PARM_DECLs. BINDINGS, if non-null, is a vector of bindings for those
- parameters. */
-struct template_info {
- /* Vector of template parameters, either PARM_DECLs or IDENTIFIER_NODEs. */
- tree parm_vec;
- /* If non-null, a vector of bindings for the template parms. */
- tree bindings;
-
- /* Text of template, and length. */
- char *text;
- int length;
- /* Where it came from. */
- char *filename;
- int lineno;
-
- /* What kind of aggregate -- struct, class, or null. */
- tree aggr;
-};
-extern int processing_template_decl, processing_template_defn;
-
-#define PRINT_LANG_DECL
-#define PRINT_LANG_TYPE
-
-#define UNKNOWN_TYPE LANG_TYPE
-
-/* in cp-class.c */
-extern tree current_class_name;
-extern tree current_class_type;
-
-extern tree current_lang_name, lang_name_cplusplus, lang_name_c;
-
-/* Points to the name of that function. May not be the DECL_NAME
- of CURRENT_FUNCTION_DECL due to overloading */
-extern tree original_function_name;
-
-# define IS_AGGR_TYPE(t) (TYPE_LANG_FLAG_5 (t))
-
-# define IS_AGGR_TYPE_CODE(t) \
- (t == RECORD_TYPE || t == UNION_TYPE)
-
-extern tree current_class_name, current_class_type, current_class_decl, C_C_D;
-extern tree current_vtable_decl;
-
-/* in cp-init.c */
-extern tree global_base_init_list;
-extern tree current_base_init_list, current_member_init_list;
-
-extern int current_function_assigns_this;
-extern int current_function_just_assigned_this;
-extern int current_function_parms_stored;
-
-/* Here's where we control how name mangling takes place. */
-
-#define OPERATOR_ASSIGN_FORMAT "__a%s"
-#define OPERATOR_FORMAT "__%s"
-#define OPERATOR_TYPENAME_FORMAT "__op"
-
-/* Cannot use '$' up front, because this confuses gdb
- (names beginning with '$' are gdb-local identifiers).
-
- Note that all forms in which the '$' is significant are long enough
- for direct indexing (meaning that if we know there is a '$'
- at a particular location, we can index into the string at
- any other location that provides distinguishing characters). */
-
-/* Define NO_DOLLAR_IN_LABEL in your favorite tm file if your assembler
- doesn't allow '$' in symbol names. */
-#ifndef NO_DOLLAR_IN_LABEL
-
-#define JOINER '$'
-
-#define VPTR_NAME "$v"
-#define THROW_NAME "$eh_throw"
-#define DESTRUCTOR_DECL_PREFIX "_$_"
-#define IN_CHARGE_NAME "__in$chrg"
-#define AUTO_VTABLE_NAME "__vtbl$me__"
-#define AUTO_TEMP_NAME "_$tmp_"
-#define AUTO_TEMP_FORMAT "_$tmp_%d"
-#define VTBL_PTR_TYPE "$vtbl_ptr_type"
-#define VTABLE_BASE "$vb"
-#define VTABLE_NAME_FORMAT "_vt$%s"
-#define VFIELD_BASE "$vf"
-#define VFIELD_NAME "_vptr$"
-#define VFIELD_NAME_FORMAT "_vptr$%s"
-#define VBASE_NAME "_vb$"
-#define VBASE_NAME_FORMAT "_vb$%s"
-#define STATIC_NAME_FORMAT "_%s$%s"
-#define FILE_FUNCTION_FORMAT "_GLOBAL_$D$%s"
-#define ANON_AGGRNAME_FORMAT "$_%d"
-
-#else /* NO_DOLLAR_IN_LABEL */
-
-#ifndef NO_DOT_IN_LABEL
-
-#define JOINER '.'
-
-#define VPTR_NAME ".v"
-#define THROW_NAME ".eh_throw"
-#define DESTRUCTOR_DECL_PREFIX "_._"
-#define IN_CHARGE_NAME "__in.chrg"
-#define AUTO_VTABLE_NAME "__vtbl.me__"
-#define AUTO_TEMP_NAME "_.tmp_"
-#define AUTO_TEMP_FORMAT "_.tmp_%d"
-#define VTBL_PTR_TYPE ".vtbl_ptr_type"
-#define VTABLE_BASE ".vb"
-#define VTABLE_NAME_FORMAT "_vt.%s"
-#define VFIELD_BASE ".vf"
-#define VFIELD_NAME "_vptr."
-#define VFIELD_NAME_FORMAT "_vptr.%s"
-#define VBASE_NAME "_vb."
-#define VBASE_NAME_FORMAT "_vb.%s"
-#define STATIC_NAME_FORMAT "_%s.%s"
-#define FILE_FUNCTION_FORMAT "_GLOBAL_.D.%s"
-
-#define ANON_AGGRNAME_FORMAT "._%d"
-
-#else /* NO_DOT_IN_LABEL */
-
-#define VPTR_NAME "__vptr"
-#define VPTR_NAME_P(ID_NODE) \
- (!strncmp (IDENTIFIER_POINTER (ID_NODE), VPTR_NAME, sizeof (VPTR_NAME) - 1))
-#define THROW_NAME "__eh_throw"
-#define DESTRUCTOR_DECL_PREFIX "__destr_"
-#define DESTRUCTOR_NAME_P(ID_NODE) \
- (!strncmp (IDENTIFIER_POINTER (ID_NODE), DESTRUCTOR_DECL_PREFIX, \
- sizeof (DESTRUCTOR_DECL_PREFIX) - 1))
-#define IN_CHARGE_NAME "__in_chrg"
-#define AUTO_VTABLE_NAME "__vtbl_me__"
-#define AUTO_TEMP_NAME "__tmp_"
-#define TEMP_NAME_P(ID_NODE) \
- (!strncmp (IDENTIFIER_POINTER (ID_NODE), AUTO_TEMP_NAME, \
- sizeof (AUTO_TEMP_NAME) - 1))
-#define AUTO_TEMP_FORMAT "__tmp_%d"
-#define VTBL_PTR_TYPE "__vtbl_ptr_type"
-#define VTABLE_BASE "__vtb"
-#define VTABLE_NAME_FORMAT "__vt_%s"
-#define VFIELD_BASE "__vfb"
-#define VFIELD_NAME "__vptr_"
-#define VFIELD_NAME_P(ID_NODE) \
- (!strncmp (IDENTIFIER_POINTER (ID_NODE), VFIELD_NAME, \
- sizeof (VFIELD_NAME) - 1))
-#define VFIELD_NAME_FORMAT "_vptr_%s"
-#define VBASE_NAME "__vb_"
-#define VBASE_NAME_P(ID_NODE) \
- (!strncmp (IDENTIFIER_POINTER (ID_NODE), VBASE_NAME, \
- sizeof (VBASE_NAME) - 1))
-#define VBASE_NAME_FORMAT "__vb_%s"
-#define STATIC_NAME_FORMAT "__static_%s_%s"
-#define FILE_FUNCTION_FORMAT "__GLOBAL_D_%s"
-
-#define ANON_AGGRNAME_PREFIX "__anon_"
-#define ANON_AGGRNAME_P(ID_NODE) \
- (!strncmp (IDENTIFIER_POINTER (ID_NODE), ANON_AGGRNAME_PREFIX, \
- sizeof (ANON_AGGRNAME_PREFIX) - 1))
-#define ANON_AGGRNAME_FORMAT "__anon_%d"
-#define ANON_PARMNAME_FORMAT "__%d"
-#define ANON_PARMNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \
- && IDENTIFIER_POINTER (ID_NODE)[1] == '_' \
- && IDENTIFIER_POINTER (ID_NODE)[2] <= '9')
-
-#endif /* NO_DOT_IN_LABEL */
-#endif /* NO_DOLLAR_IN_LABEL */
-
-#define THIS_NAME "this"
-#define DESTRUCTOR_NAME_FORMAT "~%s"
-#define FILE_FUNCTION_PREFIX_LEN 9
-#define VTABLE_DELTA_NAME "delta"
-#define VTABLE_DELTA2_NAME "delta2"
-#define VTABLE_INDEX_NAME "index"
-#define VTABLE_PFN_NAME "pfn"
-#define EXCEPTION_CLEANUP_NAME "exception cleanup"
-
-#define THIS_NAME_P(ID_NODE) (strcmp(IDENTIFIER_POINTER (ID_NODE), "this") == 0)
-
-#if !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL)
-
-#define VPTR_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == JOINER \
- && IDENTIFIER_POINTER (ID_NODE)[1] == 'v')
-#define DESTRUCTOR_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[1] == JOINER)
-
-#define VTABLE_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[1] == 'v' \
- && IDENTIFIER_POINTER (ID_NODE)[2] == 't' \
- && IDENTIFIER_POINTER (ID_NODE)[3] == JOINER)
-
-#define VBASE_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[1] == 'v' \
- && IDENTIFIER_POINTER (ID_NODE)[2] == 'b' \
- && IDENTIFIER_POINTER (ID_NODE)[3] == JOINER)
-
-#define OPERATOR_TYPENAME_P(ID_NODE) \
- (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \
- && IDENTIFIER_POINTER (ID_NODE)[1] == '_' \
- && IDENTIFIER_POINTER (ID_NODE)[2] == 'o' \
- && IDENTIFIER_POINTER (ID_NODE)[3] == 'p')
-
-#define TEMP_NAME_P(ID_NODE) (!strncmp (IDENTIFIER_POINTER (ID_NODE), AUTO_TEMP_NAME, sizeof (AUTO_TEMP_NAME)-1))
-#define VFIELD_NAME_P(ID_NODE) (!strncmp (IDENTIFIER_POINTER (ID_NODE), VFIELD_NAME, sizeof(VFIELD_NAME)-1))
-
-/* For anonymous aggregate types, we need some sort of name to
- hold on to. In practice, this should not appear, but it should
- not be harmful if it does. */
-#define ANON_AGGRNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == JOINER \
- && IDENTIFIER_POINTER (ID_NODE)[1] == '_')
-#define ANON_PARMNAME_FORMAT "_%d"
-#define ANON_PARMNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \
- && IDENTIFIER_POINTER (ID_NODE)[1] <= '9')
-#endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */
-
-/* Define the sets of attributes that member functions and baseclasses
- can have. These are sensible combinations of {public,private,protected}
- cross {virtual,non-virtual}. */
-
-enum visibility_type {
- visibility_default,
- visibility_public,
- visibility_private,
- visibility_protected,
- visibility_default_virtual,
- visibility_public_virtual,
- visibility_private_virtual
-};
-
-/* in cp-lex.c */
-extern tree current_unit_name, current_unit_language;
-
-/* Things for handling inline functions. */
-
-struct pending_inline
-{
- struct pending_inline *next; /* pointer to next in chain */
- int lineno; /* line number we got the text from */
- char *filename; /* name of file we were processing */
- tree fndecl; /* FUNCTION_DECL that brought us here */
- int token; /* token we were scanning */
- int token_value; /* value of token we were scanning (YYSTYPE) */
-
- char *buf; /* pointer to character stream */
- int len; /* length of stream */
- tree parm_vec, bindings; /* in case this is derived from a template */
- unsigned int can_free : 1; /* free this after we're done with it? */
- unsigned int deja_vu : 1; /* set iff we don't want to see it again. */
- unsigned int interface : 2; /* 0=interface 1=unknown 2=implementation */
-};
-
-/* in cp-method.c */
-extern struct pending_inline *pending_inlines;
-
-/* 1 for -fall-virtual: make every member function (except
- constructors) lay down in the virtual function table.
- Calls can then either go through the virtual function table or not,
- depending on whether we know what function will actually be called. */
-
-extern int flag_all_virtual;
-
-/* Positive values means that we cannot make optimizing assumptions about
- `this'. Negative values means we know `this' to be of static type. */
-
-extern int flag_this_is_variable;
-
-/* Controls whether enums and ints freely convert.
- 1 means with complete freedom.
- 0 means enums can convert to ints, but not vice-versa. */
-
-extern int flag_int_enum_equivalence;
-
-/* Nonzero means layout structures so that we can do garbage collection. */
-
-extern int flag_gc;
-
-/* Nonzero means generate 'dossiers' that give run-time type information. */
-
-extern int flag_dossier;
-
-/* Current end of entries in the gc obstack for stack pointer variables. */
-
-extern int current_function_obstack_index;
-
-/* Flag saying whether we have used the obstack in this function or not. */
-
-extern int current_function_obstack_usage;
-
-enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
-
-extern tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */
-
-/* The following two can be derived from the previous one */
-extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
-extern tree current_class_type; /* _TYPE: the type of the current class */
-
-/* Some macros for char-based bitfields. */
-#define B_SET(a,x) (a[x>>3] |= (1 << (x&7)))
-#define B_CLR(a,x) (a[x>>3] &= ~(1 << (x&7)))
-#define B_TST(a,x) (a[x>>3] & (1 << (x&7)))
-
-/* These are uses as bits in flags passed to build_method_call
- to control its error reporting behavior.
-
- LOOKUP_PROTECT means flag visibility violations.
- LOOKUP_COMPLAIN mean complain if no suitable member function
- matching the arguments is found.
- LOOKUP_NORMAL is just a combination of these two.
- LOOKUP_AGGR requires the instance to be of aggregate type.
- LOOKUP_NONVIRTUAL means make a direct call to the member function found
- LOOKUP_GLOBAL means search through the space of overloaded functions,
- rather than the space of member functions.
- LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already
- in the parameter list.
- LOOKUP_PROTECTED_OK means that even if the constructor we find appears
- to be non-visible to current scope, call it anyway.
- LOOKUP_NO_CONVERSION means that user-defined conversions are not
- permitted. Built-in conversions are permitted.
- LOOKUP_DESTRUCTOR means explicit call to destructor. */
-
-#define LOOKUP_PROTECT (1)
-#define LOOKUP_COMPLAIN (2)
-#define LOOKUP_NORMAL (3)
-#define LOOKUP_AGGR (4)
-#define LOOKUP_NONVIRTUAL (8)
-#define LOOKUP_GLOBAL (16)
-#define LOOKUP_HAS_IN_CHARGE (32)
-#define LOOKUP_SPECULATIVELY (64)
-#define LOOKUP_PROTECTED_OK (128)
-/* 256 is free */
-#define LOOKUP_NO_CONVERSION (512)
-#define LOOKUP_DESTRUCTOR (512)
-
-/* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST):
- purpose = friend name (IDENTIFIER_NODE);
- value = TREE_LIST of FUNCTION_DECLS;
- chain, type = EMPTY; */
-#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
-#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
-
-/* These macros are for accessing the fields of TEMPLATE...PARM nodes. */
-#define TEMPLATE_TYPE_TPARMLIST(NODE) TREE_PURPOSE (TYPE_FIELDS (NODE))
-#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TREE_VALUE (TYPE_FIELDS (NODE)))
-#define TEMPLATE_TYPE_SET_INFO(NODE,P,I) \
- (TYPE_FIELDS (NODE) = build_tree_list (P, build_int_2 (I, 0)))
-#define TEMPLATE_CONST_TPARMLIST(NODE) (*(tree*)&TREE_INT_CST_LOW(NODE))
-#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_HIGH(NODE))
-#define TEMPLATE_CONST_SET_INFO(NODE,P,I) \
- (TEMPLATE_CONST_TPARMLIST (NODE) = saved_parmlist, \
- TEMPLATE_CONST_IDX (NODE) = I)
-
-/* in cp-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 char **opname_tab, **assignop_tab;
-
-/* in cp-call.c */
-extern int rank_for_overload PROTO((struct candidate *, struct candidate *));
-extern void compute_conversion_costs PROTO((tree, tree, struct candidate *, int));
-extern int get_arglist_len_in_bytes PROTO((tree));
-extern tree build_vfield_ref PROTO((tree, tree));
-extern tree find_scoped_type PROTO((tree, tree, tree));
-extern tree resolve_scope_to_name PROTO((tree, tree));
-extern tree build_scoped_method_call PROTO((tree, tree, tree, tree));
-extern tree build_method_call PROTO((tree, tree, tree, tree, int));
-extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate *, int));
-extern tree build_overload_call PROTO((tree, tree, int, struct candidate *));
-extern tree build_overload_call_maybe PROTO((tree, tree, int, struct candidate *));
-
-/* in cp-class.c */
-extern tree build_vbase_pointer PROTO((tree, tree));
-extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
-extern tree build_vtable_entry PROTO((tree, tree));
-extern tree build_vfn_ref PROTO((tree *, tree, tree));
-extern void add_method PROTO((tree, tree *, tree));
-extern void duplicate_tag_error PROTO((tree));
-extern tree finish_struct PROTO((tree, tree, int));
-extern int resolves_to_fixed_type_p PROTO((tree, int *));
-extern void init_class_processing PROTO((void));
-extern void pushclass PROTO((tree, int));
-extern void popclass PROTO((int));
-extern void push_lang_context PROTO((tree));
-extern void pop_lang_context PROTO((void));
-extern int root_lang_context_p PROTO((void));
-extern tree instantiate_type PROTO((tree, tree, int));
-extern void print_class_statistics PROTO((void));
-
-/* in cp-cvt.c */
-extern tree convert_to_reference PROTO((tree, tree, tree, tree, int, char *, int, int));
-extern tree convert_from_reference PROTO((tree));
-extern tree convert_to_aggr PROTO((tree, tree, char **, int));
-extern tree convert_pointer_to PROTO((tree, tree));
-extern tree convert_pointer_to_vbase PROTO((tree, tree));
-extern tree convert PROTO((tree, tree));
-extern tree convert_force PROTO((tree, tree));
-extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
-extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *));
-extern int build_default_unary_type_conversion PROTO((enum tree_code, tree *));
-
-/* cp-decl.c */
-#ifdef PARANOID
-extern void binding_levels_sane PROTO((void));
-#endif
-extern int global_bindings_p PROTO((void));
-extern void keep_next_level PROTO((void));
-extern int kept_level_p PROTO((void));
-extern void declare_parm_level PROTO((void));
-extern void declare_implicit_exception PROTO((void));
-extern int have_exceptions_p PROTO((void));
-extern void declare_uninstantiated_type_level PROTO((void));
-extern int uninstantiated_type_level_p PROTO((void));
-extern void declare_pseudo_global_level PROTO((void));
-extern int pseudo_global_level_p PROTO((void));
-extern void pushlevel PROTO((int));
-extern void pushlevel_temporary PROTO((int));
-extern tree poplevel PROTO((int, int, int));
-extern void delete_block PROTO((tree));
-extern void insert_block PROTO((tree));
-extern void add_block_current_level PROTO((tree));
-extern void set_block PROTO((tree));
-extern void pushlevel_class PROTO((void));
-extern tree poplevel_class PROTO((void));
-/* skip print_other_binding_stack and print_binding_level */
-extern void print_binding_stack PROTO((void));
-extern void push_to_top_level PROTO((void));
-extern void pop_from_top_level PROTO((void));
-extern void set_identifier_type_value PROTO((tree, tree));
-extern void set_identifier_local_value PROTO((tree, tree));
-extern tree make_type_decl PROTO((tree, tree));
-extern void pushtag PROTO((tree, tree));
-extern tree make_anon_name PROTO((void));
-extern void clear_anon_tags PROTO((void));
-extern void adjust_type_value PROTO((tree));
-extern tree pushdecl PROTO((tree));
-extern tree pushdecl_top_level PROTO((tree));
-extern void push_overloaded_decl_top_level PROTO((tree, int));
-extern tree pushdecl_class_level PROTO((tree));
-extern int overloaded_globals_p PROTO((tree));
-extern tree push_overloaded_decl PROTO((tree, int));
-extern tree implicitly_declare PROTO((tree));
-extern tree lookup_label PROTO((tree));
-extern tree shadow_label PROTO((tree));
-extern tree define_label PROTO((char *, int, tree));
-extern void define_case_label PROTO((tree));
-extern tree getdecls PROTO((void));
-extern tree gettags PROTO((void));
-extern void set_current_level_tags_transparency PROTO((int));
-extern tree typedecl_for_tag PROTO((tree));
-extern tree lookup_name PROTO((tree, int));
-extern tree lookup_name_current_level PROTO((tree));
-extern void init_decl_processing PROTO((void));
-/* skipped define_function */
-extern void shadow_tag PROTO((tree));
-extern void grok_ctor_properties PROTO((tree, tree));
-extern tree groktypename PROTO((tree));
-extern tree start_decl PROTO((tree, tree, int, tree));
-extern void finish_decl PROTO((tree, tree, tree, int));
-extern int complete_array_type PROTO((tree, tree, int));
-extern tree grokdeclarator (); /* PROTO((tree, tree, enum decl_context, int, tree)); */
-extern tree xref_defn_tag PROTO((tree, tree, tree));
-extern tree xref_tag PROTO((tree, tree, tree));
-extern tree start_enum PROTO((tree));
-extern tree finish_enum PROTO((tree, tree));
-extern tree build_enumerator PROTO((tree, tree));
-extern tree grok_enum_decls PROTO((tree, tree));
-extern int start_function PROTO((tree, tree, tree, int));
-extern void store_parm_decls PROTO((void));
-extern void store_return_init PROTO((tree, tree));
-extern void finish_function PROTO((int, int));
-extern tree start_method PROTO((tree, tree, tree));
-extern tree finish_method PROTO((tree));
-extern void hack_incomplete_structures PROTO((tree));
-extern tree maybe_build_cleanup PROTO((tree));
-extern void cplus_expand_expr_stmt PROTO((tree));
-extern void finish_stmt PROTO((void));
-extern void pop_implicit_try_blocks PROTO((tree));
-extern void push_exception_cleanup PROTO((tree));
-extern void revert_static_member_fn PROTO((tree *, tree *, tree *));
-
-/* in cp-decl2.c */
-extern int lang_decode_option PROTO((char *));
-extern tree grok_method_quals PROTO((tree, tree, tree));
-extern void grokclassfn PROTO((tree, tree, tree, enum overload_flags, tree));
-extern void bad_specifiers PROTO((char *, int, int, int, int));
-extern void check_classfn PROTO((tree, tree, tree));
-extern tree grokfield PROTO((tree, tree, tree, tree, tree));
-extern tree grokbitfield PROTO((tree, tree, tree));
-extern tree groktypefield PROTO((tree, tree));
-extern tree grokoptypename PROTO((tree, int));
-extern tree build_push_scope PROTO((tree, tree));
-extern tree constructor_name PROTO((tree));
-extern void setup_vtbl_ptr PROTO((void));
-extern void mark_inline_for_output PROTO((tree));
-extern void clear_temp_name PROTO((void));
-extern tree get_temp_name PROTO((tree, int));
-extern tree get_temp_regvar PROTO((tree, tree));
-extern void finish_anon_union PROTO((tree));
-extern tree finish_table PROTO((tree, tree, tree, int));
-extern void finish_builtin_type PROTO((tree, char *, tree *, int, tree));
-extern tree coerce_new_type PROTO((tree));
-extern tree coerce_delete_type PROTO((tree));
-extern void walk_vtables PROTO((void (*)(), void (*)()));
-extern void finish_file PROTO((void));
-
-/* in cp-dem.c */
-extern char *cplus_demangle PROTO((char *));
-
-/* in cp-edsel.c */
-
-/* in cp-except.c */
-extern tree lookup_exception_cname PROTO((tree, tree, tree));
-extern tree lookup_exception_tname PROTO((tree));
-extern tree lookup_exception_object PROTO((tree, tree, int));
-extern tree lookup_exception_type PROTO((tree, tree, tree));
-extern tree finish_exception PROTO((tree, tree));
-extern void finish_exception_decl PROTO((tree, tree));
-extern void end_exception_decls PROTO((void));
-extern void cplus_expand_start_try PROTO((int));
-extern tree cplus_expand_end_try PROTO((int));
-extern void cplus_expand_start_except PROTO((tree, tree));
-extern void cplus_expand_end_except PROTO((tree));
-extern void cplus_expand_raise PROTO((tree, tree, tree, int));
-extern tree ansi_exception_object_lookup PROTO((tree));
-extern void cplus_expand_throw PROTO((tree));
-extern tree cplus_expand_start_catch PROTO((tree));
-extern tree ansi_expand_start_catch PROTO((tree));
-extern void cplus_expand_end_catch PROTO((int));
-extern void cplus_expand_reraise PROTO((tree));
-extern void setup_exception_throw_decl PROTO((void));
-extern void init_exception_processing PROTO((void));
-extern void init_exception_processing_1 PROTO((void));
-
-/* in cp-expr.c */
-/* skip cplus_expand_expr */
-extern void init_cplus_expand PROTO((void));
-extern void fixup_result_decl PROTO((tree, struct rtx_def *));
-extern int decl_in_memory_p PROTO((tree));
-
-/* in cp-gc.c */
-extern int type_needs_gc_entry PROTO((tree));
-extern int value_safe_from_gc PROTO((tree, tree));
-extern void build_static_gc_entry PROTO((tree, tree));
-extern tree protect_value_from_gc PROTO((tree, tree));
-extern tree build_headof PROTO((tree));
-extern tree build_classof PROTO((tree));
-extern tree build_t_desc PROTO((tree, int));
-extern tree build_i_desc PROTO((tree));
-extern tree build_m_desc PROTO((tree));
-extern void expand_gc_prologue_and_epilogue PROTO((void));
-extern void lang_expand_end_bindings PROTO((struct rtx_def *, struct rtx_def *));
-extern void init_gc_processing PROTO((void));
-
-/* in cp-init.c */
-extern void emit_base_init PROTO((tree, int));
-extern void check_base_init PROTO((tree));
-extern tree build_virtual_init PROTO((tree, tree, tree));
-extern void do_member_init PROTO((tree, tree, tree));
-extern void expand_member_init PROTO((tree, tree, tree));
-extern void expand_aggr_init PROTO((tree, tree, int));
-extern int is_aggr_typedef PROTO((tree, int));
-extern tree build_member_call PROTO((tree, tree, tree));
-extern tree build_offset_ref PROTO((tree, tree));
-extern tree get_member_function PROTO((tree *, tree, tree));
-extern tree resolve_offset_ref PROTO((tree));
-extern tree decl_constant_value PROTO((tree));
-extern int is_friend PROTO((tree, tree));
-extern void xref_friend PROTO((tree, tree, tree));
-extern void xref_friends PROTO((tree, tree, tree));
-extern void make_friend_class PROTO((tree, tree));
-extern tree do_friend PROTO((tree, tree, tree, tree, enum overload_flags, tree));
-extern void embrace_waiting_friends PROTO((tree));
-extern tree build_builtin_call PROTO((tree, tree, tree));
-extern tree build_new PROTO((tree, tree, tree, int));
-extern tree expand_vec_init PROTO((tree, tree, tree, tree, int));
-extern tree build_x_delete PROTO((tree, tree, int, tree));
-extern tree build_delete PROTO((tree, tree, tree, int, int, int));
-extern tree build_vbase_delete PROTO((tree, tree));
-extern tree build_vec_delete PROTO((tree, tree, tree, tree, tree, tree));
-
-/* in cp-input.c */
-
-/* in cp-lex.c */
-extern tree make_pointer_declarator PROTO((tree, tree));
-extern tree make_reference_declarator PROTO((tree, tree));
-extern char *operator_name_string PROTO((tree));
-extern void lang_init PROTO((void));
-extern void lang_finish PROTO((void));
-extern void init_filename_times PROTO((void));
-extern void reinit_lang_specific PROTO((void));
-extern void init_lex PROTO((void));
-extern void reinit_parse_for_function PROTO((void));
-extern int *init_parse PROTO((void));
-extern void print_parse_statistics PROTO((void));
-extern void extract_interface_info PROTO((void));
-extern void set_vardecl_interface_info PROTO((tree, tree));
-extern void do_pending_inlines PROTO((void));
-extern void process_next_inline PROTO((tree));
-#if 0
-extern void consume_string PROTO((struct obstack *));
-#endif
-/* skip restore_pending_input */
-extern void yyungetc PROTO((int, int));
-extern void reinit_parse_for_method PROTO((int, tree));
-#if 0
-extern void reinit_parse_for_block PROTO((int, struct obstack *, int));
-#endif
-extern tree cons_up_default_function PROTO((tree, tree, int));
-extern void check_for_missing_semicolon PROTO((tree));
-extern void note_got_semicolon PROTO((tree));
-extern void note_list_got_semicolon PROTO((tree));
-extern int check_newline PROTO((void));
-extern void dont_see_typename PROTO((void));
-extern int identifier_type PROTO((tree));
-extern void see_typename PROTO((void));
-extern tree do_identifier PROTO((tree));
-extern tree identifier_typedecl_value PROTO((tree));
-extern int real_yylex PROTO((void));
-extern tree build_lang_decl PROTO((enum tree_code, tree, tree));
-extern tree build_lang_field_decl PROTO((enum tree_code, tree, tree));
-extern void copy_lang_decl PROTO((tree));
-extern tree make_lang_type PROTO((enum tree_code));
-extern void copy_decl_lang_specific PROTO((tree));
-extern void dump_time_statistics PROTO((void));
-/* extern void compiler_error PROTO((char *, HOST_WIDE_INT, HOST_WIDE_INT)); */
-extern void compiler_error_with_decl PROTO((tree, char *));
-extern void yyerror PROTO((char *));
-
-/* in cp-method.c */
-extern void init_method PROTO((void));
-extern tree make_anon_parm_name PROTO((void));
-extern void clear_anon_parm_name PROTO((void));
-extern char *fndecl_as_string PROTO((tree, tree, int));
-extern char *type_as_string PROTO((tree));
-extern char *decl_as_string PROTO((tree));
-extern void do_inline_function_hair PROTO((tree, tree));
-/* skip report_type_mismatch */
-extern char *build_overload_name PROTO((tree, int, int));
-extern tree cplus_exception_name PROTO((tree));
-extern tree build_decl_overload PROTO((tree, tree, int));
-extern tree build_typename_overload PROTO((tree));
-extern tree build_t_desc_overload PROTO((tree));
-extern void declare_overloaded PROTO((tree));
-#ifdef NO_AUTO_OVERLOAD
-extern int is_overloaded PROTO((tree));
-#endif
-extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree));
-extern tree hack_identifier PROTO((tree, tree, int));
-extern tree build_component_type_expr PROTO((tree, tree, tree, int));
-
-/* in cp-pt.c */
-extern void begin_template_parm_list PROTO((void));
-extern tree process_template_parm PROTO((tree, tree));
-extern tree end_template_parm_list PROTO((tree));
-extern void end_template_decl PROTO((tree, tree, tree));
-extern tree lookup_template_class PROTO((tree, tree, tree));
-extern void push_template_decls PROTO((tree, tree, int));
-extern void pop_template_decls PROTO((tree, tree, int));
-extern int uses_template_parms PROTO((tree));
-extern void instantiate_member_templates PROTO((tree));
-extern tree instantiate_class_template PROTO((tree, int));
-extern tree instantiate_template PROTO((tree, tree *));
-extern void undo_template_name_overload PROTO((tree, int));
-extern void overload_template_name PROTO((tree, int));
-extern void end_template_instantiation PROTO((tree, tree));
-extern void reinit_parse_for_template PROTO((int, tree, tree));
-extern int type_unification PROTO((tree, tree *, tree, tree, int *));
-extern int do_pending_expansions PROTO((void));
-extern void do_pending_templates PROTO((void));
-
-/* in cp-search.c */
-extern tree make_memoized_table_entry PROTO((tree, tree, int));
-extern void push_memoized_context PROTO((tree, int));
-extern void pop_memoized_context PROTO((int));
-extern tree get_binfo PROTO((tree, tree, int));
-extern int get_base_distance PROTO((tree, tree, int, tree *));
-extern enum visibility_type check_visibility PROTO((tree, tree));
-extern tree lookup_field PROTO((tree, tree, int, int));
-extern tree lookup_nested_field PROTO((tree, int));
-extern tree lookup_fnfields PROTO((tree, tree, int));
-extern HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)()));
-extern int tree_needs_constructor_p PROTO((tree, int));
-extern int tree_has_any_destructor_p PROTO((tree, int));
-extern tree get_first_matching_virtual PROTO((tree, tree, int));
-extern tree get_abstract_virtuals PROTO((tree));
-extern tree get_baselinks PROTO((tree, tree, tree));
-extern tree next_baselink PROTO((tree));
-extern tree init_vbase_pointers PROTO((tree, tree));
-extern tree build_vbase_vtables_init PROTO((tree, tree, tree, tree, int));
-extern void clear_search_slots PROTO((tree));
-extern tree get_vbase_types PROTO((tree));
-extern void build_mi_matrix PROTO((tree));
-extern void free_mi_matrix PROTO((void));
-extern void build_mi_virtuals PROTO((int, int));
-extern void add_mi_virtuals PROTO((int, tree));
-extern void report_ambiguous_mi_virtuals PROTO((int, tree));
-extern void note_debug_info_needed PROTO((tree));
-extern void push_class_decls PROTO((tree));
-extern void pop_class_decls PROTO((tree));
-extern tree build_type_pathname PROTO((char *, tree, tree));
-extern void unmark_finished_struct PROTO((tree));
-extern void print_search_statistics PROTO((void));
-extern void init_search_processing PROTO((void));
-extern void reinit_search_statistics PROTO((void));
-
-/* in cp-spew.c */
-extern void init_spew PROTO((void));
-extern int yylex PROTO((void));
-extern tree arbitrate_lookup PROTO((tree, tree, tree));
-
-/* in cp-tree.c */
-extern int lvalue_p PROTO((tree));
-extern int lvalue_or_else PROTO((tree, char *));
-extern tree build_cplus_new PROTO((tree, tree, int));
-extern tree break_out_cleanups PROTO((tree));
-extern tree break_out_calls PROTO((tree));
-extern tree build_cplus_method_type PROTO((tree, tree, tree));
-extern tree build_cplus_staticfn_type PROTO((tree, tree, tree));
-extern tree build_cplus_array_type PROTO((tree, tree));
-extern void propagate_binfo_offsets PROTO((tree, tree));
-extern int layout_vbasetypes PROTO((tree, int));
-extern tree layout_basetypes PROTO((tree, tree));
-extern int list_hash PROTO((tree));
-extern tree list_hash_lookup PROTO((int, tree));
-extern void list_hash_add PROTO((int, tree));
-extern tree list_hash_canon PROTO((int, tree));
-extern tree hash_tree_cons PROTO((int, int, int, tree, tree, tree));
-extern tree hash_tree_chain PROTO((tree, tree));
-extern tree hash_chainon PROTO((tree, tree));
-extern tree get_decl_list PROTO((tree));
-extern tree list_hash_lookup_or_cons PROTO((tree));
-extern tree make_binfo PROTO((tree, tree, tree, tree, tree));
-extern tree copy_binfo PROTO((tree));
-extern tree binfo_value PROTO((tree, tree));
-extern tree reverse_path PROTO((tree));
-extern tree virtual_member PROTO((tree, tree));
-extern tree virtual_offset PROTO((tree, tree, tree));
-extern void debug_binfo PROTO((tree));
-extern int decl_list_length PROTO((tree));
-extern tree fnaddr_from_vtable_entry PROTO((tree));
-extern void set_fnaddr_from_vtable_entry PROTO((tree, tree));
-extern tree function_arg_chain PROTO((tree));
-extern int promotes_to_aggr_type PROTO((tree, enum tree_code));
-extern int is_aggr_type_2 PROTO((tree, tree));
-extern void message_2_types PROTO((void (*)(), char *, tree, tree));
-extern char *lang_printable_name PROTO((tree));
-extern tree build_exception_variant PROTO((tree, tree, tree));
-extern tree copy_to_permanent PROTO((tree));
-extern void print_lang_statistics PROTO((void));
-/* skip __eprintf */
-extern tree array_type_nelts_total PROTO((tree));
-extern tree array_type_nelts_top PROTO((tree));
-
-/* in cp-typeck.c */
-extern tree target_type PROTO((tree));
-extern tree require_complete_type PROTO((tree));
-extern int type_unknown_p PROTO((tree));
-extern tree require_instantiated_type PROTO((tree, tree, tree));
-extern tree commonparms PROTO((tree, tree));
-extern tree common_type PROTO((tree, tree));
-extern int compexcepttypes PROTO((tree, tree, int));
-extern int comptypes PROTO((tree, tree, int));
-extern int comp_target_types PROTO((tree, tree, int));
-extern tree common_base_types PROTO((tree, tree));
-extern int compparms PROTO((tree, tree, int));
-extern int comp_target_types PROTO((tree, tree, int));
-extern tree unsigned_type PROTO((tree));
-extern tree signed_type PROTO((tree));
-extern tree signed_or_unsigned_type PROTO((int, tree));
-extern tree c_sizeof PROTO((tree));
-extern tree c_sizeof_nowarn PROTO((tree));
-extern tree c_alignof PROTO((tree));
-extern tree default_conversion PROTO((tree));
-extern tree build_component_ref_1 PROTO((tree, tree, int));
-extern tree build_component_ref PROTO((tree, tree, tree, int));
-extern tree build_x_indirect_ref PROTO((tree, char *));
-extern tree build_indirect_ref PROTO((tree, char *));
-extern tree build_x_array_ref PROTO((tree, tree));
-extern tree build_array_ref PROTO((tree, tree));
-extern tree build_x_function_call PROTO((tree, tree, tree));
-extern tree build_function_call_real PROTO((tree, tree, int));
-extern tree build_function_call PROTO((tree, tree));
-extern tree build_function_call_maybe PROTO((tree, tree));
-extern tree convert_arguments PROTO((tree, tree, tree, tree, int));
-extern tree build_x_binary_op PROTO((enum tree_code, tree, tree));
-extern tree build_binary_op PROTO((enum tree_code, tree, tree, int));
-extern tree build_binary_op_nodefault PROTO((enum tree_code, tree, tree, enum tree_code));
-extern tree build_component_addr PROTO((tree, tree, char *));
-extern tree build_x_unary_op PROTO((enum tree_code, tree));
-extern tree build_unary_op PROTO((enum tree_code, tree, int));
-extern tree unary_complex_lvalue PROTO((enum tree_code, tree));
-extern int mark_addressable PROTO((tree));
-extern tree build_x_conditional_expr PROTO((tree, tree, tree));
-extern tree build_conditional_expr PROTO((tree, tree, tree));
-extern tree build_x_compound_expr PROTO((tree));
-extern tree build_compound_expr PROTO((tree));
-extern tree build_c_cast PROTO((tree, tree));
-extern tree build_modify_expr PROTO((tree, enum tree_code, tree));
-extern int language_lvalue_valid PROTO((tree));
-extern void warn_for_assignment PROTO((char *, char *, char *, tree, int, int));
-extern tree convert_for_initialization PROTO((tree, tree, tree, int, char *, tree, int));
-extern void c_expand_asm_operands PROTO((tree, tree, tree, tree, int, char *, int));
-extern void c_expand_return PROTO((tree));
-extern tree c_expand_start_case PROTO((tree));
-extern void record_format_info PROTO((tree, int, int, int));
-extern tree build_component_ref PROTO((tree, tree, tree, int));
-
-/* in cp-type2.c */
-extern tree error_not_base_type PROTO((tree, tree));
-extern tree binfo_or_else PROTO((tree, tree));
-extern void error_with_aggr_type (); /* PROTO((tree, char *, HOST_WIDE_INT)); */
-extern void readonly_error PROTO((tree, char *, int));
-extern void abstract_virtuals_error PROTO((tree, tree));
-extern void incomplete_type_error PROTO((tree, tree));
-extern void my_friendly_abort PROTO((int));
-extern void my_friendly_assert PROTO((int, int));
-extern tree store_init_value PROTO((tree, tree));
-extern tree digest_init PROTO((tree, tree, tree *));
-extern tree build_scoped_ref PROTO((tree, tree));
-extern tree build_x_arrow PROTO((tree));
-extern tree build_m_component_ref PROTO((tree, tree));
-extern tree build_functional_cast PROTO((tree, tree));
-extern char *enum_name_string PROTO((tree, tree));
-extern void report_case_error PROTO((int, tree, tree, tree));
-
-/* in cp-xref.c */
-extern void GNU_xref_begin PROTO((char *));
-extern void GNU_xref_end PROTO((int));
-extern void GNU_xref_file PROTO((char *));
-extern void GNU_xref_start_scope PROTO((HOST_WIDE_INT));
-extern void GNU_xref_end_scope PROTO((HOST_WIDE_INT, HOST_WIDE_INT, int, int, int));
-extern void GNU_xref_def PROTO((tree, char *));
-extern void GNU_xref_decl PROTO((tree, tree));
-extern void GNU_xref_call PROTO((tree, char *));
-extern void GNU_xref_function PROTO((tree, tree));
-extern void GNU_xref_assign PROTO((tree));
-extern void GNU_xref_hier PROTO((char *, char *, int, int, int));
-extern void GNU_xref_member PROTO((tree, tree));
-
-/* -- end of C++ */
diff --git a/gnu/gcc2/cc1plus/cp-type2.c b/gnu/gcc2/cc1plus/cp-type2.c
deleted file mode 100644
index eaa009e84114..000000000000
--- a/gnu/gcc2/cc1plus/cp-type2.c
+++ /dev/null
@@ -1,1635 +0,0 @@
-/* Report error messages, build initializers, and perform
- some front-end optimizations for C++ compiler.
- Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-
-/* This file is part of the C++ front end.
- It contains routines to build C++ expressions given their operands,
- including computing the types of the result, C and C++ specific error
- checks, and some optimization.
-
- There are also routines to build RETURN_STMT nodes and CASE_STMT nodes,
- and to process initializations in declarations (since they work
- like a strange sort of assignment). */
-
-#include "config.h"
-#include <stdio.h>
-#include "tree.h"
-#include "cp-tree.h"
-#include "flags.h"
-
-static tree process_init_constructor ();
-extern void pedwarn (), error ();
-
-extern int errorcount;
-extern int sorrycount;
-
-/* Print an error message stemming from an attempt to use
- BASETYPE as a base class for TYPE. */
-tree
-error_not_base_type (basetype, type)
- tree basetype, type;
-{
- tree name1;
- tree name2;
- if (TREE_CODE (basetype) == FUNCTION_DECL)
- basetype = DECL_CLASS_CONTEXT (basetype);
- name1 = TYPE_NAME (basetype);
- name2 = TYPE_NAME (type);
- if (TREE_CODE (name1) == TYPE_DECL)
- name1 = DECL_NAME (name1);
- if (TREE_CODE (name2) == TYPE_DECL)
- name2 = DECL_NAME (name2);
- error ("type `%s' is not a base type for type `%s'",
- IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2));
- return error_mark_node;
-}
-
-tree
-binfo_or_else (parent_or_type, type)
- tree parent_or_type, type;
-{
- tree binfo;
- if (TYPE_MAIN_VARIANT (parent_or_type) == TYPE_MAIN_VARIANT (type))
- return parent_or_type;
- if (binfo = get_binfo (parent_or_type, TYPE_MAIN_VARIANT (type), 0))
- {
- if (binfo == error_mark_node)
- return NULL_TREE;
- return binfo;
- }
- error_not_base_type (parent_or_type, type);
- return NULL_TREE;
-}
-
-/* Print an error message stemming from an invalid use of an
- aggregate type.
-
- TYPE is the type or binfo which draws the error.
- MSG is the message to print.
- ARG is an optional argument which may provide more information. */
-void
-error_with_aggr_type (type, msg, arg)
- tree type;
- char *msg;
- HOST_WIDE_INT arg;
-{
- tree name;
-
- if (TREE_CODE (type) == TREE_VEC)
- type = BINFO_TYPE (type);
-
- name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- error (msg, IDENTIFIER_POINTER (name), arg);
-}
-
-/* According to ARM $7.1.6, "A `const' object may be initialized, but its
- value may not be changed thereafter. Thus, we emit hard errors for these,
- rather than just pedwarns. If `SOFT' is 1, then we just pedwarn. (For
- example, conversions to references.) */
-void
-readonly_error (arg, string, soft)
- tree arg;
- char *string;
- int soft;
-{
- char *fmt;
- void (*fn)();
-
- if (soft)
- fn = pedwarn;
- else
- fn = error;
-
- if (TREE_CODE (arg) == COMPONENT_REF)
- {
- if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
- fmt = "%s of member `%s' in read-only structure";
- else
- fmt = "%s of read-only member `%s'";
- (*fn) (fmt, string, lang_printable_name (TREE_OPERAND (arg, 1)));
- }
- else if (TREE_CODE (arg) == VAR_DECL)
- {
- if (DECL_LANG_SPECIFIC (arg)
- && DECL_IN_AGGR_P (arg)
- && !TREE_STATIC (arg))
- fmt = "%s of constant field `%s'";
- else
- fmt = "%s of read-only variable `%s'";
- (*fn) (fmt, string, lang_printable_name (arg));
- }
- else if (TREE_CODE (arg) == PARM_DECL)
- (*fn) ("%s of read-only parameter `%s'", string,
- lang_printable_name (arg));
- else if (TREE_CODE (arg) == INDIRECT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE
- && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL
- || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))
- (*fn) ("%s of read-only reference `%s'",
- string, lang_printable_name (TREE_OPERAND (arg, 0)));
- else
- (*fn) ("%s of read-only location", string);
-}
-
-/* Print an error message for invalid use of a type which declares
- virtual functions which are not inheritable. */
-void
-abstract_virtuals_error (decl, type)
- tree decl;
- tree type;
-{
- char *typename = TYPE_NAME_STRING (type);
- tree u = CLASSTYPE_ABSTRACT_VIRTUALS (type);
-
- if (decl)
- {
- if (TREE_CODE (decl) == RESULT_DECL)
- return;
-
- if (TREE_CODE (decl) == VAR_DECL)
- error_with_decl (decl, "cannot declare variable `%s' to be of type `%s'", typename);
- else if (TREE_CODE (decl) == PARM_DECL)
- error_with_decl (decl, "cannot declare parameter `%s' to be of type `%s'", typename);
- else if (TREE_CODE (decl) == FIELD_DECL)
- error_with_decl (decl, "cannot declare field `%s' to be of type `%s'", typename);
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- error_with_decl (decl, "invalid return type for method `%s'");
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- error_with_decl (decl, "invalid return type for function `%s'");
- }
- else error ("cannot allocate an object of type `%s'", typename);
- /* Only go through this once. */
- if (TREE_PURPOSE (u) == NULL_TREE)
- {
- error (" since the following virtual functions are abstract:");
- TREE_PURPOSE (u) = error_mark_node;
- while (u)
- {
- error_with_decl (TREE_VALUE (u), "\t%s");
- u = TREE_CHAIN (u);
- }
- }
- else error (" since type `%s' has abstract virtual functions", typename);
-}
-
-/* Print an error message for invalid use of an incomplete type.
- VALUE is the expression that was used (or 0 if that isn't known)
- and TYPE is the type that was invalid. */
-
-void
-incomplete_type_error (value, type)
- tree value;
- tree type;
-{
- char *errmsg;
-
- /* Avoid duplicate error message. */
- if (TREE_CODE (type) == ERROR_MARK)
- return;
-
- if (value != 0 && (TREE_CODE (value) == VAR_DECL
- || TREE_CODE (value) == PARM_DECL))
- error ("`%s' has an incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (value)));
- else
- {
- retry:
- /* We must print an error message. Be clever about what it says. */
-
- switch (TREE_CODE (type))
- {
- case RECORD_TYPE:
- errmsg = "invalid use of undefined type `struct %s'";
- break;
-
- case UNION_TYPE:
- errmsg = "invalid use of undefined type `union %s'";
- break;
-
- case ENUMERAL_TYPE:
- errmsg = "invalid use of undefined type `enum %s'";
- break;
-
- case VOID_TYPE:
- error ("invalid use of void expression");
- return;
-
- case ARRAY_TYPE:
- if (TYPE_DOMAIN (type))
- {
- type = TREE_TYPE (type);
- goto retry;
- }
- error ("invalid use of array with unspecified bounds");
- return;
-
- case OFFSET_TYPE:
- error ("invalid use of member type (did you forget the `&' ?)");
- return;
-
- default:
- my_friendly_abort (108);
- }
-
- error_with_aggr_type (type, errmsg);
- }
-}
-
-/* There are times when the compiler can get very confused, confused
- to the point of giving up by aborting, simply because of previous
- input errors. It is much better to have the user go back and
- correct those errors first, and see if it makes us happier, than it
- is to abort on him. This is because when one has a 10,000 line
- program, and the compiler comes back with ``core dump'', the user
- is left not knowing even where to begin to fix things and no place
- to even try and work around things.
-
- The parameter is to uniquely identify the problem to the user, so
- that they can say, I am having problem 59, and know that fix 7 will
- probably solve their problem. Or, we can document what problem
- 59 is, so they can understand how to work around it, should they
- ever run into it.
-
- Note, there will be no more calls in the C++ front end to abort,
- because the C++ front end is so unreliable still. The C front end
- can get away with calling abort, because for most of the calls to
- abort on most machines, it, I suspect, can be proven that it is
- impossible to ever call abort. The same is not yet true for C++,
- one day, maybe it will be.
-
- We used to tell people to "fix the above error[s] and try recompiling
- the program" via a call to fatal, but that message tended to look
- silly. So instead, we just do the equivalent of a call to fatal in the
- same situation (call exit). */
-
-/* First used: 0 (reserved), Last used: 347 */
-
-void
-my_friendly_abort (i)
- int i;
-{
- if (errorcount > 0 || sorrycount > 0)
- exit (34);
-
- if (i == 0)
- error ("Internal compiler error.");
- else
- error ("Internal compiler error %d.", i);
-
- fatal ("Please submit a full bug report to `bug-g++@prep.ai.mit.edu'.");
-}
-
-void
-my_friendly_assert (cond, where)
- int cond, where;
-{
- if (cond == 0)
- my_friendly_abort (where);
-}
-
-/* Return nonzero if VALUE is a valid constant-valued expression
- for use in initializing a static variable; one that can be an
- element of a "constant" initializer.
-
- Return 1 if the value is absolute; return 2 if it is relocatable.
- We assume that VALUE has been folded as much as possible;
- therefore, we do not need to check for such things as
- arithmetic-combinations of integers. */
-
-static int
-initializer_constant_valid_p (value)
- tree value;
-{
- switch (TREE_CODE (value))
- {
- case CONSTRUCTOR:
- return TREE_STATIC (value);
-
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- return 1;
-
- case ADDR_EXPR:
- return 2;
-
- case CONVERT_EXPR:
- case NOP_EXPR:
- /* Allow conversions between types of the same kind. */
- if (TREE_CODE (TREE_TYPE (value))
- == TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0));
- /* Allow (int) &foo. */
- if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE)
- return initializer_constant_valid_p (TREE_OPERAND (value, 0));
- return 0;
-
- case PLUS_EXPR:
- {
- int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0));
- int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1));
- if (valid0 == 1 && valid1 == 2)
- return 2;
- if (valid0 == 2 && valid1 == 1)
- return 2;
- return 0;
- }
-
- case MINUS_EXPR:
- {
- int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0));
- int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1));
- if (valid0 == 2 && valid1 == 1)
- return 2;
- return 0;
- }
- }
-
- return 0;
-}
-
-/* Perform appropriate conversions on the initial value of a variable,
- store it in the declaration DECL,
- and print any error messages that are appropriate.
- If the init is invalid, store an ERROR_MARK.
-
- C++: Note that INIT might be a TREE_LIST, which would mean that it is
- a base class initializer for some aggregate type, hopefully compatible
- with DECL. If INIT is a single element, and DECL is an aggregate
- type, we silently convert INIT into a TREE_LIST, allowing a constructor
- to be called.
-
- If INIT is a TREE_LIST and there is no constructor, turn INIT
- into a CONSTRUCTOR and use standard initialization techniques.
- Perhaps a warning should be generated?
-
- Returns value of initializer if initialization could not be
- performed for static variable. In that case, caller must do
- the storing. */
-
-tree
-store_init_value (decl, init)
- tree decl, init;
-{
- register tree value, type;
-
- /* If variable's type was invalidly declared, just ignore it. */
-
- type = TREE_TYPE (decl);
- if (TREE_CODE (type) == ERROR_MARK)
- return NULL_TREE;
-
- /* Take care of C++ business up here. */
- type = TYPE_MAIN_VARIANT (type);
-
- /* implicitly tests if IS_AGGR_TYPE. */
- if (TYPE_NEEDS_CONSTRUCTING (type))
- my_friendly_abort (109);
- else if (IS_AGGR_TYPE (type))
- {
- /* @@ This may be wrong, but I do not know what is right. */
- if (TREE_CODE (init) == TREE_LIST)
- {
- error_with_aggr_type (type, "constructor syntax used, but no constructor declared for type `%s'");
- init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));
- }
- }
- else if (TREE_CODE (init) == TREE_LIST
- && TREE_TYPE (init) != unknown_type_node)
- {
- if (TREE_CODE (decl) == RESULT_DECL)
- {
- if (TREE_CHAIN (init))
- {
- warning ("comma expression used to initialize return value");
- init = build_compound_expr (init);
- }
- else
- init = TREE_VALUE (init);
- }
- else if (TREE_TYPE (init) != 0
- && TREE_CODE (TREE_TYPE (init)) == OFFSET_TYPE)
- {
- /* Use the type of our variable to instantiate
- the type of our initializer. */
- init = instantiate_type (type, init, 1);
- }
- else if (TREE_CODE (init) == TREE_LIST
- && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- {
- error ("cannot initialize arrays using this syntax");
- return NULL_TREE;
- }
- else
- {
- error ("bad syntax in initialization");
- return NULL_TREE;
- }
- }
-
- /* End of special C++ code. */
-
- /* Digest the specified initializer into an expression. */
-
- value = digest_init (type, init, (tree *) 0);
-
- /* Store the expression if valid; else report error. */
-
- if (TREE_CODE (value) == ERROR_MARK)
- ;
- else if (TREE_STATIC (decl)
- && (! TREE_CONSTANT (value)
- || ! initializer_constant_valid_p (value)
- /* Since ctors and dtors are the only things that can
- reference vtables, and they are always written down
- the the vtable definition, we can leave the
- vtables in initialized data space.
- However, other initialized data cannot be initialized
- this way. Instead a global file-level initializer
- must do the job. */
- || (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))))
- return value;
- else
- {
- if (pedantic && TREE_CODE (value) == CONSTRUCTOR)
- {
- if (! TREE_CONSTANT (value) || ! TREE_STATIC (value))
- pedwarn ("ANSI C++ forbids non-constant aggregate initializer expressions");
- }
- }
- DECL_INITIAL (decl) = value;
- return NULL_TREE;
-}
-
-/* Digest the parser output INIT as an initializer for type TYPE.
- Return a C expression of type TYPE to represent the initial value.
-
- If TAIL is nonzero, it points to a variable holding a list of elements
- of which INIT is the first. We update the list stored there by
- removing from the head all the elements that we use.
- Normally this is only one; we use more than one element only if
- TYPE is an aggregate and INIT is not a constructor. */
-
-tree
-digest_init (type, init, tail)
- tree type, init, *tail;
-{
- enum tree_code code = TREE_CODE (type);
- tree element = 0;
- tree old_tail_contents;
- /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
- tree node which has no TREE_TYPE. */
- int raw_constructor
- = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
-
- /* By default, assume we use one element from a list.
- We correct this later in the sole case where it is not true. */
-
- if (tail)
- {
- old_tail_contents = *tail;
- *tail = TREE_CHAIN (*tail);
- }
-
- if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST
- && TREE_VALUE (init) == error_mark_node))
- return error_mark_node;
-
- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
- if (TREE_CODE (init) == NON_LVALUE_EXPR)
- init = TREE_OPERAND (init, 0);
-
- if (init && raw_constructor
- && CONSTRUCTOR_ELTS (init) != 0
- && TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0)
- {
- element = TREE_VALUE (CONSTRUCTOR_ELTS (init));
- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
- if (element && TREE_CODE (element) == NON_LVALUE_EXPR)
- element = TREE_OPERAND (element, 0);
- if (element == error_mark_node)
- return element;
- }
-
- /* Any type can be initialized from an expression of the same type,
- optionally with braces. */
-
- if (init && TREE_TYPE (init)
- && (TYPE_MAIN_VARIANT (TREE_TYPE (init)) == type
- || (code == ARRAY_TYPE && comptypes (TREE_TYPE (init), type, 1))))
- {
- if (pedantic && code == ARRAY_TYPE
- && TREE_CODE (init) != STRING_CST)
- pedwarn ("ANSI C++ forbids initializing array from array expression");
- if (TREE_CODE (init) == CONST_DECL)
- init = DECL_INITIAL (init);
- else if (TREE_READONLY_DECL_P (init))
- init = decl_constant_value (init);
- return init;
- }
-
- if (element && (TREE_TYPE (element) == type
- || (code == ARRAY_TYPE && TREE_TYPE (element)
- && comptypes (TREE_TYPE (element), type, 1))))
- {
- if (pedantic && code == ARRAY_TYPE)
- pedwarn ("ANSI C++ forbids initializing array from array expression");
- if (pedantic && (code == RECORD_TYPE || code == UNION_TYPE))
- pedwarn ("ANSI C++ forbids single nonscalar initializer with braces");
- if (TREE_CODE (element) == CONST_DECL)
- element = DECL_INITIAL (element);
- else if (TREE_READONLY_DECL_P (element))
- element = decl_constant_value (element);
- return element;
- }
-
- /* Check for initializing a union by its first field.
- Such an initializer must use braces. */
-
- if (code == UNION_TYPE)
- {
- tree result, field = TYPE_FIELDS (type);
-
- /* Find the first named field. ANSI decided in September 1990
- that only named fields count here. */
- while (field && DECL_NAME (field) == 0)
- field = TREE_CHAIN (field);
-
- if (field == 0)
- {
- error ("union with no named members cannot be initialized");
- return error_mark_node;
- }
-
- if (raw_constructor && !TYPE_NEEDS_CONSTRUCTING (type))
- {
- result = process_init_constructor (type, init, NULL_PTR);
- return result;
- }
-
- if (! raw_constructor)
- {
- error ("type mismatch in initialization");
- return error_mark_node;
- }
- if (element == 0)
- {
- if (!TYPE_NEEDS_CONSTRUCTING (type))
- {
- error ("union initializer requires one element");
- return error_mark_node;
- }
- }
- else
- {
- /* Take just the first element from within the constructor
- and it should match the type of the first element. */
- element = digest_init (TREE_TYPE (field), element, (tree *) 0);
- result = build (CONSTRUCTOR, type, 0, build_tree_list (field, element));
- TREE_CONSTANT (result) = TREE_CONSTANT (element);
- TREE_STATIC (result) = (initializer_constant_valid_p (element)
- && TREE_CONSTANT (element));
- return result;
- }
- }
-
- /* Initialization of an array of chars from a string constant
- optionally enclosed in braces. */
-
- if (code == ARRAY_TYPE)
- {
- tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if ((typ1 == char_type_node
- || typ1 == signed_char_type_node
- || typ1 == unsigned_char_type_node
- || typ1 == unsigned_wchar_type_node
- || typ1 == signed_wchar_type_node)
- && ((init && TREE_CODE (init) == STRING_CST)
- || (element && TREE_CODE (element) == STRING_CST)))
- {
- tree string = element ? element : init;
-
- if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
- != char_type_node)
- && TYPE_PRECISION (typ1) == BITS_PER_UNIT)
- {
- error ("char-array initialized from wide string");
- return error_mark_node;
- }
- if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
- == char_type_node)
- && TYPE_PRECISION (typ1) != BITS_PER_UNIT)
- {
- error ("int-array initialized from non-wide string");
- return error_mark_node;
- }
-
- if (pedantic && typ1 != char_type_node)
- pedwarn ("ANSI C++ forbids string initializer except for `char' elements");
- TREE_TYPE (string) = type;
- if (TYPE_DOMAIN (type) != 0
- && TREE_CONSTANT (TYPE_SIZE (type)))
- {
- register int size
- = TREE_INT_CST_LOW (TYPE_SIZE (type));
- size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
- /* In C it is ok to subtract 1 from the length of the string
- because it's ok to ignore the terminating null char that is
- counted in the length of the constant, but in C++ this would
- be invalid. */
- if (size < TREE_STRING_LENGTH (string))
- warning ("initializer-string for array of chars is too long");
- }
- return string;
- }
- }
-
- /* Handle scalar types, including conversions. */
-
- if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
- || code == ENUMERAL_TYPE || code == REFERENCE_TYPE)
- {
- if (raw_constructor)
- {
- if (element == 0)
- {
- error ("initializer for scalar variable requires one element");
- return error_mark_node;
- }
- init = element;
- }
-
- return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
- "initialization", NULL_TREE, 0);
- }
-
- /* Come here only for records and arrays (and unions with constructors). */
-
- if (TYPE_SIZE (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))
- {
- error ("variable-sized object may not be initialized");
- return error_mark_node;
- }
-
- if (code == ARRAY_TYPE || code == RECORD_TYPE || code == UNION_TYPE)
- {
- if (raw_constructor)
- return process_init_constructor (type, init, 0);
- else if (TYPE_NEEDS_CONSTRUCTING (type))
- {
- /* This can only be reached when caller is initializing
- ARRAY_TYPE. In that case, we don't want to convert
- INIT to TYPE. We will let `expand_vec_init' do it. */
- return init;
- }
- else if (tail != 0)
- {
- *tail = old_tail_contents;
- return process_init_constructor (type, 0, tail);
- }
- else if (flag_traditional)
- /* Traditionally one can say `char x[100] = 0;'. */
- return process_init_constructor (type,
- build_nt (CONSTRUCTOR, 0,
- tree_cons (0, init, 0)),
- 0);
- if (code != ARRAY_TYPE)
- return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
- "initialization", NULL_TREE, 0);
- }
-
- error ("invalid initializer");
- return error_mark_node;
-}
-
-/* Process a constructor for a variable of type TYPE.
- The constructor elements may be specified either with INIT or with ELTS,
- only one of which should be non-null.
-
- If INIT is specified, it is a CONSTRUCTOR node which is specifically
- and solely for initializing this datum.
-
- If ELTS is specified, it is the address of a variable containing
- a list of expressions. We take as many elements as we need
- from the head of the list and update the list.
-
- In the resulting constructor, TREE_CONSTANT is set if all elts are
- constant, and TREE_STATIC is set if, in addition, all elts are simple enough
- constants that the assembler and linker can compute them. */
-
-static tree
-process_init_constructor (type, init, elts)
- tree type, init, *elts;
-{
- extern tree empty_init_node;
- register tree tail;
- /* List of the elements of the result constructor,
- in reverse order. */
- register tree members = NULL;
- tree result;
- int allconstant = 1;
- int allsimple = 1;
- int erroneous = 0;
-
- /* Make TAIL be the list of elements to use for the initialization,
- no matter how the data was given to us. */
-
- if (elts)
- {
- if (extra_warnings)
- warning ("aggregate has a partly bracketed initializer");
- tail = *elts;
- }
- else
- tail = CONSTRUCTOR_ELTS (init);
-
- /* Gobble as many elements as needed, and make a constructor or initial value
- for each element of this aggregate. Chain them together in result.
- If there are too few, use 0 for each scalar ultimate component. */
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree domain = TYPE_DOMAIN (type);
- register long len;
- register int i;
-
- if (domain)
- len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain))
- - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain))
- + 1);
- else
- len = -1; /* Take as many as there are */
-
- for (i = 0; (len < 0 || i < len) && tail != 0; i++)
- {
- register tree next1;
-
- if (TREE_VALUE (tail) != 0)
- {
- tree tail1 = tail;
- next1 = digest_init (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
- TREE_VALUE (tail), &tail1);
- my_friendly_assert (tail1 == 0
- || TREE_CODE (tail1) == TREE_LIST, 319);
- if (tail == tail1 && len < 0)
- {
- error ("non-empty initializer for array of empty elements");
- /* Just ignore what we were supposed to use. */
- tail1 = 0;
- }
- tail = tail1;
- }
- else
- {
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
- }
-
- if (next1 == error_mark_node)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (! initializer_constant_valid_p (next1))
- allsimple = 0;
- members = tree_cons (NULL_TREE, next1, members);
- }
- }
- if (TREE_CODE (type) == RECORD_TYPE && init != empty_init_node)
- {
- register tree field;
-
- if (tail)
- {
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- {
- sorry ("initializer list for object of class with virtual baseclasses");
- return error_mark_node;
- }
-
- if (TYPE_BINFO_BASETYPES (type))
- {
- sorry ("initializer list for object of class with baseclasses");
- return error_mark_node;
- }
-
- if (TYPE_VIRTUAL_P (type))
- {
- sorry ("initializer list for object using virtual functions");
- return error_mark_node;
- }
- }
-
- for (field = TYPE_FIELDS (type); field && tail;
- field = TREE_CHAIN (field))
- {
- register tree next1;
-
- if (! DECL_NAME (field))
- {
- members = tree_cons (field, integer_zero_node, members);
- continue;
- }
-
- if (TREE_CODE (field) == CONST_DECL || TREE_CODE (field) == TYPE_DECL)
- continue;
-
- /* A static mmmember isn't considered "part of the object", so
- it has no business even thinking about involving itself in
- what an initializer-list is trying to do. */
- if (TREE_CODE (field) == VAR_DECL && TREE_STATIC (field))
- continue;
-
- if (TREE_VALUE (tail) != 0)
- {
- tree tail1 = tail;
- next1 = digest_init (TREE_TYPE (field),
- TREE_VALUE (tail), &tail1);
- my_friendly_assert (tail1 == 0
- || TREE_CODE (tail1) == TREE_LIST, 320);
- if (TREE_CODE (field) == VAR_DECL
- && ! global_bindings_p ())
- warning_with_decl (field, "initialization of static member `%s'");
- tail = tail1;
- }
- else
- {
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
- }
-
- if (next1 == error_mark_node)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (! initializer_constant_valid_p (next1))
- allsimple = 0;
- members = tree_cons (field, next1, members);
- }
- for (; field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- /* Does this field have a default initialization? */
- if (DECL_INITIAL (field))
- {
- register tree next1 = DECL_INITIAL (field);
- if (TREE_CODE (next1) == ERROR_MARK)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (! initializer_constant_valid_p (next1))
- allsimple = 0;
- members = tree_cons (field, next1, members);
- }
- else if (TREE_READONLY (field))
- error ("uninitialized const member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field))
- && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
- error ("member `%s' with uninitialized const fields",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
- error ("member `%s' is uninitialized reference",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- }
- }
-
- if (TREE_CODE (type) == UNION_TYPE)
- {
- register tree field = TYPE_FIELDS (type);
- register tree next1;
-
- /* Find the first named field. ANSI decided in September 1990
- that only named fields count here. */
- while (field && DECL_NAME (field) == 0)
- field = TREE_CHAIN (field);
-
- /* For a union, get the initializer for 1 fld. */
-
- if (tail == NULL_TREE)
- {
- error ("empty initializer for union");
- tail = build_tree_list (NULL_TREE, NULL_TREE);
- }
-
- /* If this element specifies a field, initialize via that field. */
- if (TREE_PURPOSE (tail) != NULL_TREE)
- {
- int win = 0;
-
- if (TREE_CODE (TREE_PURPOSE (tail)) == FIELD_DECL)
- /* Handle the case of a call by build_c_cast. */
- field = TREE_PURPOSE (tail), win = 1;
- else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE)
- error ("index value instead of field name in union initializer");
- else
- {
- tree temp;
- for (temp = TYPE_FIELDS (type);
- temp;
- temp = TREE_CHAIN (temp))
- if (DECL_NAME (temp) == TREE_PURPOSE (tail))
- break;
- if (temp)
- field = temp, win = 1;
- else
- error ("no field `%s' in union being initialized",
- IDENTIFIER_POINTER (TREE_PURPOSE (tail)));
- }
- if (!win)
- TREE_VALUE (tail) = error_mark_node;
- }
-
- if (TREE_VALUE (tail) != 0)
- {
- tree tail1 = tail;
-
- next1 = digest_init (TREE_TYPE (field),
- TREE_VALUE (tail), &tail1);
- if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
- abort ();
- tail = tail1;
- }
- else
- {
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
- }
-
- if (next1 == error_mark_node)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (initializer_constant_valid_p (next1) == 0)
- allsimple = 0;
- members = tree_cons (field, next1, members);
- }
-
- /* If arguments were specified as a list, just remove the ones we used. */
- if (elts)
- *elts = tail;
- /* If arguments were specified as a constructor,
- complain unless we used all the elements of the constructor. */
- else if (tail)
- warning ("excess elements in aggregate initializer");
-
- if (erroneous)
- return error_mark_node;
-
- result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members));
- if (init)
- TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init);
- if (allconstant) TREE_CONSTANT (result) = 1;
- if (allconstant && allsimple) TREE_STATIC (result) = 1;
- return result;
-}
-
-/* Given a structure or union value DATUM, construct and return
- the structure or union component which results from narrowing
- that value by the types specified in TYPES. For example, given the
- hierarchy
-
- class L { int ii; };
- class A : L { ... };
- class B : L { ... };
- class C : A, B { ... };
-
- and the declaration
-
- C x;
-
- then the expression
-
- x::C::A::L::ii refers to the ii member of the L part of
- of A part of the C object named by X. In this case,
- DATUM would be x, and TYPES would be a SCOPE_REF consisting of
-
- SCOPE_REF
- SCOPE_REF
- C A
- L
-
- The last entry in the SCOPE_REF is always an IDENTIFIER_NODE.
-
-*/
-
-tree
-build_scoped_ref (datum, types)
- tree datum;
- tree types;
-{
- tree ref;
- tree type = TREE_TYPE (datum);
-
- if (datum == error_mark_node)
- return error_mark_node;
- type = TYPE_MAIN_VARIANT (type);
-
- if (TREE_CODE (types) == SCOPE_REF)
- {
- /* We have some work to do. */
- struct type_chain { tree type; struct type_chain *next; } *chain = 0, *head = 0, scratch;
- ref = build_unary_op (ADDR_EXPR, datum, 0);
- while (TREE_CODE (types) == SCOPE_REF)
- {
- tree t = TREE_OPERAND (types, 1);
- if (is_aggr_typedef (t, 1))
- {
- head = (struct type_chain *)alloca (sizeof (struct type_chain));
- head->type = IDENTIFIER_TYPE_VALUE (t);
- head->next = chain;
- chain = head;
- types = TREE_OPERAND (types, 0);
- }
- else return error_mark_node;
- }
- if (! is_aggr_typedef (types, 1))
- return error_mark_node;
-
- head = &scratch;
- head->type = IDENTIFIER_TYPE_VALUE (types);
- head->next = chain;
- chain = head;
- while (chain)
- {
- tree binfo = chain->type;
- type = TREE_TYPE (TREE_TYPE (ref));
- if (binfo != TYPE_BINFO (type))
- {
- binfo = get_binfo (binfo, type, 1);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (binfo == 0)
- return error_not_base_type (chain->type, type);
- ref = convert_pointer_to (binfo, ref);
- }
- chain = chain->next;
- }
- return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
- }
-
- /* This is an easy conversion. */
- if (is_aggr_typedef (types, 1))
- {
- tree binfo = TYPE_BINFO (IDENTIFIER_TYPE_VALUE (types));
- if (binfo != TYPE_BINFO (type))
- {
- binfo = get_binfo (binfo, type, 1);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (binfo == 0)
- return error_not_base_type (IDENTIFIER_TYPE_VALUE (types), type);
- }
-
- switch (TREE_CODE (datum))
- {
- case NOP_EXPR:
- case CONVERT_EXPR:
- case FLOAT_EXPR:
- case FIX_TRUNC_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_CEIL_EXPR:
- ref = convert_pointer_to (binfo,
- build_unary_op (ADDR_EXPR, TREE_OPERAND (datum, 0), 0));
- break;
- default:
- ref = convert_pointer_to (binfo,
- build_unary_op (ADDR_EXPR, datum, 0));
- }
- return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
- }
- return error_mark_node;
-}
-
-/* Build a reference to an object specified by the C++ `->' operator.
- Usually this just involves dereferencing the object, but if the
- `->' operator is overloaded, then such overloads must be
- performed until an object which does not have the `->' operator
- overloaded is found. An error is reported when circular pointer
- delegation is detected. */
-tree
-build_x_arrow (datum)
- tree datum;
-{
- tree types_memoized = NULL_TREE;
- register tree rval = datum;
- tree type = TREE_TYPE (rval);
- tree last_rval;
-
- if (type == error_mark_node)
- return error_mark_node;
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- rval = convert_from_reference (rval);
- type = TREE_TYPE (rval);
- }
-
- if (IS_AGGR_TYPE (type) && TYPE_OVERLOADS_ARROW (type))
- {
- while (rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, NULL_TREE, NULL_TREE))
- {
- if (rval == error_mark_node)
- return error_mark_node;
-
- if (value_member (TREE_TYPE (rval), types_memoized))
- {
- error ("circular pointer delegation detected");
- return error_mark_node;
- }
- else
- {
- types_memoized = tree_cons (NULL_TREE, TREE_TYPE (rval),
- types_memoized);
- }
- last_rval = rval;
- }
- if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE)
- last_rval = convert_from_reference (last_rval);
- }
- else
- last_rval = default_conversion (rval);
-
- more:
- if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
- return build_indirect_ref (last_rval, 0);
-
- if (TREE_CODE (TREE_TYPE (last_rval)) == OFFSET_TYPE)
- {
- if (TREE_CODE (last_rval) == OFFSET_REF
- && TREE_STATIC (TREE_OPERAND (last_rval, 1)))
- {
- last_rval = TREE_OPERAND (last_rval, 1);
- if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE)
- last_rval = convert_from_reference (last_rval);
- goto more;
- }
- compiler_error ("invalid member type in build_x_arrow");
- return error_mark_node;
- }
-
- if (types_memoized)
- error ("result of `operator->()' yields non-pointer result");
- else
- error ("base operand of `->' is not a pointer");
- return error_mark_node;
-}
-
-/* Make an expression to refer to the COMPONENT field of
- structure or union value DATUM. COMPONENT is an arbitrary
- expression. DATUM has already been checked out to be of
- aggregate type.
-
- For C++, COMPONENT may be a TREE_LIST. This happens when we must
- return an object of member type to a method of the current class,
- but there is not yet enough typing information to know which one.
- As a special case, if there is only one method by that name,
- it is returned. Otherwise we return an expression which other
- routines will have to know how to deal with later. */
-tree
-build_m_component_ref (datum, component)
- tree datum, component;
-{
- tree type = TREE_TYPE (component);
- tree objtype = TREE_TYPE (datum);
-
- if (datum == error_mark_node || component == error_mark_node)
- return error_mark_node;
-
- if (TREE_CODE (type) != OFFSET_TYPE && TREE_CODE (type) != METHOD_TYPE)
- {
- error ("non-member type composed with object");
- return error_mark_node;
- }
-
- if (TREE_CODE (objtype) == REFERENCE_TYPE)
- objtype = TREE_TYPE (objtype);
-
- if (! comptypes (TYPE_METHOD_BASETYPE (type), objtype, 0))
- {
- error ("member type `%s::' incompatible with object type `%s'",
- TYPE_NAME_STRING (TYPE_METHOD_BASETYPE (type)),
- TYPE_NAME_STRING (objtype));
- return error_mark_node;
- }
-
- return build (OFFSET_REF, TREE_TYPE (TREE_TYPE (component)), datum, component);
-}
-
-/* Return a tree node for the expression TYPENAME '(' PARMS ')'.
-
- Because we cannot tell whether this construct is really
- a function call or a call to a constructor or a request for
- a type conversion, we try all three, and report any ambiguities
- we find. */
-tree
-build_functional_cast (exp, parms)
- tree exp;
- tree parms;
-{
- /* This is either a call to a constructor,
- or a C cast in C++'s `functional' notation. */
- tree type, name = NULL_TREE;
- tree expr_as_ctor = NULL_TREE;
- tree expr_as_method = NULL_TREE;
- tree expr_as_fncall = NULL_TREE;
- tree expr_as_conversion = NULL_TREE;
-
- if (exp == error_mark_node || parms == error_mark_node)
- return error_mark_node;
-
- if (TREE_CODE (exp) == IDENTIFIER_NODE)
- {
- name = exp;
-
- if (IDENTIFIER_HAS_TYPE_VALUE (exp))
- /* Either an enum or an aggregate type. */
- type = IDENTIFIER_TYPE_VALUE (exp);
- else
- {
- type = lookup_name (exp, 1);
- if (!type || TREE_CODE (type) != TYPE_DECL)
- {
- error ("`%s' fails to be a typedef or built-in type",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- type = TREE_TYPE (type);
- }
- }
- else type = exp;
-
- /* Prepare to evaluate as a call to a constructor. If this expression
- is actually used, for example,
-
- return X (arg1, arg2, ...);
-
- then the slot being initialized will be filled in. */
-
- if (name == NULL_TREE)
- {
- name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- }
-
- /* Try evaluating as a call to a function. */
- if (IDENTIFIER_CLASS_VALUE (name))
- expr_as_method = build_method_call (current_class_decl, name, parms,
- NULL_TREE, LOOKUP_SPECULATIVELY);
- if (IDENTIFIER_GLOBAL_VALUE (name)
- && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TREE_LIST
- || TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == FUNCTION_DECL))
- {
- expr_as_fncall = build_overload_call (name, parms, 0,
- (struct candidate *)0);
- if (expr_as_fncall == NULL_TREE)
- expr_as_fncall = error_mark_node;
- }
-
- if (! IS_AGGR_TYPE (type))
- {
- /* this must build a C cast */
- if (parms == NULL_TREE)
- {
- if (expr_as_method || expr_as_fncall)
- goto return_function;
-
- error ("cannot cast null list to type `%s'",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- if (expr_as_method
- || (expr_as_fncall && expr_as_fncall != error_mark_node))
- {
- error ("ambiguity between cast to `%s' and function call",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- return build_c_cast (type, build_compound_expr (parms));
- }
-
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- if (expr_as_method || expr_as_fncall)
- goto return_function;
- error ("type `%s' is not yet defined", IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
-
- if (parms && TREE_CHAIN (parms) == NULL_TREE)
- expr_as_conversion
- = build_type_conversion (CONVERT_EXPR, type, TREE_VALUE (parms), 0);
-
- if (! TYPE_NEEDS_CONSTRUCTOR (type) && parms != NULL_TREE)
- {
- char *msg = 0;
-
- if (parms == NULL_TREE)
- msg = "argument missing in cast to `%s' type";
- else if (TREE_CHAIN (parms) == NULL_TREE)
- {
- if (expr_as_conversion == NULL_TREE)
- msg = "conversion to type `%s' failed";
- }
- else msg = "type `%s' does not have a constructor";
-
- if ((expr_as_method || expr_as_fncall) && expr_as_conversion)
- msg = "ambiguity between conversion to `%s' and function call";
- else if (expr_as_method || expr_as_fncall)
- goto return_function;
- else if (expr_as_conversion)
- return expr_as_conversion;
-
- error (msg, IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
-
- if (! TYPE_HAS_CONSTRUCTOR (type))
- {
- if (expr_as_method || expr_as_fncall)
- goto return_function;
- if (expr_as_conversion)
- return expr_as_conversion;
-
- /* Look through this type until we find the
- base type which has a constructor. */
- do
- {
- tree binfos = TYPE_BINFO_BASETYPES (type);
- int i, index = 0;
-
- while (binfos && TREE_VEC_LENGTH (binfos) == 1
- && ! TYPE_HAS_CONSTRUCTOR (type))
- {
- type = BINFO_TYPE (TREE_VEC_ELT (binfos, 0));
- binfos = TYPE_BINFO_BASETYPES (type);
- }
- if (TYPE_HAS_CONSTRUCTOR (type))
- break;
- /* Hack for MI. */
- i = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- if (i == 0) break;
- while (--i > 0)
- {
- if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (TREE_VEC_ELT (binfos, i))))
- {
- if (index == 0)
- index = i;
- else
- {
- error ("multiple base classes with constructor, ambiguous");
- type = 0;
- break;
- }
- }
- }
- if (type == 0)
- break;
- } while (! TYPE_HAS_CONSTRUCTOR (type));
- if (type == 0)
- return error_mark_node;
- }
- name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
-
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 321);
-
- {
- int flags = LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN;
-
- if (parms && TREE_CHAIN (parms) == NULL_TREE)
- flags |= LOOKUP_NO_CONVERSION;
-
- try_again:
- expr_as_ctor = build_method_call (NULL_TREE, name, parms, NULL_TREE, flags);
-
- if (expr_as_ctor && expr_as_ctor != error_mark_node)
- {
-#if 0
- /* mrs Mar 12, 1992 I claim that if it is a constructor, it is
- impossible to be an expr_as_method, without being a
- constructor call. */
- if (expr_as_method
- || (expr_as_fncall && expr_as_fncall != error_mark_node))
-#else
- if (expr_as_fncall && expr_as_fncall != error_mark_node)
-#endif
- {
- error ("ambiguity between constructor for `%s' and function call",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- else if (expr_as_conversion && expr_as_conversion != error_mark_node)
- {
- /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
- error ("ambiguity between conversion to `%s' and constructor",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
-
- if (current_function_decl)
- return build_cplus_new (type, expr_as_ctor, 1);
-
- {
- register tree parm = TREE_OPERAND (expr_as_ctor, 1);
-
- /* Initializers for static variables and parameters have
- to handle doing the initialization and cleanup themselves. */
- my_friendly_assert (TREE_CODE (expr_as_ctor) == CALL_EXPR, 322);
- my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)), 323);
- TREE_VALUE (parm) = NULL_TREE;
- expr_as_ctor = build_indirect_ref (expr_as_ctor, 0);
- TREE_HAS_CONSTRUCTOR (expr_as_ctor) = 1;
- }
- return expr_as_ctor;
- }
-
- /* If it didn't work going through constructor, try type conversion. */
- if (! (flags & LOOKUP_COMPLAIN))
- {
- if (expr_as_conversion)
- return expr_as_conversion;
- if (flags & LOOKUP_NO_CONVERSION)
- {
- flags = LOOKUP_NORMAL;
- goto try_again;
- }
- }
-
- if (expr_as_conversion)
- {
- if (expr_as_method || expr_as_fncall)
- {
- error ("ambiguity between conversion to `%s' and function call",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- return expr_as_conversion;
- }
- return_function:
- if (expr_as_method)
- return build_method_call (current_class_decl, name, parms,
- NULL_TREE, LOOKUP_NORMAL);
- if (expr_as_fncall)
- return expr_as_fncall == error_mark_node
- ? build_overload_call (name, parms, 1, (struct candidate *)0)
- : expr_as_fncall;
- error ("invalid functional cast");
- return error_mark_node;
- }
-}
-
-/* Return the character string for the name that encodes the
- enumeral value VALUE in the domain TYPE. */
-char *
-enum_name_string (value, type)
- tree value;
- tree type;
-{
- register tree values = TYPE_VALUES (type);
- register HOST_WIDE_INT intval = TREE_INT_CST_LOW (value);
-
- my_friendly_assert (TREE_CODE (type) == ENUMERAL_TYPE, 324);
- while (values
- && TREE_INT_CST_LOW (TREE_VALUE (values)) != intval)
- values = TREE_CHAIN (values);
- if (values == NULL_TREE)
- {
- char *buf = (char *)oballoc (16 + TYPE_NAME_LENGTH (type));
-
- /* Value must have been cast. */
- sprintf (buf, "(enum %s)%d",
- TYPE_NAME_STRING (type), intval);
- return buf;
- }
- return IDENTIFIER_POINTER (TREE_PURPOSE (values));
-}
-
-/* Print out a language-specific error message for
- (Pascal) case or (C) switch statements.
- CODE tells what sort of message to print.
- TYPE is the type of the switch index expression.
- NEW is the new value that we were trying to add.
- OLD is the old value that stopped us from adding it. */
-void
-report_case_error (code, type, new_value, old_value)
- int code;
- tree type;
- tree new_value, old_value;
-{
- if (code == 1)
- {
- if (new_value)
- error ("case label not within a switch statement");
- else
- error ("default label not within a switch statement");
- }
- else if (code == 2)
- {
- if (new_value == 0)
- {
- error ("multiple default labels in one switch");
- return;
- }
- if (TREE_CODE (new_value) == RANGE_EXPR)
- if (TREE_CODE (old_value) == RANGE_EXPR)
- {
- char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type)));
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- sprintf (buf, "overlapping ranges [%s..%s], [%s..%s] in case expression",
- enum_name_string (TREE_OPERAND (new_value, 0), type),
- enum_name_string (TREE_OPERAND (new_value, 1), type),
- enum_name_string (TREE_OPERAND (old_value, 0), type),
- enum_name_string (TREE_OPERAND (old_value, 1), type));
- else
- sprintf (buf, "overlapping ranges [%d..%d], [%d..%d] in case expression",
- TREE_INT_CST_LOW (TREE_OPERAND (new_value, 0)),
- TREE_INT_CST_LOW (TREE_OPERAND (new_value, 1)),
- TREE_INT_CST_LOW (TREE_OPERAND (old_value, 0)),
- TREE_INT_CST_LOW (TREE_OPERAND (old_value, 1)));
- error (buf);
- }
- else
- {
- char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type)));
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- sprintf (buf, "range [%s..%s] includes element `%s' in case expression",
- enum_name_string (TREE_OPERAND (new_value, 0), type),
- enum_name_string (TREE_OPERAND (new_value, 1), type),
- enum_name_string (old_value, type));
- else
- sprintf (buf, "range [%d..%d] includes (%d) in case expression",
- TREE_INT_CST_LOW (TREE_OPERAND (new_value, 0)),
- TREE_INT_CST_LOW (TREE_OPERAND (new_value, 1)),
- TREE_INT_CST_LOW (old_value));
- error (buf);
- }
- else if (TREE_CODE (old_value) == RANGE_EXPR)
- {
- char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type)));
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- sprintf (buf, "range [%s..%s] includes element `%s' in case expression",
- enum_name_string (TREE_OPERAND (old_value, 0), type),
- enum_name_string (TREE_OPERAND (old_value, 1), type),
- enum_name_string (new_value, type));
- else
- sprintf (buf, "range [%d..%d] includes (%d) in case expression",
- TREE_INT_CST_LOW (TREE_OPERAND (old_value, 0)),
- TREE_INT_CST_LOW (TREE_OPERAND (old_value, 1)),
- TREE_INT_CST_LOW (new_value));
- error (buf);
- }
- else
- {
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- error ("duplicate label `%s' in switch statement",
- enum_name_string (new_value, type));
- else
- error ("duplicate label (%d) in switch statement",
- TREE_INT_CST_LOW (new_value));
- }
- }
- else if (code == 3)
- {
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- warning ("case value out of range for enum %s",
- TYPE_NAME_STRING (type));
- else
- warning ("case value out of range");
- }
- else if (code == 4)
- {
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- error ("range values `%s' and `%s' reversed",
- enum_name_string (new_value, type),
- enum_name_string (old_value, type));
- else
- error ("range values reversed");
- }
-}
diff --git a/gnu/gcc2/cc1plus/cp-typeck.c b/gnu/gcc2/cc1plus/cp-typeck.c
deleted file mode 100644
index 362e17080993..000000000000
--- a/gnu/gcc2/cc1plus/cp-typeck.c
+++ /dev/null
@@ -1,6374 +0,0 @@
-/* Build expressions with type checking for C++ compiler.
- Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
- Hacked 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. */
-
-
-/* This file is part of the C++ front end.
- It contains routines to build C++ expressions given their operands,
- including computing the types of the result, C and C++ specific error
- checks, and some optimization.
-
- There are also routines to build RETURN_STMT nodes and CASE_STMT nodes,
- and to process initializations in declarations (since they work
- like a strange sort of assignment). */
-
-extern void error ();
-extern void warning ();
-
-#include "config.h"
-#include <stdio.h>
-#include "tree.h"
-#include "rtl.h"
-#include "cp-tree.h"
-#include "flags.h"
-
-int mark_addressable ();
-static tree convert_for_assignment ();
-/* static */ tree convert_for_initialization ();
-int compparms ();
-static int self_promoting_args_p ();
-int comp_target_types ();
-extern tree shorten_compare ();
-void warn_for_assignment ();
-extern void binary_op_error ();
-static tree pointer_int_sum ();
-static tree pointer_diff ();
-static tree convert_sequence ();
-/* static */ tree unary_complex_lvalue ();
-static void pedantic_lvalue_warning ();
-tree truthvalue_conversion ();
-
-extern rtx original_result_rtx;
-
-/* Return the target type of TYPE, which meas return T for:
- T*, T&, T[], T (...), and otherwise, just T. */
-
-tree
-target_type (type)
- tree type;
-{
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
- while (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == ARRAY_TYPE
- || TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE
- || TREE_CODE (type) == OFFSET_TYPE)
- type = TREE_TYPE (type);
- return type;
-}
-
-/* Do `exp = require_complete_type (exp);' to make sure exp
- does not have an incomplete type. (That includes void types.) */
-
-tree
-require_complete_type (value)
- tree value;
-{
- tree type = TREE_TYPE (value);
-
- /* First, detect a valid value with a complete type. */
- if (TYPE_SIZE (type) != 0
- && type != void_type_node)
- return value;
-
- /* If we see X::Y, we build an OFFSET_TYPE which has
- not been laid out. Try to avoid an error by interpreting
- it as this->X::Y, if reasonable. */
- if (TREE_CODE (value) == OFFSET_REF
- && C_C_D != 0
- && TREE_OPERAND (value, 0) == C_C_D)
- {
- tree base, member = TREE_OPERAND (value, 1);
- tree basetype = TYPE_OFFSET_BASETYPE (type);
- my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305);
- base = convert_pointer_to (basetype, current_class_decl);
- value = build (COMPONENT_REF, TREE_TYPE (member),
- build_indirect_ref (base, NULL_PTR), member);
- return require_complete_type (value);
- }
-
- incomplete_type_error (value, type);
- return error_mark_node;
-}
-
-/* Return truthvalue of whether type of EXP is instantiated. */
-int
-type_unknown_p (exp)
- tree exp;
-{
- return (TREE_CODE (exp) == TREE_LIST
- || TREE_TYPE (exp) == unknown_type_node
- || (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE
- && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node));
-}
-
-/* Do `exp = require_instantiated_type (type, exp);' to make sure EXP
- does not have an uninstantiated type.
- TYPE is type to instantiate with, if uninstantiated. */
-tree
-require_instantiated_type (type, exp, errval)
- tree type, exp, errval;
-{
- if (TREE_TYPE (exp) == unknown_type_node
- || (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE
- && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node))
- {
- exp = instantiate_type (type, exp, 1);
- if (TREE_TYPE (exp) == error_mark_node)
- return errval;
- }
- return exp;
-}
-
-/* Return a variant of TYPE which has all the type qualifiers of LIKE
- as well as those of TYPE. */
-
-static tree
-qualify_type (type, like)
- tree type, like;
-{
- int constflag = TYPE_READONLY (type) || TYPE_READONLY (like);
- int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);
- /* @@ Must do member pointers here. */
- return build_type_variant (type, constflag, volflag);
-}
-
-/* Return the common type of two parameter lists.
- We assume that comptypes has already been done and returned 1;
- if that isn't so, this may crash.
-
- As an optimization, free the space we allocate if the parameter
- lists are already common. */
-
-tree
-commonparms (p1, p2)
- tree p1, p2;
-{
- tree oldargs = p1, newargs, n;
- int i, len;
- int any_change = 0;
- char *first_obj = (char *) oballoc (0);
-
- len = list_length (p1);
- newargs = tree_last (p1);
-
- if (newargs == void_list_node)
- i = 1;
- else
- {
- i = 0;
- newargs = 0;
- }
-
- for (; i < len; i++)
- newargs = tree_cons (NULL_TREE, NULL_TREE, newargs);
-
- n = newargs;
-
- for (i = 0; p1;
- p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n), i++)
- {
- if (TREE_PURPOSE (p1) && !TREE_PURPOSE (p2))
- {
- /* We used to give a warning here that advised about a default
- argument being given in the prototype but not in the function's
- declaration. It's best not to bother. */
- TREE_PURPOSE (n) = TREE_PURPOSE (p1);
- any_change = 1;
- }
- else if (! TREE_PURPOSE (p1))
- {
- if (TREE_PURPOSE (p2))
- {
- TREE_PURPOSE (n) = TREE_PURPOSE (p2);
- any_change = 1;
- }
- }
- else
- {
- int cmp = simple_cst_equal (TREE_PURPOSE (p1), TREE_PURPOSE (p2));
- if (cmp < 0)
- my_friendly_abort (111);
- if (cmp == 0)
- {
- error ("redeclaration of default argument %d", i+1);
- any_change = 1;
- }
- TREE_PURPOSE (n) = TREE_PURPOSE (p2);
- }
- if (TREE_VALUE (p1) != TREE_VALUE (p2))
- {
- any_change = 1;
- TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2));
- }
- else
- TREE_VALUE (n) = TREE_VALUE (p1);
- }
- if (! any_change)
- {
- obfree (first_obj);
- return oldargs;
- }
-
- return newargs;
-}
-
-/* Return the common type of two types.
- We assume that comptypes has already been done and returned 1;
- if that isn't so, this may crash.
-
- This is the type for the result of most arithmetic operations
- if the operands have the given two types.
-
- We do not deal with enumeral types here because they have already been
- converted to integer types. */
-
-tree
-common_type (t1, t2)
- tree t1, t2;
-{
- register enum tree_code code1;
- register enum tree_code code2;
-
- /* Save time if the two types are the same. */
-
- if (t1 == t2) return t1;
-
- /* If one type is nonsense, use the other. */
- if (t1 == error_mark_node)
- return t2;
- if (t2 == error_mark_node)
- return t1;
-
- /* Treat an enum type as the unsigned integer type of the same width. */
-
- if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), 1);
- if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), 1);
-
- code1 = TREE_CODE (t1);
- code2 = TREE_CODE (t2);
-
- switch (code1)
- {
- case INTEGER_TYPE:
- case REAL_TYPE:
- /* If only one is real, use it as the result. */
-
- if (code1 == REAL_TYPE && code2 != REAL_TYPE)
- return t1;
-
- if (code2 == REAL_TYPE && code1 != REAL_TYPE)
- return t2;
-
- /* Both real or both integers; use the one with greater precision. */
-
- if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
- return t1;
- else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
- return t2;
-
- /* Same precision. Prefer longs to ints even when same size. */
-
- if (t1 == long_unsigned_type_node
- || t2 == long_unsigned_type_node)
- return long_unsigned_type_node;
-
- if (t1 == long_integer_type_node
- || t2 == long_integer_type_node)
- {
- /* But preserve unsignedness from the other type,
- since long cannot hold all the values of an unsigned int. */
- if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
- return long_unsigned_type_node;
- return long_integer_type_node;
- }
-
- /* Otherwise prefer the unsigned one. */
-
- if (TREE_UNSIGNED (t1))
- return t1;
- else return t2;
-
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- /* For two pointers, do this recursively on the target type,
- and combine the qualifiers of the two types' targets. */
- /* This code was turned off; I don't know why.
- But ANSI C++ specifies doing this with the qualifiers.
- So I turned it on again. */
- {
- tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),
- TYPE_MAIN_VARIANT (TREE_TYPE (t2)));
- int constp
- = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
- int volatilep
- = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
- target = build_type_variant (target, constp, volatilep);
- if (code1 == POINTER_TYPE)
- return build_pointer_type (target);
- else
- return build_reference_type (target);
- }
-#if 0
- case POINTER_TYPE:
- return build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
-
- case REFERENCE_TYPE:
- return build_reference_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
-#endif
-
- case ARRAY_TYPE:
- {
- tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
- /* Save space: see if the result is identical to one of the args. */
- if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
- return t1;
- if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
- return t2;
- /* Merge the element types, and have a size if either arg has one. */
- return build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
- }
-
- case FUNCTION_TYPE:
- /* Function types: prefer the one that specified arg types.
- If both do, merge the arg types. Also merge the return types. */
- {
- tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
- tree p1 = TYPE_ARG_TYPES (t1);
- tree p2 = TYPE_ARG_TYPES (t2);
- tree rval, raises;
-
- /* Save space: see if the result is identical to one of the args. */
- if (valtype == TREE_TYPE (t1) && ! p2)
- return t1;
- if (valtype == TREE_TYPE (t2) && ! p1)
- return t2;
-
- /* Simple way if one arg fails to specify argument types. */
- if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
- {
- rval = build_function_type (valtype, p2);
- if (raises = TYPE_RAISES_EXCEPTIONS (t2))
- rval = build_exception_variant (NULL_TREE, rval, raises);
- return rval;
- }
- raises = TYPE_RAISES_EXCEPTIONS (t1);
- if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
- {
- rval = build_function_type (valtype, p1);
- if (raises)
- rval = build_exception_variant (NULL_TREE, rval, raises);
- return rval;
- }
-
- rval = build_function_type (valtype, commonparms (p1, p2));
- return build_exception_variant (NULL_TREE, rval, raises);
- }
-
- case RECORD_TYPE:
- case UNION_TYPE:
- my_friendly_assert (TYPE_MAIN_VARIANT (t1) == t1
- && TYPE_MAIN_VARIANT (t2) == t2, 306);
-
- if (binfo_or_else (t1, t2))
- return t1;
- compiler_error ("common_type called with uncommon aggregate types");
- return t1;
-
- case METHOD_TYPE:
- if (TYPE_METHOD_BASETYPE (t1) == TYPE_METHOD_BASETYPE (t2)
- && TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
- {
- /* Get this value the long way, since TYPE_METHOD_BASETYPE
- is just the main variant of this. */
- tree basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t1)));
- tree raises, t3;
-
- raises = TYPE_RAISES_EXCEPTIONS (t1);
-
- /* If this was a member function type, get back to the
- original type of type member function (i.e., without
- the class instance variable up front. */
- t1 = build_function_type (TREE_TYPE (t1), TREE_CHAIN (TYPE_ARG_TYPES (t1)));
- t2 = build_function_type (TREE_TYPE (t2), TREE_CHAIN (TYPE_ARG_TYPES (t2)));
- t3 = common_type (t1, t2);
- t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3));
- return build_exception_variant (basetype, t3, raises);
- }
- compiler_error ("common_type called with uncommon method types");
- return t1;
-
- case OFFSET_TYPE:
- if (TYPE_OFFSET_BASETYPE (t1) == TYPE_OFFSET_BASETYPE (t2)
- && TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
- {
- tree basetype = TYPE_OFFSET_BASETYPE (t1);
- return build_offset_type (basetype,
- common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
- }
- compiler_error ("common_type called with uncommon member types");
- return t1;
-
- default:
- return t1;
- }
-}
-
-/* Return 1 if TYPE1 and TYPE2 raise the same exceptions. */
-int
-compexcepttypes (t1, t2, strict)
- tree t1, t2;
- int strict;
-{
- return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);
-}
-
-static int
-comp_array_types (cmp, t1, t2, strict)
- register int (*cmp)();
- tree t1, t2;
- int strict;
-{
- tree d1 = TYPE_DOMAIN (t1);
- tree d2 = TYPE_DOMAIN (t2);
-
- /* Target types must match incl. qualifiers. */
- if (!(TREE_TYPE (t1) == TREE_TYPE (t2)
- || (*cmp) (TREE_TYPE (t1), TREE_TYPE (t2), strict)))
- return 0;
-
- /* Sizes must match unless one is missing or variable. */
- if (d1 == 0 || d2 == 0 || d1 == d2
- || TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
- || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
- || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST
- || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)
- return 1;
-
- return ((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1))
- == TREE_INT_CST_LOW (TYPE_MIN_VALUE (d2)))
- && (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d1))
- == TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d2)))
- && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (d1))
- == TREE_INT_CST_LOW (TYPE_MAX_VALUE (d2)))
- && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d1))
- == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2))));
-}
-
-/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
- or various other operations. This is what ANSI C++ speaks of as
- "being the same".
-
- For C++: argument STRICT says we should be strict about this
- comparison:
-
- 1 : strict (compared according to ANSI C)
- 0 : <= (compared according to C++)
- -1: <= or >= (relaxed)
-
- Otherwise, pointers involving base classes and derived classes
- can be mixed as legal: i.e. a pointer to a base class may be assigned
- to a pointer to one of its derived classes, as per C++. A pointer to
- a derived class may be passed as a parameter to a function expecting a
- pointer to a base classes. These allowances do not commute. In this
- case, TYPE1 is assumed to be the base class, and TYPE2 is assumed to
- be the derived class. */
-int
-comptypes (type1, type2, strict)
- tree type1, type2;
- int strict;
-{
- register tree t1 = type1;
- register tree t2 = type2;
-
- /* Suppress errors caused by previously reported errors */
-
- if (t1 == t2)
- return 1;
- /* This should never happen. */
- my_friendly_assert (t1 != error_mark_node, 307);
-
- /* We don't want this to happen. */
- if (t2 == error_mark_node)
- {
- warning ("Internal error: t2 == error_mark_node in `comptypes'");
- return 0;
- }
-
- if (strict < 0)
- {
- /* Treat an enum type as the unsigned integer type of the same width. */
-
- if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), 1);
- if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), 1);
- }
-
- if (t1 == t2)
- return 1;
-
- /* Different classes of types can't be compatible. */
-
- if (TREE_CODE (t1) != TREE_CODE (t2)) return 0;
-
- /* Qualifiers must match. */
-
- if (TYPE_READONLY (t1) != TYPE_READONLY (t2))
- return 0;
- if (TREE_THIS_VOLATILE (t1) != TREE_THIS_VOLATILE (t2))
- return 0;
-
- switch (TREE_CODE (t1))
- {
- case RECORD_TYPE:
- case UNION_TYPE:
- if (t1 == t2)
- return 1;
- if (strict <= 0)
- goto look_hard;
- return 0;
-
- case OFFSET_TYPE:
- return (comptypes (TYPE_POINTER_TO (TYPE_OFFSET_BASETYPE (t1)),
- TYPE_POINTER_TO (TYPE_OFFSET_BASETYPE (t2)), strict)
- && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict));
-
- case METHOD_TYPE:
- if (! compexcepttypes (t1, t2, strict))
- return 0;
-
- /* This case is anti-symmetrical!
- One can pass a base member (or member function)
- to something expecting a derived member (or member function),
- but not vice-versa! */
-
- return (comptypes (TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t2)),
- TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t1)), strict)
- && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
- && compparms (TREE_CHAIN (TYPE_ARG_TYPES (t1)),
- TREE_CHAIN (TYPE_ARG_TYPES(t2)), strict));
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- t1 = TREE_TYPE (t1);
- t2 = TREE_TYPE (t2);
- if (t1 == t2)
- return 1;
- if (strict <= 0)
- {
- if (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE)
- {
- int rval;
- look_hard:
- rval = t1 == t2 || UNIQUELY_DERIVED_FROM_P (t1, t2);
-
- if (rval)
- return 1;
- if (strict < 0)
- return UNIQUELY_DERIVED_FROM_P (t2, t1);
- }
- return 0;
- }
- else
- return comptypes (t1, t2, strict);
-
- case FUNCTION_TYPE:
- if (! compexcepttypes (t1, t2, strict))
- return 0;
-
- return ((TREE_TYPE (t1) == TREE_TYPE (t2)
- || comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
- && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2), strict));
-
- case ARRAY_TYPE:
- /* Target types must match incl. qualifiers. */
- return comp_array_types (comptypes, t1, t2, strict);
-
- }
- return 0;
-}
-
-/* Return 1 if TTL and TTR are pointers to types that are equivalent,
- ignoring their qualifiers.
-
- NPTRS is the number of pointers we can strip off and keep cool.
- This is used to permit (for aggr A, aggr B) A, B* to convert to A*,
- but to not permit B** to convert to A**. */
-
-int
-comp_target_types (ttl, ttr, nptrs)
- tree ttl, ttr;
- int nptrs;
-{
- ttl = TYPE_MAIN_VARIANT (ttl);
- ttr = TYPE_MAIN_VARIANT (ttr);
- if (ttl == ttr)
- return 1;
-
- if (TREE_CODE (ttr) != TREE_CODE (ttl))
- return 0;
-
- if (TREE_CODE (ttr) == POINTER_TYPE)
- return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs - 1);
-
- if (TREE_CODE (ttr) == REFERENCE_TYPE)
- return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);
- if (TREE_CODE (ttr) == ARRAY_TYPE)
- return comp_array_types (comp_target_types, ttl, ttr, 0);
- else if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE)
- if (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
- switch (comp_target_parms (TYPE_ARG_TYPES (ttl), TYPE_ARG_TYPES (ttr), 0))
- {
- case 0:
- return 0;
- case 1:
- return 1;
- case 2:
- warning ("contravariance violation for method types ignored");
- return 1;
- default:
- my_friendly_abort (112);
- }
- else
- return 0;
-
- /* for C++ */
- else if (TREE_CODE (ttr) == OFFSET_TYPE)
- {
- /* Contravariance: we can assign a pointer to base member to a pointer
- to derived member. Note difference from simple pointer case, where
- we can pass a pointer to derived to a pointer to base. */
- if (comptypes (TYPE_OFFSET_BASETYPE (ttr), TYPE_OFFSET_BASETYPE (ttl), 0))
- return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);
- else if (comptypes (TYPE_OFFSET_BASETYPE (ttl), TYPE_OFFSET_BASETYPE (ttr), 0)
- && comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
- {
- warning ("contravariance violation for member types ignored");
- return 1;
- }
- }
- else if (IS_AGGR_TYPE (ttl))
- {
- if (nptrs < 0)
- return 0;
- return comptypes (TYPE_POINTER_TO (ttl), TYPE_POINTER_TO (ttr), 0);
- }
-
- return 0;
-}
-
-/* If two types share a common base type, return that basetype.
- If there is not a unique most-derived base type, this function
- returns ERROR_MARK_NODE. */
-tree
-common_base_type (tt1, tt2)
- tree tt1, tt2;
-{
- tree best = NULL_TREE, tmp;
- int i;
-
- /* If one is a baseclass of another, that's good enough. */
- if (UNIQUELY_DERIVED_FROM_P (tt1, tt2))
- return tt1;
- if (UNIQUELY_DERIVED_FROM_P (tt2, tt1))
- return tt2;
-
- /* If they share a virtual baseclass, that's good enough. */
- for (tmp = CLASSTYPE_VBASECLASSES (tt1); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (binfo_member (BINFO_TYPE (tmp), CLASSTYPE_VBASECLASSES (tt2)))
- return BINFO_TYPE (tmp);
- }
-
- /* Otherwise, try to find a unique baseclass of TT1
- that is shared by TT2, and follow that down. */
- for (i = CLASSTYPE_N_BASECLASSES (tt1)-1; i >= 0; i--)
- {
- tree basetype = TYPE_BINFO_BASETYPE (tt1, i);
- tree trial = common_base_type (basetype, tt2);
- if (trial)
- {
- if (trial == error_mark_node)
- return trial;
- if (best == NULL_TREE)
- best = trial;
- else if (best != trial)
- return error_mark_node;
- }
- }
-
- /* Same for TT2. */
- for (i = CLASSTYPE_N_BASECLASSES (tt2)-1; i >= 0; i--)
- {
- tree basetype = TYPE_BINFO_BASETYPE (tt2, i);
- tree trial = common_base_type (tt1, basetype);
- if (trial)
- {
- if (trial == error_mark_node)
- return trial;
- if (best == NULL_TREE)
- best = trial;
- else if (best != trial)
- return error_mark_node;
- }
- }
- return best;
-}
-
-/* Subroutines of `comptypes'. */
-
-/* Return 1 if two parameter type lists PARMS1 and PARMS2
- are equivalent in the sense that functions with those parameter types
- can have equivalent types.
- If either list is empty, we win.
- Otherwise, the two lists must be equivalent, element by element.
-
- C++: See comment above about TYPE1, TYPE2, STRICT.
- If STRICT == 3, it means checking is strict, but do not compare
- default parameter values. */
-int
-compparms (parms1, parms2, strict)
- tree parms1, parms2;
- int strict;
-{
- register tree t1 = parms1, t2 = parms2;
-
- /* An unspecified parmlist matches any specified parmlist
- whose argument types don't need default promotions. */
-
- if (t1 == 0)
- return self_promoting_args_p (t2);
- if (t2 == 0)
- return self_promoting_args_p (t1);
-
- while (1)
- {
- if (t1 == 0 && t2 == 0)
- return 1;
- /* If one parmlist is shorter than the other,
- they fail to match, unless STRICT is <= 0. */
- if (t1 == 0 || t2 == 0)
- {
- if (strict > 0)
- return 0;
- if (strict < 0)
- return 1;
- if (strict == 0)
- return t1 && TREE_PURPOSE (t1);
- }
- if (! comptypes (TREE_VALUE (t2), TREE_VALUE (t1), strict))
- {
- if (strict > 0)
- return 0;
- if (strict == 0)
- return t2 == void_list_node && TREE_PURPOSE (t1);
- return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);
- }
- if (strict != 3 && TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
- {
- int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
- if (cmp < 0)
- my_friendly_abort (113);
- if (cmp == 0)
- return 0;
- }
-
- t1 = TREE_CHAIN (t1);
- t2 = TREE_CHAIN (t2);
- }
-}
-
-/* This really wants return whether or not parameter type lists
- would make their owning functions assignment compatible or not. */
-int
-comp_target_parms (parms1, parms2, strict)
- tree parms1, parms2;
- int strict;
-{
- register tree t1 = parms1, t2 = parms2;
- int warn_contravariance = 0;
-
- /* An unspecified parmlist matches any specified parmlist
- whose argument types don't need default promotions. */
-
- if (t1 == 0)
- return self_promoting_args_p (t2);
- if (t2 == 0)
- return self_promoting_args_p (t1);
-
- for (; t1 || t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
- {
- tree p1, p2;
-
- /* If one parmlist is shorter than the other,
- they fail to match, unless STRICT is <= 0. */
- if (t1 == 0 || t2 == 0)
- {
- if (strict > 0)
- return 0;
- if (strict < 0)
- return 1 + warn_contravariance;
- return ((t1 && TREE_PURPOSE (t1)) + warn_contravariance);
- }
- p1 = TREE_VALUE (t1);
- p2 = TREE_VALUE (t2);
- if (p1 == p2)
- continue;
- if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE)
- || (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE))
- {
- if (strict <= 0
- && (TYPE_MAIN_VARIANT (TREE_TYPE (p1))
- == TYPE_MAIN_VARIANT (TREE_TYPE (p2))))
- continue;
-
- /* The following is wrong for contravariance,
- but many programs depend on it. */
- if (TREE_TYPE (p1) == void_type_node)
- continue;
- if (TREE_TYPE (p2) == void_type_node)
- {
- warn_contravariance = 1;
- continue;
- }
- if (IS_AGGR_TYPE (TREE_TYPE (p1)))
- {
- if (comptypes (p2, p1, 0) == 0)
- {
- if (comptypes (p1, p2, 0) != 0)
- warn_contravariance = 1;
- else
- return 0;
- }
- continue;
- }
- }
- /* Note backwards order due to contravariance. */
- if (comp_target_types (p2, p1, 1) == 0)
- {
- if (comp_target_types (p1, p2, 1))
- {
- warn_contravariance = 1;
- continue;
- }
- if (strict > 0)
- return 0;
-#if 0
- /* What good do these cases do? */
- if (strict == 0)
- return p2 == void_type_node && TREE_PURPOSE (t1);
- return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);
-#endif
- }
- /* Target types are compatible--just make sure that if
- we use parameter lists, that they are ok as well. */
- if (TREE_CODE (p1) == FUNCTION_TYPE || TREE_CODE (p1) == METHOD_TYPE)
- switch (comp_target_parms (TYPE_ARG_TYPES (p1),
- TYPE_ARG_TYPES (p2),
- strict))
- {
- case 0:
- return 0;
- case 1:
- break;
- case 2:
- warn_contravariance = 1;
- }
-
- if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
- {
- int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
- if (cmp < 0)
- my_friendly_abort (114);
- if (cmp == 0)
- return 0;
- }
- }
- return 1 + warn_contravariance;
-}
-
-/* Return 1 if PARMS specifies a fixed number of parameters
- and none of their types is affected by default promotions. */
-
-static int
-self_promoting_args_p (parms)
- tree parms;
-{
- register tree t;
- for (t = parms; t; t = TREE_CHAIN (t))
- {
- register tree type = TREE_VALUE (t);
-
- if (TREE_CHAIN (t) == 0 && type != void_type_node)
- return 0;
-
- if (TYPE_MAIN_VARIANT (type) == float_type_node)
- return 0;
-
- if (type == 0)
- return 0;
-
- if (C_PROMOTING_INTEGER_TYPE_P (type))
- return 0;
- }
- return 1;
-}
-
-/* Return an unsigned type the same as TYPE in other respects.
-
- C++: must make these work for type variants as well. */
-
-tree
-unsigned_type (type)
- tree type;
-{
- tree type1 = TYPE_MAIN_VARIANT (type);
- if (type1 == signed_char_type_node || type1 == char_type_node)
- return unsigned_char_type_node;
- if (type1 == integer_type_node)
- return unsigned_type_node;
- if (type1 == short_integer_type_node)
- return short_unsigned_type_node;
- if (type1 == long_integer_type_node)
- return long_unsigned_type_node;
- if (type1 == long_long_integer_type_node)
- return long_long_unsigned_type_node;
- return type;
-}
-
-/* Return a signed type the same as TYPE in other respects. */
-
-tree
-signed_type (type)
- tree type;
-{
- tree type1 = TYPE_MAIN_VARIANT (type);
- if (type1 == unsigned_char_type_node || type1 == char_type_node)
- return signed_char_type_node;
- if (type1 == unsigned_type_node)
- return integer_type_node;
- if (type1 == short_unsigned_type_node)
- return short_integer_type_node;
- if (type1 == long_unsigned_type_node)
- return long_integer_type_node;
- if (type1 == long_long_unsigned_type_node)
- return long_long_integer_type_node;
- return type;
-}
-
-/* Return a type the same as TYPE except unsigned or
- signed according to UNSIGNEDP. */
-
-tree
-signed_or_unsigned_type (unsignedp, type)
- int unsignedp;
- tree type;
-{
- if (TREE_CODE (type) != INTEGER_TYPE)
- return type;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
- return unsignedp ? unsigned_char_type_node : signed_char_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
- return unsignedp ? unsigned_type_node : integer_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
- return unsignedp ? short_unsigned_type_node : short_integer_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
- return unsignedp ? long_unsigned_type_node : long_integer_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
- return (unsignedp ? long_long_unsigned_type_node
- : long_long_integer_type_node);
- return type;
-}
-
-tree
-c_sizeof (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
- tree t;
-
- if (code == FUNCTION_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ANSI C++ forbids taking the sizeof a function type");
- return size_int (1);
- }
- if (code == METHOD_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ANSI C++ forbids taking the sizeof a method type");
- return size_int (1);
- }
- if (code == VOID_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ANSI C++ forbids taking the sizeof a void type");
- return size_int (1);
- }
- if (code == ERROR_MARK)
- return size_int (1);
-
- /* ARM $5.3.2: ``When applied to a reference, the result is the size of the
- referenced object.'' */
- if (code == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (TYPE_SIZE (type) == 0)
- {
- error ("sizeof applied to an incomplete type");
- return size_int (0);
- }
-
- /* Convert in case a char is more than one unit. */
- t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
- size_int (TYPE_PRECISION (char_type_node)));
- force_fit_type (t, 0);
- return t;
-}
-
-tree
-c_sizeof_nowarn (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
- tree t;
-
- if (code == FUNCTION_TYPE
- || code == METHOD_TYPE
- || code == VOID_TYPE
- || code == ERROR_MARK)
- return size_int (1);
- if (code == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (TYPE_SIZE (type) == 0)
- {
- /* ??? Tiemann, why have any diagnostic here?
- There is none in the corresponding function for C. */
- warning ("sizeof applied to an incomplete type");
- return size_int (0);
- }
-
- /* Convert in case a char is more than one unit. */
- t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
- size_int (TYPE_PRECISION (char_type_node)));
- force_fit_type (t, 0);
- return t;
-}
-
-/* Implement the __alignof keyword: Return the minimum required
- alignment of TYPE, measured in bytes. */
-
-tree
-c_alignof (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
- tree t;
-
- if (code == FUNCTION_TYPE || code == METHOD_TYPE)
- return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-
- if (code == VOID_TYPE || code == ERROR_MARK)
- return size_int (1);
-
- /* C++: this is really correct! */
- if (code == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
- force_fit_type (t, 0);
- return t;
-}
-
-/* Perform default promotions for C data used in expressions.
- Arrays and functions are converted to pointers;
- enumeral types or short or char, to int.
- In addition, manifest constants symbols are replaced by their values.
-
- C++: this will automatically bash references to their target type. */
-
-tree
-default_conversion (exp)
- tree exp;
-{
- register tree type = TREE_TYPE (exp);
- register enum tree_code code = TREE_CODE (type);
-
- if (code == OFFSET_TYPE /* || TREE_CODE (exp) == OFFSET_REF */ )
- {
- if (TREE_CODE (exp) == OFFSET_REF)
- return default_conversion (resolve_offset_ref (exp));
-
- type = TREE_TYPE (type);
- code = TREE_CODE (type);
- }
-
- if (code == REFERENCE_TYPE)
- {
- exp = convert_from_reference (exp);
- type = TREE_TYPE (exp);
- code = TREE_CODE (type);
- }
-
- /* Constants can be used directly unless they're not loadable. */
- if (TREE_CODE (exp) == CONST_DECL)
- exp = DECL_INITIAL (exp);
- /* Replace a nonvolatile const static variable with its value. */
- else if (TREE_READONLY_DECL_P (exp) && DECL_MODE (exp) != BLKmode)
- {
- exp = decl_constant_value (exp);
- type = TREE_TYPE (exp);
- }
-
- /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
- Strip such NOP_EXPRs, since EXP is being used in non-lvalue context. */
- if (TREE_CODE (exp) == NOP_EXPR
- && TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0)))
- exp = TREE_OPERAND (exp, 0);
-
- /* Normally convert enums to int,
- but convert wide enums to something wider. */
- if (code == ENUMERAL_TYPE)
- {
- type = type_for_size (MAX (TYPE_PRECISION (type),
- TYPE_PRECISION (integer_type_node)),
- (flag_traditional && TREE_UNSIGNED (type)));
- return convert (type, exp);
- }
-
- if (C_PROMOTING_INTEGER_TYPE_P (type))
- {
- /* Traditionally, unsignedness is preserved in default promotions.
- Otherwise, retain unsignedness if really not getting bigger. */
- if (TREE_UNSIGNED (type)
- && (flag_traditional
- || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
- return convert (unsigned_type_node, exp);
- return convert (integer_type_node, exp);
- }
- if (flag_traditional
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- return convert (double_type_node, exp);
- if (code == VOID_TYPE)
- {
- error ("void value not ignored as it ought to be");
- return error_mark_node;
- }
- if (code == FUNCTION_TYPE)
- {
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
- if (code == METHOD_TYPE)
- {
- if (TREE_CODE (exp) == OFFSET_REF)
- {
- my_friendly_assert (TREE_CODE (TREE_OPERAND (exp, 1)) == FUNCTION_DECL,
- 308);
- return build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
- }
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
- if (code == ARRAY_TYPE)
- {
- register tree adr;
- tree restype = TREE_TYPE (type);
- tree ptrtype;
-
- if (TREE_CODE (exp) == INDIRECT_REF)
- {
- /* Stripping away the INDIRECT_REF is not the right
- thing to do for references... */
- tree inner = TREE_OPERAND (exp, 0);
- if (TREE_CODE (TREE_TYPE (inner)) == REFERENCE_TYPE)
- {
- inner = build1 (CONVERT_EXPR,
- build_pointer_type (TREE_TYPE (TREE_TYPE (inner))),
- inner);
- TREE_REFERENCE_EXPR (inner) = 1;
- }
- return convert (TYPE_POINTER_TO (TREE_TYPE (type)), inner);
- }
-
- if (TREE_CODE (exp) == COMPOUND_EXPR)
- {
- tree op1 = default_conversion (TREE_OPERAND (exp, 1));
- return build (COMPOUND_EXPR, TREE_TYPE (op1),
- TREE_OPERAND (exp, 0), op1);
- }
-
- if (!lvalue_p (exp)
- && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
- {
- error ("invalid use of non-lvalue array");
- return error_mark_node;
- }
-
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
- restype = build_type_variant (restype, TYPE_READONLY (type),
- TYPE_VOLATILE (type));
-
- ptrtype = build_pointer_type (restype);
-
- if (TREE_CODE (exp) == VAR_DECL)
- {
- /* ??? This is not really quite correct
- in that the type of the operand of ADDR_EXPR
- is not the target type of the type of the ADDR_EXPR itself.
- Question is, can this lossage be avoided? */
- adr = build1 (ADDR_EXPR, ptrtype, exp);
- if (mark_addressable (exp) == 0)
- return error_mark_node;
- TREE_CONSTANT (adr) = staticp (exp);
- TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
- return adr;
- }
- /* This way is better for a COMPONENT_REF since it can
- simplify the offset for a component. */
- adr = build_unary_op (ADDR_EXPR, exp, 1);
- return convert (ptrtype, adr);
- }
- return exp;
-}
-
-/* Like `build_component_ref, but uses an already found field.
- Must compute visibility for C_C_D. Otherwise, ok. */
-tree
-build_component_ref_1 (datum, field, protect)
- tree datum, field;
- int protect;
-{
- register tree basetype = TREE_TYPE (datum);
- register enum tree_code code = TREE_CODE (basetype);
- register tree ref;
-
- if (code == REFERENCE_TYPE)
- {
- datum = convert_from_reference (datum);
- basetype = TREE_TYPE (datum);
- code = TREE_CODE (basetype);
- }
-
- if (! IS_AGGR_TYPE_CODE (code))
- {
- if (code != ERROR_MARK)
- error_with_decl (field, "request for member `%s' in something not a class, structure or union");
- return error_mark_node;
- }
-
- if (TYPE_SIZE (basetype) == 0)
- {
- incomplete_type_error (0, basetype);
- return error_mark_node;
- }
-
- /* Look up component name in the structure type definition. */
-
- if (field == error_mark_node)
- my_friendly_abort (115);
-
- if (TREE_STATIC (field))
- return field;
-
- if (datum == C_C_D && ! DECL_PUBLIC (field))
- {
- enum visibility_type visibility
- = compute_visibility (TYPE_BINFO (current_class_type), field);
-
- if (visibility == visibility_private)
- {
- error_with_decl (field, "field `%s' is private");
- return error_mark_node;
- }
- else if (visibility == visibility_protected)
- {
- error_with_decl (field, "field `%s' is protected");
- return error_mark_node;
- }
- }
-
- ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field);
-
- if (TREE_READONLY (datum) || TREE_READONLY (field))
- TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
- TREE_THIS_VOLATILE (ref) = 1;
-
- return ref;
-}
-
-tree
-build_component_ref (datum, component, basetype_path, protect)
- tree datum, component, basetype_path;
- int protect;
-{
- register tree basetype = TREE_TYPE (datum);
- register enum tree_code code = TREE_CODE (basetype);
- register tree field = NULL;
- register tree ref;
-
- /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it
- unless we are not to support things not strictly ANSI. */
- switch (TREE_CODE (datum))
- {
- case COMPOUND_EXPR:
- {
- tree value = build_component_ref (TREE_OPERAND (datum, 1), component,
- basetype_path, protect);
- return build (COMPOUND_EXPR, TREE_TYPE (value),
- TREE_OPERAND (datum, 0), value);
- }
- case COND_EXPR:
- return build_conditional_expr
- (TREE_OPERAND (datum, 0),
- build_component_ref (TREE_OPERAND (datum, 1), component,
- basetype_path, protect),
- build_component_ref (TREE_OPERAND (datum, 2), component,
- basetype_path, protect));
- }
-
- if (code == REFERENCE_TYPE)
- {
-#if 0
- /* TREE_REFERENCE_EXPRs are not converted by `convert_from_reference'.
- @@ Maybe that is not right. */
- if (TREE_REFERENCE_EXPR (datum))
- datum = build1 (INDIRECT_REF, TREE_TYPE (basetype), datum);
- else
-#endif
- datum = convert_from_reference (datum);
- basetype = TREE_TYPE (datum);
- code = TREE_CODE (basetype);
- }
-
- /* First, see if there is a field or component with name COMPONENT. */
- if (TREE_CODE (component) == TREE_LIST)
- {
- my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE
- && DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);
- return build (COMPONENT_REF, TREE_TYPE (component), datum, component);
- }
- if (TREE_CODE (component) == TYPE_EXPR)
- return build_component_type_expr (datum, component, NULL_TREE, protect);
-
- if (! IS_AGGR_TYPE_CODE (code))
- {
- if (code != ERROR_MARK)
- error ("request for member `%s' in something not a class, structure or union",
- IDENTIFIER_POINTER (component));
- return error_mark_node;
- }
-
- if (TYPE_SIZE (basetype) == 0)
- {
- incomplete_type_error (0, basetype);
- return error_mark_node;
- }
-
- if (TREE_CODE (component) == BIT_NOT_EXPR)
- {
- if (TYPE_IDENTIFIER (basetype) != TREE_OPERAND (component, 0))
- {
- error_with_aggr_type (basetype,
- "destructor specifier `%s::~%s' must have matching names",
- IDENTIFIER_POINTER (TREE_OPERAND (component, 0)));
- return error_mark_node;
- }
- if (! TYPE_HAS_DESTRUCTOR (basetype))
- {
- error_with_aggr_type (basetype, "type `%s' has no destructor");
- return error_mark_node;
- }
- return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
- }
-
- /* Look up component name in the structure type definition. */
- if (CLASSTYPE_VFIELD (basetype)
- && DECL_NAME (CLASSTYPE_VFIELD (basetype)) == component)
- /* Special-case this because if we use normal lookups in an ambiguous
- hierarchy, the compiler will abort (because vptr lookups are
- not supposed to be ambiguous. */
- field = CLASSTYPE_VFIELD (basetype);
- else
- {
- if (basetype_path == NULL_TREE)
- basetype_path = TYPE_BINFO (basetype);
- field = lookup_field (basetype_path, component,
- protect && ! VFIELD_NAME_P (component), 0);
- if (field == error_mark_node)
- return error_mark_node;
-
- if (field == NULL_TREE)
- {
- /* Not found as a data field, look for it as a method. If found,
- then if this is the only possible one, return it, else
- report ambiguity error. */
- tree fndecls = lookup_fnfields (basetype_path, component, 1);
- if (fndecls == error_mark_node)
- return error_mark_node;
- if (fndecls)
- {
- if (TREE_CHAIN (fndecls) == NULL_TREE
- && DECL_CHAIN (TREE_VALUE (fndecls)) == NULL_TREE)
- {
- enum visibility_type visibility;
- tree fndecl;
-
- /* Unique, so use this one now. */
- basetype = TREE_PURPOSE (fndecls);
- fndecl = TREE_VALUE (fndecls);
- visibility = compute_visibility (TREE_PURPOSE (fndecls), fndecl);
- if (visibility == visibility_public)
- {
- if (DECL_VINDEX (fndecl)
- && ! resolves_to_fixed_type_p (datum, 0))
- {
- tree addr = build_unary_op (ADDR_EXPR, datum, 0);
- addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr);
- datum = build_indirect_ref (addr, NULL_PTR);
- my_friendly_assert (datum != error_mark_node, 310);
- fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));
- }
- return fndecl;
- }
- if (visibility == visibility_protected)
- error_with_decl (fndecl, "member function `%s' is protected");
- else
- error_with_decl (fndecl, "member function `%s' is private");
- return error_mark_node;
- }
- else
- return build (COMPONENT_REF, unknown_type_node, datum, fndecls);
- }
-
- if (component == ansi_opname[(int) TYPE_EXPR])
- error ("%s has no such type conversion operator",
- code == RECORD_TYPE ? "structure" : "union");
- else
- error (code == RECORD_TYPE
- ? "structure has no member named `%s'"
- : "union has no member named `%s'",
- IDENTIFIER_POINTER (component));
- return error_mark_node;
- }
- else if (TREE_TYPE (field) == error_mark_node)
- return error_mark_node;
-
- if (TREE_CODE (field) != FIELD_DECL)
- {
- if (TREE_CODE (field) == TYPE_DECL)
- {
- error ("invalid use of type decl `%s' as expression",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- return error_mark_node;
- }
- if (DECL_RTL (field) != 0)
- assemble_external (field);
- TREE_USED (field) = 1;
- return field;
- }
- }
-
- if (DECL_FIELD_CONTEXT (field) != basetype
- && TYPE_USES_COMPLEX_INHERITANCE (basetype))
- {
- tree addr = build_unary_op (ADDR_EXPR, datum, 0);
- if (integer_zerop (addr))
- {
- error ("invalid reference to NULL ptr, use ptr-to-member instead");
- return error_mark_node;
- }
- addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);
- datum = build_indirect_ref (addr, NULL_PTR);
- my_friendly_assert (datum != error_mark_node, 311);
- }
- ref = build (COMPONENT_REF, TREE_TYPE (field), break_out_cleanups (datum), field);
-
- if (TREE_READONLY (datum) || TREE_READONLY (field))
- TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
- TREE_THIS_VOLATILE (ref) = 1;
-
- return ref;
-}
-
-/* Given an expression PTR for a pointer, return an expression
- for the value pointed to.
- ERRORSTRING is the name of the operator to appear in error messages.
-
- This function may need to overload OPERATOR_FNNAME.
- Must also handle REFERENCE_TYPEs for C++. */
-
-tree
-build_x_indirect_ref (ptr, errorstring)
- tree ptr;
- char *errorstring;
-{
- tree rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE);
-
- if (rval) return rval;
- return build_indirect_ref (ptr, errorstring);
-}
-
-tree
-build_indirect_ref (ptr, errorstring)
- tree ptr;
- char *errorstring;
-{
- register tree pointer = default_conversion (ptr);
- register tree type = TREE_TYPE (pointer);
-
- if (ptr == current_class_decl)
- return C_C_D;
-
- if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
- if (TREE_CODE (pointer) == ADDR_EXPR
- && (TREE_TYPE (TREE_OPERAND (pointer, 0))
- == TREE_TYPE (type)))
- return TREE_OPERAND (pointer, 0);
- else
- {
- tree t = TREE_TYPE (type);
- register tree ref = build1 (INDIRECT_REF,
- TYPE_MAIN_VARIANT (t), pointer);
-
- TREE_READONLY (ref) = TYPE_READONLY (t);
- TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
- TREE_SIDE_EFFECTS (ref)
- = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
- return ref;
- }
- else if (pointer != error_mark_node)
- {
- if (errorstring)
- error ("invalid type argument of `%s'", errorstring);
- else
- error ("invalid type argument");
- }
- return error_mark_node;
-}
-
-/* This handles expressions of the form "a[i]", which denotes
- an array reference.
-
- This is logically equivalent in C to *(a+i), but we may do it differently.
- If A is a variable or a member, we generate a primitive ARRAY_REF.
- This avoids forcing the array out of registers, and can work on
- arrays that are not lvalues (for example, members of structures returned
- by functions).
-
- If INDEX is of some user-defined type, it must be converted to
- integer type. Otherwise, to make a compatible PLUS_EXPR, it
- will inherit the type of the array, which will be some pointer type. */
-
-tree
-build_x_array_ref (array, index)
- tree array, index;
-{
- tree rval;
-
- rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, index, NULL_TREE);
- if (rval)
- return rval;
- return build_array_ref (array, index);
-}
-
-tree
-build_array_ref (array, index)
- tree array, index;
-{
- tree itype;
-
- if (index == 0)
- {
- error ("subscript missing in array reference");
- return error_mark_node;
- }
-
- if (TREE_TYPE (array) == error_mark_node
- || TREE_TYPE (index) == error_mark_node)
- return error_mark_node;
-
- itype = TREE_TYPE (index);
- /* We must check here for the reference, so we can do the possible
- conversions immediately afterwards. */
- if (TREE_CODE (itype) == REFERENCE_TYPE)
- {
- index = convert_from_reference (index);
- itype = TREE_TYPE (index);
- }
-
- if (IS_AGGR_TYPE (itype))
- {
- if (TYPE_HAS_INT_CONVERSION (itype))
- index = build_type_conversion (CONVERT_EXPR,
- integer_type_node, index, 1);
- else
- {
- error_with_aggr_type (itype,
- "type `%s' requires integer conversion for array indexing");
- return error_mark_node;
- }
- }
-
- if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
- && TREE_CODE (array) != INDIRECT_REF)
- {
- tree rval, type;
-
- /* Subscripting with type char is likely to lose
- on a machine where chars are signed.
- So warn on any machine, but optionally.
- Don't warn for unsigned char since that type is safe.
- Don't warn for signed char because anyone who uses that
- must have done so deliberately. */
- if (warn_char_subscripts
- && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
- warning ("array subscript has type `char'");
-
- /* Apply default promotions *after* noticing character types. */
- index = default_conversion (index);
-
- if (TREE_CODE (TREE_TYPE (index)) != INTEGER_TYPE)
- {
- error ("array subscript is not an integer");
- return error_mark_node;
- }
-
- /* An array that is indexed by a non-constant
- cannot be stored in a register; we must be able to do
- address arithmetic on its address.
- Likewise an array of elements of variable size. */
- if (TREE_CODE (index) != INTEGER_CST
- || (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))) != 0
- && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
- {
- if (mark_addressable (array) == 0)
- return error_mark_node;
- }
-
- /* Note in C++ we don't bother warning about subscripting a
- `register' array, since it's legal in C++ to take the address
- of something with that storage specification. */
- if (pedantic && !lvalue_p (array))
- pedwarn ("ANSI C++ forbids subscripting non-lvalue array");
-
- if (pedantic)
- {
- tree foo = array;
- while (TREE_CODE (foo) == COMPONENT_REF)
- foo = TREE_OPERAND (foo, 0);
- if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
- pedwarn ("ANSI C++ forbids subscripting non-lvalue array");
- }
-
- type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
- rval = build (ARRAY_REF, type, array, index);
- /* Array ref is const/volatile if the array elements are
- or if the array is.. */
- TREE_READONLY (rval)
- |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
- | TREE_READONLY (array));
- TREE_SIDE_EFFECTS (rval)
- |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
- | TREE_SIDE_EFFECTS (array));
- TREE_THIS_VOLATILE (rval)
- |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
- /* This was added by rms on 16 Nov 91.
- It fixes vol struct foo *a; a->elts[1]
- in an inline function.
- Hope it doesn't break something else. */
- | TREE_THIS_VOLATILE (array));
- return require_complete_type (fold (rval));
- }
-
- {
- tree ar = default_conversion (array);
- tree ind = default_conversion (index);
-
- /* Put the integer in IND to simplify error checking. */
- if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)
- {
- tree temp = ar;
- ar = ind;
- ind = temp;
- }
-
- if (ar == error_mark_node)
- return ar;
-
- if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE)
- {
- error ("subscripted value is neither array nor pointer");
- return error_mark_node;
- }
- if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)
- {
- error ("array subscript is not an integer");
- return error_mark_node;
- }
-
- return build_indirect_ref (build_binary_op_nodefault (PLUS_EXPR, ar, ind, PLUS_EXPR),
- "array indexing");
- }
-}
-
-/* Build a function call to function FUNCTION with parameters PARAMS.
- PARAMS is a list--a chain of TREE_LIST nodes--in which the
- TREE_VALUE of each node is a parameter-expression.
- FUNCTION's data type may be a function type or a pointer-to-function.
-
- For C++: If FUNCTION's data type is a TREE_LIST, then the tree list
- is the list of possible methods that FUNCTION could conceivably
- be. If the list of methods comes from a class, then it will be
- a list of lists (where each element is associated with the class
- that produced it), otherwise it will be a simple list (for
- functions overloaded in global scope).
-
- In the first case, TREE_VALUE (function) is the head of one of those
- lists, and TREE_PURPOSE is the name of the function.
-
- In the second case, TREE_PURPOSE (function) is the function's
- name directly.
-
- DECL is the class instance variable, usually CURRENT_CLASS_DECL. */
-
-/*
- * [eichin:19911015.1726EST] actually return a possibly incomplete
- * type
- */
-tree
-build_x_function_call (function, params, decl)
- tree function, params, decl;
-{
- tree type = TREE_TYPE (function);
- int is_method = ((TREE_CODE (function) == TREE_LIST
- && current_class_type != NULL_TREE
- && IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function)) == function)
- || TREE_CODE (function) == IDENTIFIER_NODE
- || TREE_CODE (type) == METHOD_TYPE
- || (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE));
-
- /* Handle methods, friends, and overloaded functions, respectively. */
- if (is_method)
- {
- if (TREE_CODE (function) == FUNCTION_DECL)
- {
- if (DECL_NAME (function))
- function = DECL_NAME (function);
- else
- function = TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function));
- }
- else if (TREE_CODE (function) == TREE_LIST)
- {
-#if 0
- if (TREE_CODE (TREE_VALUE (function)) == TREE_LIST)
- function = TREE_PURPOSE (TREE_VALUE (function));
- else
- function = TREE_PURPOSE (function);
-#else
- my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312);
- function = TREE_PURPOSE (function);
-#endif
- }
- else if (TREE_CODE (function) != IDENTIFIER_NODE)
- {
- /* Call via a pointer to member function. */
- if (decl == NULL_TREE)
- {
- error ("pointer to member function called, but not in class scope");
- return error_mark_node;
- }
- if (TREE_CODE (TREE_TYPE (function)) != POINTER_TYPE)
- function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE, function);
- goto do_x_function;
- }
-
- /* this is an abbreviated method call.
- must go through here in case it is a virtual function.
- @@ Perhaps this could be optimized. */
-
- if (decl == NULL_TREE)
- {
- if (current_class_type == NULL_TREE)
- {
- error ("object missing in call to method `%s'",
- IDENTIFIER_POINTER (function));
- return error_mark_node;
- }
- /* Yow: call from a static member function. */
- decl = build1 (NOP_EXPR,
- TYPE_POINTER_TO (current_class_type),
- error_mark_node);
- }
-
- return build_method_call (decl, function, params,
- NULL_TREE, LOOKUP_NORMAL);
- }
- else if (TREE_CODE (function) == COMPONENT_REF
- && type == unknown_type_node)
- {
- function = TREE_PURPOSE (TREE_OPERAND (function, 1));
- return build_method_call (decl, function, params,
- NULL_TREE, LOOKUP_NORMAL);
- }
- else if (TREE_CODE (function) == TREE_LIST)
- {
- if (TREE_CHAIN (function) != NULL_TREE)
- {
- if (TREE_CODE (TREE_VALUE (function)) == TEMPLATE_DECL)
- return build_overload_call_maybe (TREE_PURPOSE (function),
- params, 1, (struct candidate *)0);
- else
- return build_overload_call (TREE_PURPOSE (function), params, 1,
- (struct candidate *)0);
- }
- else if (TREE_VALUE (function) == NULL_TREE)
- {
- error ("function `%s' declared overloaded, but no definitions appear with which to resolve it",
- IDENTIFIER_POINTER (TREE_PURPOSE (function)));
- return error_mark_node;
- }
- else if (TREE_CODE (TREE_VALUE (function)) == TEMPLATE_DECL)
- return build_overload_call_maybe (TREE_PURPOSE (function),
- params, 1, (struct candidate *)0);
- else
- function = TREE_VALUE (function);
- }
- else if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
- && (TREE_CODE (function) == VAR_DECL
- || TREE_CODE (function) == PARM_DECL
- || TREE_CODE (function) == FIELD_DECL))
- {
- error_with_decl (function, "call via pointer-to-member-function `%s' must be composed with object");
- return error_mark_node;
- }
-
- do_x_function:
- if (TREE_CODE (function) == OFFSET_REF)
- {
- /* If the component is a data element (or a virtual function), we play
- games here to make things work. */
- tree decl_addr;
-
- if (TREE_OPERAND (function, 0))
- decl = TREE_OPERAND (function, 0);
- else
- decl = C_C_D;
-
- decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
- function = get_member_function (&decl_addr, decl,
- TREE_OPERAND (function, 1));
- params = tree_cons (NULL_TREE, decl_addr, params);
- return build_function_call (function, params);
- }
-
- type = TREE_TYPE (function);
- if (type != error_mark_node)
- {
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (TYPE_LANG_SPECIFIC (type) && TYPE_OVERLOADS_CALL_EXPR (type))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params, NULL_TREE);
- }
-
- if (is_method)
- {
- tree fntype = TREE_TYPE (function);
- tree ctypeptr;
- /* Explicitly named method? */
- if (TREE_CODE (function) == FUNCTION_DECL)
- ctypeptr = TYPE_POINTER_TO (DECL_CLASS_CONTEXT (function));
- /* Expression with ptr-to-method type? It could either be a plain
- usage, or it might be a case where the ptr-to-method is being
- passed in as an argument. */
- else if (TREE_CODE (fntype) == POINTER_TYPE
- && (TREE_CODE_CLASS (TREE_CODE (function)) == 'e'
- || ((TREE_CODE_CLASS (TREE_CODE (function)) == 'd'
- || TREE_CODE_CLASS (TREE_CODE (function)) == 'r')
- && TREE_CODE (TREE_TYPE (fntype)) == METHOD_TYPE)))
- {
- tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
- ctypeptr = TYPE_POINTER_TO (rec);
- }
- /* Unexpected node type? */
- else
- my_friendly_abort (116);
- if (decl == NULL_TREE)
- {
- if (current_function_decl
- && DECL_STATIC_FUNCTION_P (current_function_decl))
- error ("invalid call to member function needing `this' in static member function scope");
- else
- error ("pointer to member function called, but not in class scope");
- return error_mark_node;
- }
- if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
- {
- decl = build_unary_op (ADDR_EXPR, decl, 0);
- decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl);
- }
- else
- decl = build_c_cast (ctypeptr, decl);
- params = tree_cons (NULL_TREE, decl, params);
- }
-
- return build_function_call (function, params);
-}
-
-tree
-build_function_call_real (function, params, require_complete)
- tree function, params;
- int require_complete;
-{
- register tree fntype, fndecl;
- register tree value_type;
- register tree coerced_params;
- int is_method;
-
- /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
- Strip such NOP_EXPRs, since FUNCTION is used in non-lvalue context. */
- if (TREE_CODE (function) == NOP_EXPR
- && TREE_TYPE (function) == TREE_TYPE (TREE_OPERAND (function, 0)))
- function = TREE_OPERAND (function, 0);
-
- if (TREE_CODE (function) == FUNCTION_DECL)
- {
- GNU_xref_call (current_function_decl,
- IDENTIFIER_POINTER (DECL_NAME (function)
- ? DECL_NAME (function)
- : TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function))));
- assemble_external (function);
- fndecl = function;
-
- /* Convert anything with function type to a pointer-to-function. */
- if (pedantic
- && DECL_NAME (function)
- && IDENTIFIER_LENGTH (DECL_NAME (function)) == 4
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (function)), "main")
- && DECL_CONTEXT (function) == NULL_TREE)
- {
- pedwarn ("ANSI C++ forbids calling `main' from within program");
- }
-
- /* Differs from default_conversion by not setting TREE_ADDRESSABLE
- (because calling an inline function does not mean the function
- needs to be separately compiled). */
-
- if (! DECL_INLINE (function))
- {
- assemble_external (function);
- TREE_USED (function) = 1;
- }
-
- fntype = build_type_variant (TREE_TYPE (function),
- TREE_READONLY (function),
- TREE_THIS_VOLATILE (function));
- function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
- }
- else
- {
- fndecl = NULL_TREE;
-
- /* Convert anything with function type to a pointer-to-function. */
- if (function == error_mark_node)
- return error_mark_node;
- function = default_conversion (function);
- }
-
- fntype = TREE_TYPE (function);
-
- is_method = (TREE_CODE (fntype) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (fntype)) == METHOD_TYPE);
-
- if (!(TREE_CODE (fntype) == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE || is_method)))
- {
- error ("called object is not a function");
- return error_mark_node;
- }
-
- /* fntype now gets the type of function pointed to. */
- fntype = TREE_TYPE (fntype);
-
- /* Convert the parameters to the types declared in the
- function prototype, or apply default promotions. */
-
- coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
- params, fndecl, LOOKUP_NORMAL);
-
- /* Recognize certain built-in functions so we can make tree-codes
- other than CALL_EXPR. We do this when it enables fold-const.c
- to do something useful. */
-
- if (TREE_CODE (function) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
- && DECL_BUILT_IN (TREE_OPERAND (function, 0)))
- switch (DECL_FUNCTION_CODE (TREE_OPERAND (function, 0)))
- {
- case BUILT_IN_ABS:
- case BUILT_IN_LABS:
- case BUILT_IN_FABS:
- if (coerced_params == 0)
- return integer_zero_node;
- return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
- }
-
- /* C++ */
- value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
- {
- register tree result =
- build (CALL_EXPR, value_type,
- function, coerced_params, NULL_TREE);
-
- TREE_SIDE_EFFECTS (result) = 1;
- TREE_RAISES (result) |= !! TYPE_RAISES_EXCEPTIONS (fntype);
- if (! require_complete)
- return result;
- if (value_type == void_type_node)
- return result;
- return require_complete_type (result);
- }
-}
-
-tree
-build_function_call (function, params)
- tree function, params;
-{
- return build_function_call_real (function, params, 1);
-}
-
-tree
-build_function_call_maybe (function, params)
- tree function, params;
-{
- return build_function_call_real (function, params, 0);
-}
-
-
-/* Convert the actual parameter expressions in the list VALUES
- to the types in the list TYPELIST.
- If parmdecls is exhausted, or when an element has NULL as its type,
- perform the default conversions.
-
- RETURN_LOC is the location of the return value, if known, NULL_TREE
- otherwise. This is useful in the case where we can avoid creating
- a temporary variable in the case where we can initialize the return
- value directly. If we are not eliding constructors, then we set this
- to NULL_TREE to avoid this avoidance.
-
- NAME is an IDENTIFIER_NODE or 0. It is used only for error messages.
-
- This is also where warnings about wrong number of args are generated.
-
- Return a list of expressions for the parameters as converted.
-
- Both VALUES and the returned value are chains of TREE_LIST nodes
- with the elements of the list in the TREE_VALUE slots of those nodes.
-
- In C++, unspecified trailing parameters can be filled in with their
- default arguments, if such were specified. Do so here. */
-
-tree
-convert_arguments (return_loc, typelist, values, fndecl, flags)
- tree return_loc, typelist, values, fndecl;
- int flags;
-{
- extern tree gc_protect_fndecl;
- register tree typetail, valtail;
- register tree result = NULL_TREE;
- char *called_thing;
- int maybe_raises = 0;
- int i = 0;
-
- if (! flag_elide_constructors)
- return_loc = 0;
-
- if (fndecl)
- {
- if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
- {
- if (DECL_NAME (fndecl) == NULL_TREE
- || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
- called_thing = "constructor";
- else
- called_thing = "member function";
- i -= 1;
- }
- else
- {
- called_thing = "function";
- }
- }
-
- for (valtail = values, typetail = typelist;
- valtail;
- valtail = TREE_CHAIN (valtail), i++)
- {
- register tree type = typetail ? TREE_VALUE (typetail) : 0;
- register tree val = TREE_VALUE (valtail);
-
- if (type == void_type_node)
- {
- if (fndecl)
- {
- char *buf = (char *)alloca (40 + strlen (called_thing));
- sprintf (buf, "too many arguments to %s `%%s'", called_thing);
- error_with_decl (fndecl, buf);
- error ("at this point in file");
- }
- else
- error ("too many arguments to function");
- /* In case anybody wants to know if this argument
- list is valid. */
- if (result)
- TREE_TYPE (tree_last (result)) = error_mark_node;
- break;
- }
-
- /* The tree type of the parameter being passed may not yet be
- known. In this case, its type is TYPE_UNKNOWN, and will
- be instantiated by the type given by TYPE. If TYPE
- is also NULL, the tree type of VAL is ERROR_MARK_NODE. */
- if (type && type_unknown_p (val))
- val = require_instantiated_type (type, val, integer_zero_node);
- else if (type_unknown_p (val))
- {
- /* Strip the `&' from an overloaded FUNCTION_DECL. */
- if (TREE_CODE (val) == ADDR_EXPR)
- val = TREE_OPERAND (val, 0);
- if (TREE_CODE (val) == TREE_LIST
- && TREE_CHAIN (val) == NULL_TREE
- && TREE_TYPE (TREE_VALUE (val)) != NULL_TREE
- && (TREE_TYPE (val) == unknown_type_node
- || DECL_CHAIN (TREE_VALUE (val)) == NULL_TREE))
- /* Instantiates automatically. */
- val = TREE_VALUE (val);
- else
- {
- error ("insufficient type information in parameter list");
- val = integer_zero_node;
- }
- }
- else if (TREE_CODE (val) == OFFSET_REF)
- val = resolve_offset_ref (val);
-
- {
-#if 0
- /* This code forces the assumption that if we have a ptr-to-func
- type in an arglist, that every routine that wants to check
- its validity has done so, and thus we need not do any
- more conversion. I don't remember why this is necessary. */
- else if (TREE_CODE (ttype) == FUNCTION_TYPE
- && (type == NULL
- || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (type)) == VOID_TYPE))
- {
- type = build_pointer_type (ttype);
- }
-#endif
- }
-
- /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
- Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */
- if (TREE_CODE (val) == NOP_EXPR
- && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)))
- val = TREE_OPERAND (val, 0);
-
- if ((type == 0 || TREE_CODE (type) != REFERENCE_TYPE)
- && (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE))
- val = default_conversion (val);
-
- val = require_complete_type (val);
-
- if (val == error_mark_node)
- continue;
-
- maybe_raises |= TREE_RAISES (val);
-
- if (type != 0)
- {
- /* Formal parm type is specified by a function prototype. */
- tree parmval;
-
- if (TYPE_SIZE (type) == 0)
- {
- error ("parameter type of called function is incomplete");
- parmval = val;
- }
- else
- {
-#ifdef PROMOTE_PROTOTYPES
- /* Rather than truncating and then reextending,
- convert directly to int, if that's the type we will want. */
- if (! flag_traditional
- && TREE_CODE (type) == INTEGER_TYPE
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- type = integer_type_node;
-#endif
- parmval = convert_for_initialization (return_loc, type, val, flags,
- "argument passing", fndecl, i);
-#ifdef PROMOTE_PROTOTYPES
- if (TREE_CODE (type) == INTEGER_TYPE
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- parmval = default_conversion (parmval);
-#endif
- }
- result = tree_cons (NULL_TREE, parmval, result);
- }
- else
- {
- if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
- val = convert_from_reference (val);
-
- if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
- && (TYPE_PRECISION (TREE_TYPE (val))
- < TYPE_PRECISION (double_type_node)))
- /* Convert `float' to `double'. */
- result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
- else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val))
- && (TYPE_GETS_INIT_REF (TREE_TYPE (val))
- || TYPE_GETS_ASSIGN_REF (TREE_TYPE (val))))
- {
- if (pedantic)
- pedwarn ("ANSI C++ forbids passing objects of type `%s' through `...'",
- TYPE_NAME_STRING (TREE_TYPE (val)));
- else
- warning ("cannot pass objects of type `%s' through `...'",
- TYPE_NAME_STRING (TREE_TYPE (val)));
- result = tree_cons (NULL_TREE, val, result);
- }
- else
- /* Convert `short' and `char' to full-size `int'. */
- result = tree_cons (NULL_TREE, default_conversion (val), result);
- }
-
- if (flag_gc
- /* There are certain functions for which we don't need
- to protect our arguments. GC_PROTECT_FNDECL is one. */
- && fndecl != gc_protect_fndecl
- && type_needs_gc_entry (TREE_TYPE (TREE_VALUE (result)))
- && ! value_safe_from_gc (NULL_TREE, TREE_VALUE (result)))
- /* This will build a temporary variable whose cleanup is
- to clear the obstack entry. */
- TREE_VALUE (result) = protect_value_from_gc (NULL_TREE,
- TREE_VALUE (result));
-
- if (typetail)
- typetail = TREE_CHAIN (typetail);
- }
-
- if (typetail != 0 && typetail != void_list_node)
- {
- /* See if there are default arguments that can be used */
- if (TREE_PURPOSE (typetail))
- {
- while (typetail != void_list_node)
- {
- tree type = TREE_VALUE (typetail);
- tree val = TREE_PURPOSE (typetail);
- tree parmval;
-
- if (val == NULL_TREE)
- parmval = error_mark_node;
- else if (TREE_CODE (val) == CONSTRUCTOR)
- {
- parmval = digest_init (type, val, (tree *)0);
- parmval = convert_for_initialization (return_loc, type, parmval, flags,
- "default constructor", fndecl, i);
- }
- else
- {
- /* This could get clobbered by the following call. */
- if (TREE_HAS_CONSTRUCTOR (val))
- val = copy_node (val);
-
- parmval = convert_for_initialization (return_loc, type, val, flags,
- "default argument", fndecl, i);
-#ifdef PROMOTE_PROTOTYPES
- if (TREE_CODE (type) == INTEGER_TYPE
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- parmval = default_conversion (parmval);
-#endif
- }
- maybe_raises |= TREE_RAISES (parmval);
-
- if (flag_gc
- && type_needs_gc_entry (TREE_TYPE (parmval))
- && ! value_safe_from_gc (NULL_TREE, parmval))
- parmval = protect_value_from_gc (NULL_TREE, parmval);
-
- result = tree_cons (0, parmval, result);
- typetail = TREE_CHAIN (typetail);
- /* ends with `...'. */
- if (typetail == NULL_TREE)
- break;
- }
- }
- else
- {
- if (fndecl)
- {
- char *buf = (char *)alloca (32 + strlen (called_thing));
- sprintf (buf, "too few arguments to %s `%%s'", called_thing);
- error_with_decl (fndecl, buf);
- error ("at this point in file");
- }
- else
- error ("too few arguments to function");
- return error_mark_list;
- }
- }
- if (result)
- TREE_RAISES (result) = maybe_raises;
-
- return nreverse (result);
-}
-
-/* Build a binary-operation expression, after performing default
- conversions on the operands. CODE is the kind of expression to build. */
-
-tree
-build_x_binary_op (code, arg1, arg2)
- enum tree_code code;
- tree arg1, arg2;
-{
- tree rval;
-
- /* If there's any way we can call this function, do so. */
- if (rval = build_opfncall (code, 0, arg1, arg2, NULL_TREE))
- {
- /* If it's accessible, we win. */
- if (rval = build_opfncall (code, LOOKUP_PROTECT, arg1, arg2, NULL_TREE))
- return rval;
- /* Else, report an error. */
- build_opfncall (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
- return error_mark_node;
- }
- if (code == MEMBER_REF)
- return build_m_component_ref (build_indirect_ref (arg1, NULL_PTR),
- build_indirect_ref (arg2, NULL_PTR));
- return build_binary_op (code, arg1, arg2, 1);
-}
-
-tree
-build_binary_op (code, arg1, arg2, convert_p)
- enum tree_code code;
- tree arg1, arg2;
- int convert_p;
-{
- tree type1, type2;
- tree args[2];
-
- args[0] = arg1;
- args[1] = arg2;
-
- if (convert_p)
- {
- args[0] = default_conversion (args[0]);
- args[1] = default_conversion (args[1]);
-
- if (type_unknown_p (args[0]))
- {
- args[0] = instantiate_type (TREE_TYPE (args[1]), args[0], 1);
- args[0] = default_conversion (args[0]);
- }
- else if (type_unknown_p (args[1]))
- {
- args[1] = require_instantiated_type (TREE_TYPE (args[0]),
- args[1],
- error_mark_node);
- args[1] = default_conversion (args[1]);
- }
-
- type1 = TREE_TYPE (args[0]);
- type2 = TREE_TYPE (args[1]);
-
- if (IS_AGGR_TYPE_2 (type1, type2))
- {
- /* Try to convert this to something reasonable. */
- if (! build_default_binary_type_conversion(code, &args[0], &args[1]))
- return error_mark_node;
- }
- else if (IS_AGGR_TYPE (type1) || IS_AGGR_TYPE (type2))
- {
- int convert_index = IS_AGGR_TYPE (type2);
- /* Avoid being tripped up by things like (ARG1 != 0). */
- tree types[2], try;
-
- types[0] = type1; types[1] = type2;
- try = build_type_conversion (code, types[convert_index ^ 1],
- args[convert_index], 1);
-
- if (try == 0
- && args[1] == integer_zero_node
- && (code == NE_EXPR || code == EQ_EXPR))
- try = build_type_conversion (code, ptr_type_node,
- args[convert_index], 1);
- if (try == 0)
- {
- error_with_aggr_type (types[convert_index],
- "no member function `%s::operator %s'",
- opname_tab[(int) code]
- ? opname_tab[(int) code]
- : "<unknown>");
- return error_mark_node;
- }
- if (try == error_mark_node)
- error ("ambiguous pointer conversion");
- args[convert_index] = try;
- }
- }
- return build_binary_op_nodefault (code, args[0], args[1], code);
-}
-
-/* Build a binary-operation expression without default conversions.
- CODE is the kind of expression to build.
- This function differs from `build' in several ways:
- the data type of the result is computed and recorded in it,
- warnings are generated if arg data types are invalid,
- special handling for addition and subtraction of pointers is known,
- and some optimization is done (operations on narrow ints
- are done in the narrower type when that gives the same result).
- Constant folding is also done before the result is returned.
-
- ERROR_CODE is the code that determines what to say in error messages.
- It is usually, but not always, the same as CODE.
-
- Note that the operands will never have enumeral types
- because either they have just had the default conversions performed
- or they have both just been converted to some other type in which
- the arithmetic is to be done.
-
- C++: must do special pointer arithmetic when implementing
- multiple inheritance. */
-
-tree
-build_binary_op_nodefault (code, op0, op1, error_code)
- enum tree_code code;
- tree op0, op1;
- enum tree_code error_code;
-{
- tree type0 = TREE_TYPE (op0), type1 = TREE_TYPE (op1);
-
- /* The expression codes of the data types of the arguments tell us
- whether the arguments are integers, floating, pointers, etc. */
- register enum tree_code code0 = TREE_CODE (type0);
- register enum tree_code code1 = TREE_CODE (type1);
-
- /* Expression code to give to the expression when it is built.
- Normally this is CODE, which is what the caller asked for,
- but in some special cases we change it. */
- register enum tree_code resultcode = code;
-
- /* Data type in which the computation is to be performed.
- In the simplest cases this is the common type of the arguments. */
- register tree result_type = NULL;
-
- /* Nonzero means operands have already been type-converted
- in whatever way is necessary.
- Zero means they need to be converted to RESULT_TYPE. */
- int converted = 0;
-
- /* Nonzero means after finally constructing the expression
- give it this type. Otherwise, give it type RESULT_TYPE. */
- tree final_type = 0;
-
- /* Nonzero if this is an operation like MIN or MAX which can
- safely be computed in short if both args are promoted shorts.
- Also implies COMMON.
- -1 indicates a bitwise operation; this makes a difference
- in the exact conditions for when it is safe to do the operation
- in a narrower mode. */
- int shorten = 0;
-
- /* Nonzero if this is a comparison operation;
- if both args are promoted shorts, compare the original shorts.
- Also implies COMMON. */
- int short_compare = 0;
-
- /* Nonzero if this is a right-shift operation, which can be computed on the
- original short and then promoted if the operand is a promoted short. */
- int short_shift = 0;
-
- /* Nonzero means set RESULT_TYPE to the common type of the args. */
- int common = 0;
-
- /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
- STRIP_TYPE_NOPS (op0);
- STRIP_TYPE_NOPS (op1);
-
- /* If an error was already reported for one of the arguments,
- avoid reporting another error. */
-
- if (code0 == ERROR_MARK || code1 == ERROR_MARK)
- return error_mark_node;
-
- switch (code)
- {
- case PLUS_EXPR:
- /* Handle the pointer + int case. */
- if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- return pointer_int_sum (PLUS_EXPR, op0, op1);
- else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
- return pointer_int_sum (PLUS_EXPR, op1, op0);
- else
- common = 1;
- break;
-
- case MINUS_EXPR:
- /* Subtraction of two similar pointers.
- We must subtract them as integers, then divide by object size. */
- if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
- && comp_target_types (type0, type1, 1))
- return pointer_diff (op0, op1);
- /* Handle pointer minus int. Just like pointer plus int. */
- else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- return pointer_int_sum (MINUS_EXPR, op0, op1);
- else
- common = 1;
- break;
-
- case MULT_EXPR:
- common = 1;
- break;
-
- case TRUNC_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case EXACT_DIV_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
- {
- if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
- resultcode = RDIV_EXPR;
- else
- shorten = 1;
- common = 1;
- }
- break;
-
- case BIT_AND_EXPR:
- case BIT_ANDTC_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
- shorten = -1;
- /* If one operand is a constant, and the other is a short type
- that has been converted to an int,
- really do the work in the short type and then convert the
- result to int. If we are lucky, the constant will be 0 or 1
- in the short type, making the entire operation go away. */
- if (TREE_CODE (op0) == INTEGER_CST
- && TREE_CODE (op1) == NOP_EXPR
- && TYPE_PRECISION (type1) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))
- && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op1, 0))))
- {
- final_type = result_type;
- op1 = TREE_OPERAND (op1, 0);
- result_type = TREE_TYPE (op1);
- }
- if (TREE_CODE (op1) == INTEGER_CST
- && TREE_CODE (op0) == NOP_EXPR
- && TYPE_PRECISION (type0) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))
- && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
- {
- final_type = result_type;
- op0 = TREE_OPERAND (op0, 0);
- result_type = TREE_TYPE (op0);
- }
- break;
-
- case TRUNC_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
- shorten = 1;
- break;
-
- case TRUTH_ANDIF_EXPR:
- case TRUTH_ORIF_EXPR:
- case TRUTH_AND_EXPR:
- case TRUTH_OR_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE || code1 == REAL_TYPE))
- {
- /* Result of these operations is always an int,
- but that does not mean the operands should be
- converted to ints! */
- result_type = integer_type_node;
- op0 = truthvalue_conversion (op0);
- op1 = truthvalue_conversion (op1);
- converted = 1;
- }
- break;
-
- /* Shift operations: result has same type as first operand;
- always convert second operand to int.
- Also set SHORT_SHIFT if shifting rightward. */
-
- case RSHIFT_EXPR:
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
- {
- result_type = type0;
- if (TREE_CODE (op1) == INTEGER_CST)
- {
- if (tree_int_cst_lt (op1, integer_zero_node))
- warning ("shift count is negative");
- else
- {
- if (TREE_INT_CST_LOW (op1) | TREE_INT_CST_HIGH (op1))
- short_shift = 1;
- if (TREE_INT_CST_HIGH (op1) != 0
- || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
- >= TYPE_PRECISION (type0)))
- warning ("shift count >= width of type");
- }
- }
- /* Convert the shift-count to an integer, regardless of
- size of value being shifted. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
- /* Avoid converting op1 to result_type later. */
- converted = 1;
- }
- break;
-
- case LSHIFT_EXPR:
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
- {
- result_type = type0;
- if (TREE_CODE (op1) == INTEGER_CST)
- {
- if (tree_int_cst_lt (op1, integer_zero_node))
- warning ("shift count is negative");
- else if (TREE_INT_CST_HIGH (op1) != 0
- || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
- >= TYPE_PRECISION (type0)))
- warning ("shift count >= width of type");
- }
- /* Convert the shift-count to an integer, regardless of
- size of value being shifted. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
- /* Avoid converting op1 to result_type later. */
- converted = 1;
- }
- break;
-
- case RROTATE_EXPR:
- case LROTATE_EXPR:
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
- {
- result_type = type0;
- if (TREE_CODE (op1) == INTEGER_CST)
- {
- if (tree_int_cst_lt (op1, integer_zero_node))
- warning ("shift count is negative");
- else if (TREE_INT_CST_HIGH (op1) != 0
- || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
- >= TYPE_PRECISION (type0)))
- warning ("shift count >= width of type");
- }
- /* Convert the shift-count to an integer, regardless of
- size of value being shifted. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
- }
- break;
-
- case EQ_EXPR:
- case NE_EXPR:
- /* Result of comparison is always int,
- but don't convert the args to int! */
- result_type = integer_type_node;
- converted = 1;
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
- short_compare = 1;
- else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
- {
- register tree tt0 = TYPE_MAIN_VARIANT (TREE_TYPE (type0));
- register tree tt1 = TYPE_MAIN_VARIANT (TREE_TYPE (type1));
- /* Anything compares with void *. void * compares with anything.
- Otherwise, the targets must be the same. */
- if (tt0 != tt1 && TREE_CODE (tt0) == RECORD_TYPE
- && TREE_CODE (tt1) == RECORD_TYPE)
- {
- tree base = common_base_type (tt0, tt1);
- if (base == NULL_TREE)
- warning ("comparison of distinct object pointer types");
- else if (base == error_mark_node)
- {
- message_2_types (error, "comparison of pointer types `%s*' and `%s*' requires conversion to ambiguous supertype", tt0, tt1);
- return error_mark_node;
- }
- else
- {
- if (integer_zerop (op0))
- op0 = null_pointer_node;
- else
- op0 = convert_pointer_to (base, op0);
- if (integer_zerop (op1))
- op1 = null_pointer_node;
- else
- op1 = convert_pointer_to (base, op1);
- }
- }
- else if (comp_target_types (type0, type1, 1))
- ;
- else if (tt0 == void_type_node)
- {
- if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids comparison of `void *' with function pointer");
- }
- else if (tt1 == void_type_node)
- {
- if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids comparison of `void *' with function pointer");
- }
- else
- warning ("comparison of distinct pointer types lacks a cast");
- }
- else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
- && integer_zerop (op1))
- op1 = null_pointer_node;
- else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
- && integer_zerop (op0))
- op0 = null_pointer_node;
- else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- {
- error ("ANSI C++ forbids comparison between pointer and integer");
- op1 = convert (TREE_TYPE (op0), op1);
- }
- else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
- {
- error ("ANSI C++ forbids comparison between pointer and integer");
- op0 = convert (TREE_TYPE (op1), op0);
- }
- else
- /* If args are not valid, clear out RESULT_TYPE
- to cause an error message later. */
- result_type = 0;
- break;
-
- case MAX_EXPR:
- case MIN_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
- shorten = 1;
- else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
- {
- if (! comp_target_types (type0, type1, 1))
- warning ("comparison of distinct pointer types lacks a cast");
- else if (pedantic
- && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions");
- result_type = common_type (type0, type1);
- }
- break;
-
- case LE_EXPR:
- case GE_EXPR:
- case LT_EXPR:
- case GT_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
- short_compare = 1;
- else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
- {
- if (! comp_target_types (type0, type1, 1))
- warning ("comparison of distinct pointer types lacks a cast");
- else if (pedantic
- && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions");
- result_type = integer_type_node;
- }
- else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
- && integer_zerop (op1))
- {
- result_type = integer_type_node;
- op1 = null_pointer_node;
- if (! flag_traditional)
- warning ("ordered comparison of pointer with integer zero");
- }
- else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
- && integer_zerop (op0))
- {
- result_type = integer_type_node;
- op0 = null_pointer_node;
- if (pedantic)
- pedwarn ("ANSI C++ forbids ordered comparison of pointer with integer zero");
- }
- else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- {
- result_type = integer_type_node;
- if (pedantic)
- pedwarn ("ANSI C++ forbids comparison between pointer and integer");
- else if (! flag_traditional)
- warning ("comparison between pointer and integer");
- op1 = convert (TREE_TYPE (op0), op1);
- }
- else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
- {
- result_type = integer_type_node;
- if (pedantic)
- pedwarn ("ANSI C++ forbids comparison between pointer and integer");
- else if (! flag_traditional)
- warning ("comparison between pointer and integer");
- op0 = convert (TREE_TYPE (op1), op0);
- }
- converted = 1;
- break;
- }
-
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
- {
- if (shorten || common || short_compare)
- result_type = common_type (type0, type1);
-
- /* For certain operations (which identify themselves by shorten != 0)
- if both args were extended from the same smaller type,
- do the arithmetic in that type and then extend.
-
- shorten !=0 and !=1 indicates a bitwise operation.
- For them, this optimization is safe only if
- both args are zero-extended or both are sign-extended.
- Otherwise, we might change the result.
- Eg, (short)-1 | (unsigned short)-1 is (int)-1
- but calculated in (unsigned short) it would be (unsigned short)-1. */
-
- if (shorten)
- {
- int unsigned0, unsigned1;
- tree arg0 = get_narrower (op0, &unsigned0);
- tree arg1 = get_narrower (op1, &unsigned1);
- /* UNS is 1 if the operation to be done is an unsigned one. */
- int uns = TREE_UNSIGNED (result_type);
- tree type;
-
- final_type = result_type;
-
- /* Handle the case that OP0 does not *contain* a conversion
- but it *requires* conversion to FINAL_TYPE. */
-
- if (op0 == arg0 && TREE_TYPE (op0) != final_type)
- unsigned0 = TREE_UNSIGNED (TREE_TYPE (op0));
- if (op1 == arg1 && TREE_TYPE (op1) != final_type)
- unsigned1 = TREE_UNSIGNED (TREE_TYPE (op1));
-
- /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */
-
- /* For bitwise operations, signedness of nominal type
- does not matter. Consider only how operands were extended. */
- if (shorten == -1)
- uns = unsigned0;
-
- /* Note that in all three cases below we refrain from optimizing
- an unsigned operation on sign-extended args.
- That would not be valid. */
-
- /* Both args variable: if both extended in same way
- from same width, do it in that width.
- Do it unsigned if args were zero-extended. */
- if ((TYPE_PRECISION (TREE_TYPE (arg0))
- < TYPE_PRECISION (result_type))
- && (TYPE_PRECISION (TREE_TYPE (arg1))
- == TYPE_PRECISION (TREE_TYPE (arg0)))
- && unsigned0 == unsigned1
- && (unsigned0 || !uns))
- result_type
- = signed_or_unsigned_type (unsigned0,
- common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
- else if (TREE_CODE (arg0) == INTEGER_CST
- && (unsigned1 || !uns)
- && (TYPE_PRECISION (TREE_TYPE (arg1))
- < TYPE_PRECISION (result_type))
- && (type = signed_or_unsigned_type (unsigned1,
- TREE_TYPE (arg1)),
- int_fits_type_p (arg0, type)))
- result_type = type;
- else if (TREE_CODE (arg1) == INTEGER_CST
- && (unsigned0 || !uns)
- && (TYPE_PRECISION (TREE_TYPE (arg0))
- < TYPE_PRECISION (result_type))
- && (type = signed_or_unsigned_type (unsigned0,
- TREE_TYPE (arg0)),
- int_fits_type_p (arg1, type)))
- result_type = type;
- }
-
- /* Shifts can be shortened if shifting right. */
-
- if (short_shift)
- {
- int unsigned_arg;
- tree arg0 = get_narrower (op0, &unsigned_arg);
-
- final_type = result_type;
-
- if (arg0 == op0 && final_type == TREE_TYPE (op0))
- unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0));
-
- if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
- /* If arg is sign-extended and then unsigned-shifted,
- we can simulate this with a signed shift in arg's type
- only if the extended result is at least twice as wide
- as the arg. Otherwise, the shift could use up all the
- ones made by sign-extension and bring in zeros.
- We can't optimize that case at all, but in most machines
- it never happens because available widths are 2**N. */
- && (!TREE_UNSIGNED (final_type)
- || unsigned_arg
- || ((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0))
- <= TYPE_PRECISION (result_type))))
- {
- /* Do an unsigned shift if the operand was zero-extended. */
- result_type
- = signed_or_unsigned_type (unsigned_arg,
- TREE_TYPE (arg0));
- /* Convert value-to-be-shifted to that type. */
- if (TREE_TYPE (op0) != result_type)
- op0 = convert (result_type, op0);
- converted = 1;
- }
- }
-
- /* Comparison operations are shortened too but differently.
- They identify themselves by setting short_compare = 1. */
-
- if (short_compare)
- {
- /* Don't write &op0, etc., because that would prevent op0
- from being kept in a register.
- Instead, make copies of the our local variables and
- pass the copies by reference, then copy them back afterward. */
- tree xop0 = op0, xop1 = op1, xresult_type = result_type;
- enum tree_code xresultcode = resultcode;
- tree val
- = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
- if (val != 0)
- return val;
- op0 = xop0, op1 = xop1, result_type = xresult_type;
- resultcode = xresultcode;
- }
-
- if (short_compare && extra_warnings)
- {
- int unsignedp0, unsignedp1;
- tree primop0 = get_narrower (op0, &unsignedp0);
- tree primop1 = get_narrower (op1, &unsignedp1);
-
- /* Warn if signed and unsigned are being compared in a size larger
- than their original size, as this will always fail. */
-
- if (unsignedp0 != unsignedp1
- && (TYPE_PRECISION (TREE_TYPE (primop0))
- < TYPE_PRECISION (result_type))
- && (TYPE_PRECISION (TREE_TYPE (primop1))
- < TYPE_PRECISION (result_type)))
- warning ("comparison between promoted unsigned and signed");
-
- /* Warn if two unsigned values are being compared in a size
- larger than their original size, and one (and only one) is the
- result of a `~' operator. This comparison will always fail.
-
- Also warn if one operand is a constant, and the constant does not
- have all bits set that are set in the ~ operand when it is
- extended. */
-
- else if (TREE_CODE (primop0) == BIT_NOT_EXPR
- ^ TREE_CODE (primop1) == BIT_NOT_EXPR)
- {
- if (TREE_CODE (primop0) == BIT_NOT_EXPR)
- primop0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
- if (TREE_CODE (primop1) == BIT_NOT_EXPR)
- primop1 = get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
-
- if (TREE_CODE (primop0) == INTEGER_CST
- || TREE_CODE (primop1) == INTEGER_CST)
- {
- tree primop;
- HOST_WIDE_INT constant, mask;
- int unsignedp;
- unsigned bits;
-
- if (TREE_CODE (primop0) == INTEGER_CST)
- {
- primop = primop1;
- unsignedp = unsignedp1;
- constant = TREE_INT_CST_LOW (primop0);
- }
- else
- {
- primop = primop0;
- unsignedp = unsignedp0;
- constant = TREE_INT_CST_LOW (primop1);
- }
-
- bits = TYPE_PRECISION (TREE_TYPE (primop));
- if (bits < TYPE_PRECISION (result_type)
- && bits < HOST_BITS_PER_LONG && unsignedp)
- {
- mask = (~ (HOST_WIDE_INT) 0) << bits;
- if ((mask & constant) != mask)
- warning ("comparison of promoted ~unsigned with constant");
- }
- }
- else if (unsignedp0 && unsignedp1
- && (TYPE_PRECISION (TREE_TYPE (primop0))
- < TYPE_PRECISION (result_type))
- && (TYPE_PRECISION (TREE_TYPE (primop1))
- < TYPE_PRECISION (result_type)))
- warning ("comparison of promoted ~unsigned with unsigned");
- }
- }
- }
-
- /* At this point, RESULT_TYPE must be nonzero to avoid an error message.
- If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
- Then the expression will be built.
- It will be given type FINAL_TYPE if that is nonzero;
- otherwise, it will be given type RESULT_TYPE. */
-
- if (!result_type)
- {
- binary_op_error (error_code);
- return error_mark_node;
- }
-
- if (! converted)
- {
- if (TREE_TYPE (op0) != result_type)
- op0 = convert (result_type, op0);
- if (TREE_TYPE (op1) != result_type)
- op1 = convert (result_type, op1);
- }
-
- {
- register tree result = build (resultcode, result_type, op0, op1);
- register tree folded;
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
- if (final_type != 0)
- return convert (final_type, folded);
- return folded;
- }
-}
-
-/* Return a tree for the sum or difference (RESULTCODE says which)
- of pointer PTROP and integer INTOP. */
-
-static tree
-pointer_int_sum (resultcode, ptrop, intop)
- enum tree_code resultcode;
- register tree ptrop, intop;
-{
- tree size_exp;
-
- register tree result;
- register tree folded = fold (intop);
-
- /* The result is a pointer of the same type that is being added. */
-
- register tree result_type = TREE_TYPE (ptrop);
-
- /* Needed to make OOPS V2R3 work. */
- intop = folded;
- if (TREE_CODE (intop) == INTEGER_CST
- && TREE_INT_CST_LOW (intop) == 0
- && TREE_INT_CST_HIGH (intop) == 0)
- return ptrop;
-
- if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ANSI C++ forbids using pointer of type `void *' in arithmetic");
- size_exp = integer_one_node;
- }
- else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ANSI C++ forbids using pointer to a function in arithmetic");
- size_exp = integer_one_node;
- }
- else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ANSI C++ forbids using pointer to a method in arithmetic");
- size_exp = integer_one_node;
- }
- else if (TREE_CODE (TREE_TYPE (result_type)) == OFFSET_TYPE)
- {
- if (pedantic)
- pedwarn ("ANSI C++ forbids using pointer to a member in arithmetic");
- size_exp = integer_one_node;
- }
- else
- size_exp = size_in_bytes (TREE_TYPE (result_type));
-
- /* If what we are about to multiply by the size of the elements
- contains a constant term, apply distributive law
- and multiply that constant term separately.
- This helps produce common subexpressions. */
-
- if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
- && ! TREE_CONSTANT (intop)
- && TREE_CONSTANT (TREE_OPERAND (intop, 1))
- && TREE_CONSTANT (size_exp))
- {
- enum tree_code subcode = resultcode;
- if (TREE_CODE (intop) == MINUS_EXPR)
- subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
- ptrop = build_binary_op (subcode, ptrop, TREE_OPERAND (intop, 1), 1);
- intop = TREE_OPERAND (intop, 0);
- }
-
- /* Convert the integer argument to a type the same size as a pointer
- so the multiply won't overflow spuriously. */
-
- if (TYPE_PRECISION (TREE_TYPE (intop)) != POINTER_SIZE)
- intop = convert (type_for_size (POINTER_SIZE, 0), intop);
-
- /* Replace the integer argument
- with a suitable product by the object size. */
-
- intop = build_binary_op (MULT_EXPR, intop, size_exp, 1);
-
- /* Create the sum or difference. */
-
- result = build (resultcode, result_type, ptrop, intop);
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (ptrop) & TREE_CONSTANT (intop);
- return folded;
-}
-
-/* Return a tree for the difference of pointers OP0 and OP1.
- The resulting tree has type int. */
-
-static tree
-pointer_diff (op0, op1)
- register tree op0, op1;
-{
- register tree result, folded;
- tree restype = ptrdiff_type_node;
- tree target_type = TREE_TYPE (TREE_TYPE (op0));
-
- if (pedantic)
- {
- if (TREE_CODE (target_type) == VOID_TYPE)
- pedwarn ("ANSI C++ forbids using pointer of type `void *' in subtraction");
- if (TREE_CODE (target_type) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids using pointer to a function in subtraction");
- if (TREE_CODE (target_type) == METHOD_TYPE)
- pedwarn ("ANSI C++ forbids using pointer to a method in subtraction");
- if (TREE_CODE (target_type) == OFFSET_TYPE)
- pedwarn ("ANSI C++ forbids using pointer to a member in subtraction");
- }
-
- /* First do the subtraction as integers;
- then drop through to build the divide operator. */
-
- op0 = build_binary_op (MINUS_EXPR,
- convert (restype, op0), convert (restype, op1), 1);
- op1 = ((TREE_CODE (target_type) == VOID_TYPE
- || TREE_CODE (target_type) == FUNCTION_TYPE
- || TREE_CODE (target_type) == METHOD_TYPE
- || TREE_CODE (target_type) == OFFSET_TYPE)
- ? integer_one_node
- : size_in_bytes (target_type));
-
- /* Do the division. */
-
- result = build (EXACT_DIV_EXPR, restype, op0, op1);
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
- return folded;
-}
-
-/* Handle the case of taking the address of a COMPONENT_REF.
- Called by `build_unary_op' and `build_up_reference'.
-
- ARG is the COMPONENT_REF whose address we want.
- ARGTYPE is the pointer type that this address should have.
- MSG is an error message to print if this COMPONENT_REF is not
- addressable (such as a bitfield). */
-
-tree
-build_component_addr (arg, argtype, msg)
- tree arg, argtype;
- char *msg;
-{
- tree field = TREE_OPERAND (arg, 1);
- tree basetype = decl_type_context (field);
- tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
-
- if (DECL_BIT_FIELD (field))
- {
- error (msg, IDENTIFIER_POINTER (DECL_NAME (field)));
- return error_mark_node;
- }
-
- if (flag_gc)
- warning ("address of `%s::%s' taken", TYPE_NAME_STRING (basetype),
- IDENTIFIER_POINTER (DECL_NAME (field)));
-
- if (TREE_CODE (field) == FIELD_DECL
- && TYPE_USES_COMPLEX_INHERITANCE (basetype))
- /* Can't convert directly to ARGTYPE, since that
- may have the same pointer type as one of our
- baseclasses. */
- rval = build1 (NOP_EXPR, argtype,
- convert_pointer_to (basetype, rval));
- else
- /* This conversion is harmless. */
- rval = convert (argtype, rval);
-
- if (! integer_zerop (DECL_FIELD_BITPOS (field)))
- {
- tree offset = size_binop (EASY_DIV_EXPR, DECL_FIELD_BITPOS (field),
- size_int (BITS_PER_UNIT));
- int flag = TREE_CONSTANT (rval);
- rval = fold (build (PLUS_EXPR, argtype,
- rval, convert (argtype, offset)));
- TREE_CONSTANT (rval) = flag;
- }
- return rval;
-}
-
-/* Construct and perhaps optimize a tree representation
- for a unary operation. CODE, a tree_code, specifies the operation
- and XARG is the operand. */
-
-tree
-build_x_unary_op (code, xarg)
- enum tree_code code;
- tree xarg;
-{
- tree rval;
-
- /* See comments in `build_x_unary_op'. */
- if (rval = build_opfncall (code, 0, xarg, NULL_TREE, NULL_TREE))
- {
- if (rval = build_opfncall (code, LOOKUP_PROTECT, xarg, NULL_TREE, NULL_TREE))
- return rval;
- build_opfncall (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE);
- return error_mark_node;
- }
- return build_unary_op (code, xarg, 0);
-}
-
-/* C++: Must handle pointers to members.
-
- Perhaps type instantiation should be extended to handle conversion
- from aggregates to types we don't yet know we want? (Or are those
- cases typically errors which should be reported?)
-
- NOCONVERT nonzero suppresses the default promotions
- (such as from short to int). */
-tree
-build_unary_op (code, xarg, noconvert)
- enum tree_code code;
- tree xarg;
- int noconvert;
-{
- /* No default_conversion here. It causes trouble for ADDR_EXPR. */
- register tree arg = xarg;
- register tree argtype = 0;
- register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
- char *errstring = NULL;
- tree val;
- int isaggrtype;
-
- if (typecode == ERROR_MARK)
- return error_mark_node;
-
- if (typecode == REFERENCE_TYPE && code != ADDR_EXPR && ! noconvert)
- {
- arg = convert_from_reference (arg);
- typecode = TREE_CODE (TREE_TYPE (arg));
- }
-
- if (typecode == ENUMERAL_TYPE)
- typecode = INTEGER_TYPE;
-
- isaggrtype = IS_AGGR_TYPE_CODE (typecode);
-
- switch (code)
- {
- case CONVERT_EXPR:
- /* This is used for unary plus, because a CONVERT_EXPR
- is enough to prevent anybody from looking inside for
- associativity, but won't generate any code. */
- if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
- errstring = "wrong type argument to unary plus";
- else if (!noconvert)
- arg = default_conversion (arg);
- break;
-
- case NEGATE_EXPR:
- if (isaggrtype)
- {
- if (!noconvert)
- arg = default_conversion (arg);
- else
- {
- error_with_aggr_type (TREE_TYPE (arg), "type conversion for type `%s' not allowed");
- return error_mark_node;
- }
- typecode = TREE_CODE (TREE_TYPE (arg));
- noconvert = 1;
- }
-
- if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
- errstring = "wrong type argument to unary minus";
- else if (!noconvert)
- arg = default_conversion (arg);
- break;
-
- case BIT_NOT_EXPR:
- if (isaggrtype)
- {
- if (!noconvert)
- arg = default_conversion (arg);
- else
- {
- error_with_aggr_type (TREE_TYPE (arg), "type conversion for type `%s' not allowed");
- return error_mark_node;
- }
- typecode = TREE_CODE (TREE_TYPE (arg));
- noconvert = 1;
- }
-
- if (typecode != INTEGER_TYPE)
- errstring = "wrong type argument to bit-complement";
- else if (!noconvert)
- arg = default_conversion (arg);
- break;
-
- case ABS_EXPR:
- if (isaggrtype)
- {
- if (!noconvert)
- arg = default_conversion (arg);
- else
- {
- error_with_aggr_type (TREE_TYPE (arg), "type conversion for type `%s' not allowed");
- return error_mark_node;
- }
- typecode = TREE_CODE (TREE_TYPE (arg));
- noconvert = 1;
- }
-
- if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
- errstring = "wrong type argument to abs";
- else if (!noconvert)
- arg = default_conversion (arg);
- break;
-
- case TRUTH_NOT_EXPR:
- if (isaggrtype)
- {
- arg = truthvalue_conversion (arg);
- typecode = TREE_CODE (TREE_TYPE (arg));
- }
-
- if (typecode != INTEGER_TYPE
- && typecode != REAL_TYPE && typecode != POINTER_TYPE
- /* These will convert to a pointer. */
- && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE)
- {
- errstring = "wrong type argument to unary exclamation mark";
- break;
- }
- arg = truthvalue_conversion (arg);
- val = invert_truthvalue (arg);
- if (val) return val;
- break;
-
- case NOP_EXPR:
- break;
-
- case PREINCREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- /* Handle complex lvalues (when permitted)
- by reduction to simpler cases. */
-
- val = unary_complex_lvalue (code, arg);
- if (val != 0)
- return val;
-
- /* Report invalid types. */
-
- if (isaggrtype)
- {
- arg = default_conversion (arg);
- typecode = TREE_CODE (TREE_TYPE (arg));
- }
-
- if (typecode != POINTER_TYPE
- && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
- {
- if (code == PREINCREMENT_EXPR)
- errstring ="no pre-increment operator for type";
- else if (code == POSTINCREMENT_EXPR)
- errstring ="no post-increment operator for type";
- else if (code == PREDECREMENT_EXPR)
- errstring ="no pre-decrement operator for type";
- else
- errstring ="no post-decrement operator for type";
- break;
- }
-
- /* Report something read-only. */
-
- if (TYPE_READONLY (TREE_TYPE (arg))
- || TREE_READONLY (arg))
- readonly_error (arg, ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement"),
- 0);
-
- {
- register tree inc;
- tree result_type = TREE_TYPE (arg);
-
- arg = get_unwidened (arg, 0);
- argtype = TREE_TYPE (arg);
-
- /* ARM $5.2.5 last annotation says this should be forbidden. */
- if (TREE_CODE (argtype) == ENUMERAL_TYPE)
- pedwarn ("ANSI C++ forbids %sing an enum",
- (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement");
-
- /* Compute the increment. */
-
- if (typecode == POINTER_TYPE)
- {
- enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
- if (tmp == FUNCTION_TYPE || tmp == METHOD_TYPE
- || tmp == VOID_TYPE || tmp == OFFSET_TYPE)
- pedwarn ("ANSI C++ forbids %sing a pointer of type `%s'",
- ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement"),
- type_as_string (argtype));
- inc = c_sizeof_nowarn (TREE_TYPE (argtype));
- }
- else
- inc = integer_one_node;
-
- inc = convert (argtype, inc);
-
- /* Handle incrementing a cast-expression. */
-
- switch (TREE_CODE (arg))
- {
- case NOP_EXPR:
- case CONVERT_EXPR:
- case FLOAT_EXPR:
- case FIX_TRUNC_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_CEIL_EXPR:
- {
- tree incremented, modify, value;
- pedantic_lvalue_warning (CONVERT_EXPR);
- arg = stabilize_reference (arg);
- if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
- value = arg;
- else
- value = save_expr (arg);
- incremented = build (((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? PLUS_EXPR : MINUS_EXPR),
- argtype, value, inc);
- TREE_SIDE_EFFECTS (incremented) = 1;
- modify = build_modify_expr (arg, NOP_EXPR, incremented);
- return build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
- }
- }
-
- if (TREE_CODE (arg) == OFFSET_REF)
- arg = resolve_offset_ref (arg);
-
- /* Complain about anything else that is not a true lvalue. */
- if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement")))
- return error_mark_node;
-
- val = build (code, TREE_TYPE (arg), arg, inc);
- TREE_SIDE_EFFECTS (val) = 1;
- return convert (result_type, val);
- }
-
- case ADDR_EXPR:
- /* Note that this operation never does default_conversion
- regardless of NOCONVERT. */
-
- if (TREE_REFERENCE_EXPR (arg))
- {
- error ("references are not lvalues");
- return error_mark_node;
- }
- else if (typecode == REFERENCE_TYPE)
- {
- arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_REFERENCE_EXPR (arg) = 1;
- return arg;
- }
- else if (TREE_CODE (arg) == FUNCTION_DECL
- && DECL_NAME (arg)
- && DECL_CONTEXT (arg) == NULL_TREE
- && IDENTIFIER_LENGTH (DECL_NAME (arg)) == 4
- && IDENTIFIER_POINTER (DECL_NAME (arg))[0] == 'm'
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (arg)), "main"))
- {
- /* ARM $3.4 */
- error ("attempt to take address of function `main'");
- return error_mark_node;
- }
-
- /* Let &* cancel out to simplify resulting code. */
- if (TREE_CODE (arg) == INDIRECT_REF)
- {
- /* We don't need to have `current_class_decl' wrapped in a
- NON_LVALUE_EXPR node. */
- if (arg == C_C_D)
- return current_class_decl;
-
- /* Keep `default_conversion' from converting if
- ARG is of REFERENCE_TYPE. */
- arg = TREE_OPERAND (arg, 0);
- if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
- {
- if (TREE_CODE (arg) == VAR_DECL && DECL_INITIAL (arg)
- && !TREE_SIDE_EFFECTS (DECL_INITIAL (arg)))
- arg = DECL_INITIAL (arg);
- arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_REFERENCE_EXPR (arg) = 1;
- TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
- }
- else if (lvalue_p (arg))
- /* Don't let this be an lvalue. */
- return non_lvalue (arg);
- return arg;
- }
-
- /* For &x[y], return x+y */
- if (TREE_CODE (arg) == ARRAY_REF)
- {
- if (mark_addressable (TREE_OPERAND (arg, 0)) == 0)
- return error_mark_node;
- return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
- TREE_OPERAND (arg, 1), 1);
- }
-
- /* Uninstantiated types are all functions. Taking the
- address of a function is a no-op, so just return the
- argument. */
-
- if (TREE_CODE (arg) == IDENTIFIER_NODE
- && IDENTIFIER_OPNAME_P (arg))
- {
- my_friendly_abort (117);
- /* We don't know the type yet, so just work around the problem.
- We know that this will resolve to an lvalue. */
- return build1 (ADDR_EXPR, unknown_type_node, arg);
- }
-
- if (TREE_CODE (arg) == TREE_LIST)
- {
- /* Look at methods with only this name. */
- if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL)
- {
- tree targ = TREE_VALUE (arg);
-
- /* If this function is unique, or it is a unique
- constructor, we can takes its address easily. */
- if (DECL_CHAIN (targ) == NULL_TREE
- || (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (targ))
- && DECL_CHAIN (DECL_CHAIN (targ)) == NULL_TREE))
- {
- if (DECL_CHAIN (targ))
- targ = DECL_CHAIN (targ);
- if (DECL_CLASS_CONTEXT (targ))
- targ = build (OFFSET_REF, TREE_TYPE (targ), C_C_D, targ);
-
- val = unary_complex_lvalue (ADDR_EXPR, targ);
- if (val)
- return val;
- }
-
- /* This possible setting of TREE_CONSTANT is what makes it possible
- with an initializer list to emit the entire thing in the data
- section, rather than a run-time initialization. */
- arg = build1 (ADDR_EXPR, unknown_type_node, arg);
- if (staticp (targ))
- TREE_CONSTANT (arg) = 1;
- return arg;
- }
- if (TREE_CHAIN (arg) == NULL_TREE
- && DECL_CHAIN (TREE_VALUE (TREE_VALUE (arg))) == NULL_TREE)
- {
- /* Unique overloaded member function. */
- return build_unary_op (ADDR_EXPR, TREE_VALUE (TREE_VALUE (arg)), 0);
- }
- return build1 (ADDR_EXPR, unknown_type_node, arg);
- }
-
- /* Handle complex lvalues (when permitted)
- by reduction to simpler cases. */
- val = unary_complex_lvalue (code, arg);
- if (val != 0)
- return val;
-
-#if 0 /* Turned off because inconsistent;
- float f; *&(int)f = 3.4 stores in int format
- whereas (int)f = 3.4 stores in float format. */
- /* Address of a cast is just a cast of the address
- of the operand of the cast. */
- switch (TREE_CODE (arg))
- {
- case NOP_EXPR:
- case CONVERT_EXPR:
- case FLOAT_EXPR:
- case FIX_TRUNC_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_CEIL_EXPR:
- if (pedantic)
- pedwarn ("ANSI C++ forbids taking the address of a cast expression");
- return convert (build_pointer_type (TREE_TYPE (arg)),
- build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0));
- }
-#endif
-
- /* Allow the address of a constructor if all the elements
- are constant. */
- if (TREE_CODE (arg) == CONSTRUCTOR && TREE_CONSTANT (arg))
- ;
- /* Anything not already handled and not a true memory reference
- is an error. */
- else if (typecode != FUNCTION_TYPE
- && typecode != METHOD_TYPE
- && !lvalue_or_else (arg, "unary `&'"))
- return error_mark_node;
-
- /* Ordinary case; arg is a COMPONENT_REF or a decl. */
- argtype = TREE_TYPE (arg);
- /* If the lvalue is const or volatile,
- merge that into the type that the address will point to. */
- if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
- || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
- {
- if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
- argtype = build_type_variant (argtype,
- TREE_READONLY (arg),
- TREE_THIS_VOLATILE (arg));
- }
-
- argtype = build_pointer_type (argtype);
-
- if (mark_addressable (arg) == 0)
- return error_mark_node;
-
- {
- tree addr;
-
- if (TREE_CODE (arg) == COMPONENT_REF)
- addr = build_component_addr (arg, argtype,
- "attempt to take address of bit-field structure member `%s'");
- else
- addr = build1 (code, argtype, arg);
-
- /* Address of a static or external variable or
- function counts as a constant */
- if (staticp (arg))
- TREE_CONSTANT (addr) = 1;
- return addr;
- }
- }
-
- if (!errstring)
- {
- if (argtype == 0)
- argtype = TREE_TYPE (arg);
- return fold (build1 (code, argtype, arg));
- }
-
- error (errstring);
- return error_mark_node;
-}
-
-/* If CONVERSIONS is a conversion expression or a nested sequence of such,
- convert ARG with the same conversions in the same order
- and return the result. */
-
-static tree
-convert_sequence (conversions, arg)
- tree conversions;
- tree arg;
-{
- switch (TREE_CODE (conversions))
- {
- case NOP_EXPR:
- case CONVERT_EXPR:
- case FLOAT_EXPR:
- case FIX_TRUNC_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_CEIL_EXPR:
- return convert (TREE_TYPE (conversions),
- convert_sequence (TREE_OPERAND (conversions, 0),
- arg));
-
- default:
- return arg;
- }
-}
-
-/* Apply unary lvalue-demanding operator CODE to the expression ARG
- for certain kinds of expressions which are not really lvalues
- but which we can accept as lvalues.
-
- If ARG is not a kind of expression we can handle, return zero. */
-
-tree
-unary_complex_lvalue (code, arg)
- enum tree_code code;
- tree arg;
-{
- /* Handle (a, b) used as an "lvalue". */
- if (TREE_CODE (arg) == COMPOUND_EXPR)
- {
- tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0);
- pedantic_lvalue_warning (COMPOUND_EXPR);
- return build (COMPOUND_EXPR, TREE_TYPE (real_result),
- TREE_OPERAND (arg, 0), real_result);
- }
-
- /* Handle (a ? b : c) used as an "lvalue". */
- if (TREE_CODE (arg) == COND_EXPR)
- {
- pedantic_lvalue_warning (COND_EXPR);
- return (build_conditional_expr
- (TREE_OPERAND (arg, 0),
- build_unary_op (code, TREE_OPERAND (arg, 1), 0),
- build_unary_op (code, TREE_OPERAND (arg, 2), 0)));
- }
-
- if (code != ADDR_EXPR)
- return 0;
-
- /* Handle (a = b) used as an "lvalue" for `&'. */
- if (TREE_CODE (arg) == MODIFY_EXPR
- || TREE_CODE (arg) == INIT_EXPR)
- {
- tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
- return build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
- }
-
- if (TREE_CODE (arg) == WITH_CLEANUP_EXPR)
- {
- tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
- real_result = build (WITH_CLEANUP_EXPR, TREE_TYPE (real_result),
- real_result, 0, TREE_OPERAND (arg, 2));
- return real_result;
- }
-
- if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE
- || TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
- {
- /* The representation of something of type OFFSET_TYPE
- is really the representation of a pointer to it.
- Here give the representation its true type. */
- tree t;
- tree offset;
-
- my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313);
-
- if (TREE_CODE (arg) != OFFSET_REF)
- return 0;
-
- t = TREE_OPERAND (arg, 1);
-
- if (TREE_CODE (t) == FUNCTION_DECL)
- {
- tree context = NULL_TREE;
-
- if (DECL_VINDEX (t)
- || (flag_all_virtual == 1
- && ((context = decl_type_context (t))
- && TYPE_OVERLOADS_METHOD_CALL_EXPR (context)
- && ! DECL_CONSTRUCTOR_P (t))))
- {
- offset = copy_node (DECL_VINDEX (t));
- TREE_TYPE (offset) = build_pointer_type (TREE_TYPE (arg));
- }
- else
- offset = build_unary_op (ADDR_EXPR, t, 0);
-
- return offset;
- }
- if (TREE_CODE (t) == VAR_DECL)
- return build_unary_op (ADDR_EXPR, t, 0);
- else
- {
- /* Can't build a pointer to member if the member must
- go through virtual base classes. */
- if (virtual_member (DECL_FIELD_CONTEXT (t),
- CLASSTYPE_VBASECLASSES (TREE_TYPE (TREE_OPERAND (arg, 0)))))
- {
- sorry ("pointer to member via virtual baseclass");
- return error_mark_node;
- }
-
- if (TREE_OPERAND (arg, 0)
- && (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
- || TREE_OPERAND (TREE_OPERAND (arg, 0), 0) != error_mark_node))
- {
- /* Don't know if this should return address to just
- _DECL, or actual address resolved in this expression. */
- sorry ("address of bound pointer-to-member expression");
- return error_mark_node;
- }
-
- return convert (build_pointer_type (TREE_TYPE (arg)),
- size_binop (EASY_DIV_EXPR,
- DECL_FIELD_BITPOS (t),
- size_int (BITS_PER_UNIT)));
- }
- }
-
- if (TREE_CODE (arg) == OFFSET_REF)
- {
- tree left = TREE_OPERAND (arg, 0), left_addr;
- tree right_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 1), 0);
-
- if (left == 0)
- if (current_class_decl)
- left_addr = current_class_decl;
- else
- {
- error ("no `this' for pointer to member");
- return error_mark_node;
- }
- else
- left_addr = build_unary_op (ADDR_EXPR, left, 0);
-
- return build (PLUS_EXPR, build_pointer_type (TREE_TYPE (arg)),
- build1 (NOP_EXPR, integer_type_node, left_addr),
- build1 (NOP_EXPR, integer_type_node, right_addr));
- }
-
- /* We permit compiler to make function calls returning
- objects of aggregate type look like lvalues. */
- {
- tree targ = arg;
-
- if (TREE_CODE (targ) == SAVE_EXPR)
- targ = TREE_OPERAND (targ, 0);
-
- if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (TREE_TYPE (targ)))
- {
- if (TREE_CODE (arg) == SAVE_EXPR)
- targ = arg;
- else
- targ = build_cplus_new (TREE_TYPE (arg), arg, 1);
- return build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (arg)), targ);
- }
-
- if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF)
- return build (SAVE_EXPR, TYPE_POINTER_TO (TREE_TYPE (arg)),
- TREE_OPERAND (targ, 0), current_function_decl, NULL);
-
- /* We shouldn't wrap WITH_CLEANUP_EXPRs inside of SAVE_EXPRs, but in case
- we do, here's how to handle it. */
- if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == WITH_CLEANUP_EXPR)
- {
-#if 0
- /* Not really a bug, but something to turn on when testing. */
- compiler_error ("WITH_CLEANUP_EXPR wrapped in SAVE_EXPR");
-#endif
- return unary_complex_lvalue (ADDR_EXPR, targ);
- }
- }
-
- /* Don't let anything else be handled specially. */
- return 0;
-}
-
-/* If pedantic, warn about improper lvalue. CODE is either COND_EXPR
- COMPOUND_EXPR, or CONVERT_EXPR (for casts). */
-
-static void
-pedantic_lvalue_warning (code)
- enum tree_code code;
-{
- if (pedantic)
- pedwarn ("ANSI C++ forbids use of %s expressions as lvalues",
- code == COND_EXPR ? "conditional"
- : code == COMPOUND_EXPR ? "compound" : "cast");
-}
-
-/* Mark EXP saying that we need to be able to take the
- address of it; it should not be allocated in a register.
- Value is 1 if successful.
-
- C++: we do not allow `current_class_decl' to be addressable. */
-
-int
-mark_addressable (exp)
- tree exp;
-{
- register tree x = exp;
-
- if (TREE_ADDRESSABLE (x) == 1)
- return 1;
-
- while (1)
- switch (TREE_CODE (x))
- {
- case ADDR_EXPR:
- case COMPONENT_REF:
- case ARRAY_REF:
- x = TREE_OPERAND (x, 0);
- break;
-
- case PARM_DECL:
- if (x == current_class_decl)
- {
- error ("address of `this' not available");
- TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
- put_var_into_stack (x);
- return 1;
- }
- case VAR_DECL:
- if (TREE_STATIC (x)
- && TREE_READONLY (x)
- && DECL_RTL (x) != 0
- && ! decl_in_memory_p (x))
- {
- /* We thought this would make a good constant variable,
- but we were wrong. */
- push_obstacks_nochange ();
- end_temporary_allocation ();
-
- TREE_ASM_WRITTEN (x) = 0;
- DECL_RTL (x) = 0;
- rest_of_decl_compilation (x, 0, IDENTIFIER_LOCAL_VALUE (x) == 0, 0);
- TREE_ADDRESSABLE (x) = 1;
-
- pop_obstacks ();
-
- return 1;
- }
- /* Caller should not be trying to mark initialized
- constant fields addressable. */
- my_friendly_assert (DECL_LANG_SPECIFIC (x) == 0
- || DECL_IN_AGGR_P (x) == 0
- || TREE_STATIC (x)
- || DECL_EXTERNAL (x), 314);
-
- case CONST_DECL:
- if (DECL_REGISTER (x))
- {
- if (TREE_PUBLIC (x))
- {
- error ("address of global register variable `%s' requested",
- IDENTIFIER_POINTER (DECL_NAME (x)));
- return 0;
- }
- warning ("address requested for `%s', which is declared `register'",
- IDENTIFIER_POINTER (DECL_NAME (x)));
- }
- put_var_into_stack (x);
- TREE_ADDRESSABLE (x) = 1;
- return 1;
-
- case RESULT_DECL:
- put_var_into_stack (x);
- TREE_ADDRESSABLE (x) = 1;
- return 1;
-
- case FUNCTION_DECL:
- /* We have to test both conditions here. The first may
- be non-zero in the case of processing a default function.
- The second may be non-zero in the case of a template function. */
- x = DECL_MAIN_VARIANT (x);
- if ((DECL_INLINE (x) || DECL_PENDING_INLINE_INFO (x))
- && (DECL_CONTEXT (x) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't'
- || ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x))))
- {
- mark_inline_for_output (x);
- if (x == current_function_decl)
- DECL_EXTERNAL (x) = 0;
- }
- TREE_ADDRESSABLE (x) = 1;
- TREE_USED (x) = 1;
- TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
- return 1;
-
- default:
- return 1;
- }
-}
-
-/* Build and return a conditional expression IFEXP ? OP1 : OP2. */
-
-tree
-build_x_conditional_expr (ifexp, op1, op2)
- tree ifexp, op1, op2;
-{
- tree rval;
-
- /* See comments in `build_x_binary_op'. */
- if (op1 != 0 && (rval = build_opfncall (COND_EXPR, 0, ifexp, op1, op2)))
- {
- if (rval = build_opfncall (COND_EXPR, LOOKUP_PROTECT, ifexp, op1, op2))
- return rval;
- build_opfncall (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
- return error_mark_node;
- }
- return build_conditional_expr (ifexp, op1, op2);
-}
-
-tree
-build_conditional_expr (ifexp, op1, op2)
- tree ifexp, op1, op2;
-{
- register tree type1;
- register tree type2;
- register enum tree_code code1;
- register enum tree_code code2;
- register tree result_type = NULL_TREE;
-
- /* If second operand is omitted, it is the same as the first one;
- make sure it is calculated only once. */
- if (op1 == 0)
- {
- if (pedantic)
- pedwarn ("ANSI C++ forbids omitting the middle term of a ?: expression");
- ifexp = op1 = save_expr (ifexp);
- }
-
- ifexp = truthvalue_conversion (default_conversion (ifexp));
-
- if (TREE_CODE (ifexp) == ERROR_MARK)
- return error_mark_node;
-
- op1 = require_instantiated_type (TREE_TYPE (op2), op1, error_mark_node);
- if (op1 == error_mark_node)
- return error_mark_node;
- op2 = require_instantiated_type (TREE_TYPE (op1), op2, error_mark_node);
- if (op2 == error_mark_node)
- return error_mark_node;
-
- /* C++: REFERENCE_TYPES must be dereferenced. */
- type1 = TREE_TYPE (op1);
- code1 = TREE_CODE (type1);
- type2 = TREE_TYPE (op2);
- code2 = TREE_CODE (type2);
-
- if (code1 == REFERENCE_TYPE)
- {
- op1 = convert_from_reference (op1);
- type1 = TREE_TYPE (op1);
- code1 = TREE_CODE (type1);
- }
- if (code2 == REFERENCE_TYPE)
- {
- op2 = convert_from_reference (op2);
- type2 = TREE_TYPE (op2);
- code2 = TREE_CODE (type2);
- }
-
-#if 1 /* Produces wrong result if within sizeof. Sorry. */
- /* Don't promote the operands separately if they promote
- the same way. Return the unpromoted type and let the combined
- value get promoted if necessary. */
-
- if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)
- && code2 != ARRAY_TYPE
-#if 0
- /* For C++, let the enumeral type come through. */
- && code2 != ENUMERAL_TYPE
-#endif
- && code2 != FUNCTION_TYPE
- && code2 != METHOD_TYPE)
- {
- tree result;
-
- if (TREE_CONSTANT (ifexp)
- && (TREE_CODE (ifexp) == INTEGER_CST
- || TREE_CODE (ifexp) == ADDR_EXPR))
- return (integer_zerop (ifexp) ? op2 : op1);
-
- if (TREE_CODE (op1) == CONST_DECL)
- op1 = DECL_INITIAL (op1);
- else if (TREE_READONLY_DECL_P (op1))
- op1 = decl_constant_value (op1);
- if (TREE_CODE (op2) == CONST_DECL)
- op2 = DECL_INITIAL (op2);
- else if (TREE_READONLY_DECL_P (op2))
- op2 = decl_constant_value (op2);
- if (type1 != type2)
- type1 = build_type_variant
- (type1,
- TREE_READONLY (op1) || TREE_READONLY (op2),
- TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
- /* ??? This is a kludge to deal with the fact that
- we don't sort out integers and enums properly, yet. */
- result = fold (build (COND_EXPR, type1, ifexp, op1, op2));
- if (TREE_TYPE (result) != type1)
- result = build1 (NOP_EXPR, type1, result);
- return result;
- }
-#endif
-
- /* They don't match; promote them both and then try to reconcile them.
- But don't permit mismatching enum types. */
- if (code1 == ENUMERAL_TYPE)
- {
- if (code2 == ENUMERAL_TYPE)
- {
- message_2_types (error, "enumeral mismatch in conditional expression: `%s' vs `%s'", type1, type2);
- return error_mark_node;
- }
- else if (extra_warnings && ! IS_AGGR_TYPE_CODE (code2))
- warning ("enumeral and non-enumeral type in conditional expression");
- }
- else if (extra_warnings
- && code2 == ENUMERAL_TYPE && ! IS_AGGR_TYPE_CODE (code1))
- warning ("enumeral and non-enumeral type in conditional expression");
-
- if (code1 != VOID_TYPE)
- {
- op1 = default_conversion (op1);
- type1 = TREE_TYPE (op1);
- code1 = TREE_CODE (type1);
- }
- if (code2 != VOID_TYPE)
- {
- op2 = default_conversion (op2);
- type2 = TREE_TYPE (op2);
- code2 = TREE_CODE (type2);
- }
-
- /* Quickly detect the usual case where op1 and op2 have the same type
- after promotion. */
- if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
- {
- if (type1 == type2)
- result_type = type1;
- else
- result_type = build_type_variant
- (type1,
- TREE_READONLY (op1) || TREE_READONLY (op2),
- TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
- }
- else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE)
- && (code2 == INTEGER_TYPE || code2 == REAL_TYPE))
- {
- result_type = common_type (type1, type2);
- }
- else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
- {
- if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE))
- pedwarn ("ANSI C++ forbids conditional expr with only one void side");
- result_type = void_type_node;
- }
- else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
- {
- if (comp_target_types (type1, type2, 1))
- result_type = common_type (type1, type2);
- else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node)
- result_type = qualify_type (type2, type1);
- else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node)
- result_type = qualify_type (type1, type2);
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node)
- {
- if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids conditional expr between `void *' and function pointer");
- result_type = qualify_type (type1, type2);
- }
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (type2)) == void_type_node)
- {
- if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids conditional expr between `void *' and function pointer");
- result_type = qualify_type (type2, type1);
- }
- /* C++ */
- else if (comptypes (type2, type1, 0))
- result_type = type2;
- else if (IS_AGGR_TYPE (TREE_TYPE (type1))
- && IS_AGGR_TYPE (TREE_TYPE (type2))
- && (result_type = common_base_type (TREE_TYPE (type1), TREE_TYPE (type2))))
- {
- if (result_type == error_mark_node)
- {
- message_2_types (error, "common base type of types `%s' and `%s' is ambiguous",
- TREE_TYPE (type1), TREE_TYPE (type2));
- result_type = ptr_type_node;
- }
- else result_type = TYPE_POINTER_TO (result_type);
- }
- else
- {
- warning ("pointer type mismatch in conditional expression");
- result_type = ptr_type_node;
- }
- }
- else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
- {
- if (!integer_zerop (op2))
- warning ("pointer/integer type mismatch in conditional expression");
- else
- {
- op2 = null_pointer_node;
- if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
- }
- result_type = type1;
- }
- else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
- {
- if (!integer_zerop (op1))
- warning ("pointer/integer type mismatch in conditional expression");
- else
- {
- op1 = null_pointer_node;
- if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
- }
- result_type = type2;
- op1 = null_pointer_node;
- }
-
- if (!result_type)
- {
- /* The match does not look good. If either is
- an aggregate value, try converting to a scalar type. */
- if (code1 == RECORD_TYPE && code2 == RECORD_TYPE)
- {
- message_2_types (error, "aggregate mismatch in conditional expression: `%s' vs `%s'", type1, type2);
- return error_mark_node;
- }
- if (code1 == RECORD_TYPE && TYPE_HAS_CONVERSION (type1))
- {
- tree tmp = build_type_conversion (CONVERT_EXPR, type2, op1, 0);
- if (tmp == NULL_TREE)
- {
- error_with_aggr_type (type1, "aggregate type `%s' could not convert on lhs of `:'");
- return error_mark_node;
- }
- if (tmp == error_mark_node)
- error ("ambiguous pointer conversion");
- result_type = type2;
- op1 = tmp;
- }
- else if (code2 == RECORD_TYPE && TYPE_HAS_CONVERSION (type2))
- {
- tree tmp = build_type_conversion (CONVERT_EXPR, type1, op2, 0);
- if (tmp == NULL_TREE)
- {
- error_with_aggr_type (type2, "aggregate type `%s' could not convert on rhs of `:'");
- return error_mark_node;
- }
- if (tmp == error_mark_node)
- error ("ambiguous pointer conversion");
- result_type = type1;
- op2 = tmp;
- }
- else if (flag_cond_mismatch)
- result_type = void_type_node;
- else
- {
- error ("type mismatch in conditional expression");
- return error_mark_node;
- }
- }
-
- if (result_type != TREE_TYPE (op1))
- op1 = convert (result_type, op1);
- if (result_type != TREE_TYPE (op2))
- op2 = convert (result_type, op2);
-
-#if 0
- /* XXX delete me, I've been here for years. */
- if (IS_AGGR_TYPE_CODE (code1))
- {
- result_type = TREE_TYPE (op1);
- if (TREE_CONSTANT (ifexp))
- return (integer_zerop (ifexp) ? op2 : op1);
-
- if (TYPE_MODE (result_type) == BLKmode)
- {
- register tree tempvar
- = build_decl (VAR_DECL, NULL_TREE, result_type);
- register tree xop1 = build_modify_expr (tempvar, NOP_EXPR, op1);
- register tree xop2 = build_modify_expr (tempvar, NOP_EXPR, op2);
- register tree result = fold (build (COND_EXPR, result_type,
- ifexp, xop1, xop2));
-
- layout_decl (tempvar, 0);
- /* No way to handle variable-sized objects here.
- I fear that the entire handling of BLKmode conditional exprs
- needs to be redone. */
- my_friendly_assert (TREE_CONSTANT (DECL_SIZE (tempvar)), 315);
- DECL_RTL (tempvar)
- = assign_stack_local (DECL_MODE (tempvar),
- (TREE_INT_CST_LOW (DECL_SIZE (tempvar))
- + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT,
- 0);
-
- TREE_SIDE_EFFECTS (result)
- = TREE_SIDE_EFFECTS (ifexp) | TREE_SIDE_EFFECTS (op1)
- | TREE_SIDE_EFFECTS (op2);
- return build (COMPOUND_EXPR, result_type, result, tempvar);
- }
- }
-#endif /* 0 */
-
- if (TREE_CONSTANT (ifexp))
- return (integer_zerop (ifexp) ? op2 : op1);
-
- return fold (build (COND_EXPR, result_type, ifexp, op1, op2));
-}
-
-/* Handle overloading of the ',' operator when needed. Otherwise,
- this function just builds an expression list. */
-tree
-build_x_compound_expr (list)
- tree list;
-{
- tree rest = TREE_CHAIN (list);
- tree result;
-
- if (rest == NULL_TREE)
- return build_compound_expr (list);
-
- result = build_opfncall (COMPOUND_EXPR, LOOKUP_NORMAL,
- TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
- if (result)
- return build_x_compound_expr (tree_cons (NULL_TREE, result, TREE_CHAIN (rest)));
- else
- return build_compound_expr (tree_cons (NULL_TREE, TREE_VALUE (list),
- build_tree_list (NULL_TREE, build_x_compound_expr (rest))));
-}
-
-/* Given a list of expressions, return a compound expression
- that performs them all and returns the value of the last of them. */
-
-tree
-build_compound_expr (list)
- tree list;
-{
- register tree rest;
-
- if (TREE_READONLY_DECL_P (TREE_VALUE (list)))
- TREE_VALUE (list) = decl_constant_value (TREE_VALUE (list));
-
- if (TREE_CHAIN (list) == 0)
- {
- /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
- Strip such NOP_EXPRs, since LIST is used in non-lvalue context. */
- if (TREE_CODE (list) == NOP_EXPR
- && TREE_TYPE (list) == TREE_TYPE (TREE_OPERAND (list, 0)))
- list = TREE_OPERAND (list, 0);
-
- /* Convert arrays to pointers. */
- if (TREE_CODE (TREE_TYPE (TREE_VALUE (list))) == ARRAY_TYPE)
- return default_conversion (TREE_VALUE (list));
- else
- return TREE_VALUE (list);
- }
-
- rest = build_compound_expr (TREE_CHAIN (list));
-
- if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
- return rest;
-
- return build (COMPOUND_EXPR, TREE_TYPE (rest),
- break_out_cleanups (TREE_VALUE (list)), rest);
-}
-
-/* Build an expression representing a cast to type TYPE of expression EXPR. */
-
-tree
-build_c_cast (type, expr)
- register tree type;
- tree expr;
-{
- register tree value = expr;
-
- if (type == error_mark_node || expr == error_mark_node)
- return error_mark_node;
-
- /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
- Strip such NOP_EXPRs, since VALUE is being used in non-lvalue context. */
- if (TREE_CODE (value) == NOP_EXPR
- && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
- value = TREE_OPERAND (value, 0);
-
- if (TREE_TYPE (expr)
- && TREE_CODE (TREE_TYPE (expr)) == OFFSET_TYPE
- && TREE_CODE (type) != OFFSET_TYPE)
- value = resolve_offset_ref (value);
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- /* Allow casting from T1* to T2[] because Cfront allows it.
- NIHCL uses it. It is not valid ANSI C however, and hence, not
- valid ANSI C++. */
- if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
- {
- if (pedantic)
- pedwarn ("ANSI C++ forbids casting to an array type");
- type = build_pointer_type (TREE_TYPE (type));
- }
- else
- {
- error ("ANSI C++ forbids casting to an array type");
- return error_mark_node;
- }
- }
-
- /* When converting into a reference type, just convert into a pointer
- to the new type and deference it. While this is not exactly what ARM 5.4
- calls for, it is pretty close for now. (int &)ri ---> *(int*)&ri */
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- value = build_unary_op (ADDR_EXPR, value, 0);
- if (value != error_mark_node)
- value = convert (build_pointer_type (TREE_TYPE (type)), value);
- if (value != error_mark_node)
- value = build_indirect_ref (value, "reference conversion");
- return value;
- }
-
- if (TREE_TYPE (value)
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
- {
- /* For C++, we must copy the constness of TYPE into VALUE. */
- if (TREE_READONLY (value) != TYPE_READONLY (type))
- {
- value = copy_node (value);
- TREE_READONLY (value) = TYPE_READONLY (type);
- }
- else if (pedantic)
- {
- if (TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE)
- pedwarn ("ANSI C++ forbids casting nonscalar to the same type");
- }
- return value;
- }
-
- /* If there's only one function in the overloaded space,
- just take it. */
- if (TREE_CODE (value) == TREE_LIST
- && TREE_CHAIN (value) == NULL_TREE)
- value = TREE_VALUE (value);
-
- /* Make up for the fact that we do not always perform
- `default_conversion' anymore. */
- if (TREE_READONLY_DECL_P (value))
- value = decl_constant_value (value);
-
- if (TREE_TYPE (value) == NULL_TREE
- || type_unknown_p (value))
- {
- value = instantiate_type (type, value, 1);
- /* Did we lose? */
- if (value == error_mark_node)
- return error_mark_node;
- }
- else
- {
- tree otype;
- /* Convert functions and arrays to pointers and
- convert references to their expanded types,
- but don't convert any other types. */
- if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
- value = default_conversion (value);
- otype = TREE_TYPE (value);
-
- /* Optionally warn about potentially worrisome casts. */
-
- if (warn_cast_qual
- && TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (otype) == POINTER_TYPE)
- {
- /* For C++ we make these regular warnings, rather than
- softening them into pedwarns. */
- if (TYPE_VOLATILE (TREE_TYPE (otype))
- && ! TYPE_VOLATILE (TREE_TYPE (type)))
- warning ("cast discards `volatile' from pointer target type");
- if (TYPE_READONLY (TREE_TYPE (otype))
- && ! TYPE_READONLY (TREE_TYPE (type)))
- warning ("cast discards `const' from pointer target type");
- }
-
- /* Warn about possible alignment problems. */
- if (STRICT_ALIGNMENT && warn_cast_align
- && TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (otype) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
- && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
- && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
- warning ("cast increases required alignment of target type");
-
-#if 0
- if (TREE_CODE (type) == INTEGER_TYPE
- && TREE_CODE (otype) == POINTER_TYPE
- && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
- warning ("cast from pointer to integer of different size");
-
- if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (otype) == INTEGER_TYPE
- && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
- /* Don't warn about converting 0 to pointer,
- provided the 0 was explicit--not cast or made by folding. */
- && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value)))
- warning ("cast to pointer from integer of different size");
-#endif
-
- value = convert_force (type, value);
- }
- if (value == expr)
- /* Always produce some operator for an explicit cast,
- so we can tell (for -pedantic) that the cast is no lvalue. */
- {
- tree nvalue = build1 (NOP_EXPR, type, value);
- TREE_CONSTANT (nvalue) = TREE_CONSTANT (value);
- return nvalue;
- }
-
- return value;
-}
-
-/* Build an assignment expression of lvalue LHS from value RHS.
-
- In C++, if the left hand side of the assignment is a REFERENCE_TYPE,
- that reference becomes deferenced down to it base type. */
-
-/* Return a reference to the BASE_INDEX part of EXPR. TYPE is
- the type to which BASE_INDEX applies. */
-static tree
-get_base_ref (type, base_index, expr)
- tree type;
- int base_index;
- tree expr;
-{
- tree binfos = TYPE_BINFO_BASETYPES (type);
- tree base_binfo = TREE_VEC_ELT (binfos, base_index);
- tree ref;
-
- if (TREE_CODE (expr) == ARRAY_REF
- || ! BINFO_OFFSET_ZEROP (base_binfo)
- || TREE_VIA_VIRTUAL (base_binfo)
- || TYPE_MODE (type) != TYPE_MODE (BINFO_TYPE (base_binfo)))
- {
- tree addr = build_unary_op (ADDR_EXPR, expr, 0);
- ref = build_indirect_ref (convert_pointer_to (base_binfo, addr),
- NULL_PTR);
- }
- else
- {
- ref = copy_node (expr);
- TREE_TYPE (ref) = BINFO_TYPE (base_binfo);
- }
- return ref;
-}
-
-/* Build an assignment expression of lvalue LHS from value RHS.
- MODIFYCODE is the code for a binary operator that we use
- to combine the old value of LHS with RHS to get the new value.
- Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
-
- C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed.
-
- `build_modify_expr_1' implements recursive part of memberwise
- assignment operation. */
-static tree
-build_modify_expr_1 (lhs, modifycode, rhs, basetype_path)
- tree lhs, rhs;
- enum tree_code modifycode;
- tree basetype_path;
-{
- register tree result;
- tree newrhs = rhs;
- tree lhstype = TREE_TYPE (lhs);
- tree olhstype = lhstype;
-
- /* Avoid duplicate error messages from operands that had errors. */
- if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
- return error_mark_node;
-
- /* If a binary op has been requested, combine the old LHS value with the RHS
- producing the value we should actually store into the LHS. */
-
- if (modifycode == INIT_EXPR)
- ;
- else if (modifycode == NOP_EXPR)
- {
- /* must deal with overloading of `operator=' here. */
- if (TREE_CODE (lhstype) == REFERENCE_TYPE)
- lhstype = TREE_TYPE (lhstype);
- else
- lhstype = olhstype;
- }
- else
- {
- lhs = stabilize_reference (lhs);
- newrhs = build_binary_op (modifycode, lhs, rhs, 1);
- modifycode = NOP_EXPR;
- }
-
- /* If storing into a structure or union member,
- it has probably been given type `int'.
- Compute the type that would go with
- the actual amount of storage the member occupies. */
-
- if (TREE_CODE (lhs) == COMPONENT_REF
- && (TREE_CODE (lhstype) == INTEGER_TYPE
- || TREE_CODE (lhstype) == REAL_TYPE
- || TREE_CODE (lhstype) == ENUMERAL_TYPE))
- lhstype = TREE_TYPE (get_unwidened (lhs, 0));
-
- /* C++: The semantics of C++ differ from those of C when an
- assignment of an aggregate is desired. Assignment in C++ is
- now defined as memberwise assignment of non-static members
- and base class objects. This rule applies recursively
- until a member of a built-in type is found.
-
- Also, we cannot do a bit-wise copy of aggregates which
- contain virtual function table pointers. Those
- pointer values must be preserved through the copy.
- However, this is handled in expand_expr, and not here.
- This is because much better code can be generated at
- that stage than this one. */
- if (TREE_CODE (lhstype) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (lhstype)
- && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
- {
- register tree elt;
- int i;
-
- /* Perform operation on object. */
- if (modifycode == INIT_EXPR && TYPE_HAS_INIT_REF (lhstype))
- {
- result = build_method_call (lhs, constructor_name (lhstype),
- build_tree_list (NULL_TREE, rhs),
- basetype_path, LOOKUP_NORMAL);
- return build_indirect_ref (result, NULL_PTR);
- }
- else if (modifycode == NOP_EXPR)
- {
- /* `operator=' is not an inheritable operator. */
- if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_HAS_ASSIGNMENT (lhstype))
- {
- result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
- if (result == NULL_TREE)
- return error_mark_node;
- return result;
- }
- }
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (lhstype)
- || (modifycode == NOP_EXPR && TYPE_GETS_ASSIGNMENT (lhstype))
- || (modifycode == INIT_EXPR && TYPE_GETS_INIT_REF (lhstype)))
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (lhstype));
- result = NULL_TREE;
-
- if (binfos != NULL_TREE)
- /* Perform operation on each member, depth-first, left-right. */
- for (i = 0; i <= TREE_VEC_LENGTH (binfos)-1; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree base_lhs, base_rhs;
- tree new_result;
-
- /* Assignments from virtual baseclasses handled elsewhere. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- base_lhs = get_base_ref (lhstype, i, lhs);
- base_rhs = get_base_ref (lhstype, i, newrhs);
-
- BINFO_INHERITANCE_CHAIN (base_binfo) = basetype_path;
- new_result
- = build_modify_expr_1 (base_lhs, modifycode, base_rhs,
- base_binfo);
-
- /* We either get back a compound stmt, or a simple one. */
- if (new_result && TREE_CODE (new_result) == TREE_LIST)
- new_result = build_compound_expr (new_result);
- result = tree_cons (NULL_TREE, new_result, result);
- }
-
- for (elt = TYPE_FIELDS (lhstype); elt; elt = TREE_CHAIN (elt))
- {
- tree vbases = NULL_TREE;
- tree elt_lhs, elt_rhs;
-
- if (TREE_CODE (elt) != FIELD_DECL)
- continue;
- if (DECL_NAME (elt)
- && (VFIELD_NAME_P (DECL_NAME (elt))
- || VBASE_NAME_P (DECL_NAME (elt))))
- continue;
-
- if (IS_AGGR_TYPE (TREE_TYPE (elt))
- && TYPE_LANG_SPECIFIC (TREE_TYPE (elt)))
- vbases = CLASSTYPE_VBASECLASSES (TREE_TYPE (elt));
-
- elt_lhs = build (COMPONENT_REF, TREE_TYPE (elt), lhs, elt);
- elt_rhs = build (COMPONENT_REF, TREE_TYPE (elt), newrhs, elt);
- /* It is not always safe to go through `build_modify_expr_1'
- when performing element-wise copying. This is because
- an element may be of ARRAY_TYPE, which will not
- be properly copied as a naked element. */
- if (TREE_CODE (TREE_TYPE (elt)) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (TREE_TYPE (elt)))
- basetype_path = TYPE_BINFO (TREE_TYPE (elt));
-
- while (vbases)
- {
- tree elt_lhs_addr = build_unary_op (ADDR_EXPR, elt_lhs, 0);
- tree elt_rhs_addr = build_unary_op (ADDR_EXPR, elt_rhs, 0);
-
- elt_lhs_addr = convert_pointer_to (vbases, elt_lhs_addr);
- elt_rhs_addr = convert_pointer_to (vbases, elt_rhs_addr);
- result
- = tree_cons (NULL_TREE,
- build_modify_expr_1
- (build_indirect_ref (elt_lhs_addr, NULL_PTR),
- modifycode,
- build_indirect_ref (elt_rhs_addr, NULL_PTR),
- basetype_path),
- result);
- if (TREE_VALUE (result) == error_mark_node)
- return error_mark_node;
- vbases = TREE_CHAIN (vbases);
- }
- elt_lhs = build_modify_expr_1 (elt_lhs, modifycode, elt_rhs,
- basetype_path);
- result = tree_cons (NULL_TREE, elt_lhs, result);
- }
-
- if (result)
- return build_compound_expr (result);
- /* No fields to move. */
- return integer_zero_node;
- }
- else
- {
- result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
- void_type_node, lhs, rhs);
- TREE_SIDE_EFFECTS (result) = 1;
- return result;
- }
- }
-
- result = build_modify_expr (lhs, modifycode, newrhs);
- /* ARRAY_TYPEs cannot be converted to anything meaningful,
- and leaving it there screws up `build_compound_expr' when
- it tries to defaultly convert everything. */
- if (TREE_CODE (TREE_TYPE (result)) == ARRAY_TYPE)
- TREE_TYPE (result) = void_type_node;
- return result;
-}
-
-tree
-build_modify_expr (lhs, modifycode, rhs)
- tree lhs;
- enum tree_code modifycode;
- tree rhs;
-{
- register tree result;
- tree newrhs = rhs;
- tree lhstype = TREE_TYPE (lhs);
- tree olhstype = lhstype;
-
- /* Types that aren't fully specified cannot be used in assignments. */
- lhs = require_complete_type (lhs);
-
- /* Avoid duplicate error messages from operands that had errors. */
- if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
- return error_mark_node;
-
- /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
- Strip such NOP_EXPRs, since RHS is being used in non-lvalue context. */
- if (TREE_CODE (rhs) == NOP_EXPR
- && TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0)))
- rhs = TREE_OPERAND (rhs, 0);
-
- /* Decide early if we are going to protect RHS from GC
- before assigning it to LHS. */
- if (type_needs_gc_entry (TREE_TYPE (rhs))
- && ! value_safe_from_gc (lhs, rhs))
- rhs = protect_value_from_gc (lhs, rhs);
-
- newrhs = rhs;
-
- /* Handle control structure constructs used as "lvalues". */
-
- switch (TREE_CODE (lhs))
- {
- /* Handle --foo = 5; as these are valid constructs in C++ */
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
- if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
- lhs = build (TREE_CODE (lhs), TREE_TYPE (lhs),
- stabilize_reference (TREE_OPERAND (lhs, 0)));
- return build (COMPOUND_EXPR, lhstype,
- lhs,
- build_modify_expr (TREE_OPERAND (lhs, 0),
- modifycode, rhs));
-
- /* Handle (a, b) used as an "lvalue". */
- case COMPOUND_EXPR:
- pedantic_lvalue_warning (COMPOUND_EXPR);
- return build (COMPOUND_EXPR, lhstype,
- TREE_OPERAND (lhs, 0),
- build_modify_expr (TREE_OPERAND (lhs, 1),
- modifycode, rhs));
-
- /* Handle (a ? b : c) used as an "lvalue". */
- case COND_EXPR:
- pedantic_lvalue_warning (COND_EXPR);
- rhs = save_expr (rhs);
- {
- /* Produce (a ? (b = rhs) : (c = rhs))
- except that the RHS goes through a save-expr
- so the code to compute it is only emitted once. */
- tree cond
- = build_conditional_expr (TREE_OPERAND (lhs, 0),
- build_modify_expr (TREE_OPERAND (lhs, 1),
- modifycode, rhs),
- build_modify_expr (TREE_OPERAND (lhs, 2),
- modifycode, rhs));
- /* Make sure the code to compute the rhs comes out
- before the split. */
- return build (COMPOUND_EXPR, TREE_TYPE (lhs),
- /* Case to void to suppress warning
- from warn_if_unused_value. */
- convert (void_type_node, rhs), cond);
- }
- }
-
- /* If a binary op has been requested, combine the old LHS value with the RHS
- producing the value we should actually store into the LHS. */
-
- if (modifycode == INIT_EXPR)
- ;
- else if (modifycode == NOP_EXPR)
- {
- /* must deal with overloading of `operator=' here. */
- if (TREE_CODE (lhstype) == REFERENCE_TYPE)
- lhstype = TREE_TYPE (lhstype);
-#if 1
- /* `operator=' is not an inheritable operator. */
- if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_HAS_ASSIGNMENT (lhstype))
- {
- result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
- if (result == NULL_TREE)
- return error_mark_node;
- return result;
- }
-#else
- /* Treat `operator=' as an inheritable operator. */
- if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_GETS_ASSIGNMENT (lhstype))
- {
- tree orig_lhstype = lhstype;
- while (! TYPE_HAS_ASSIGNMENT (lhstype))
- {
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (lhstype);
- tree basetype = NULL_TREE;
- for (i = 0; i < n_baseclasses; i++)
- if (TYPE_GETS_ASSIGNMENT (TYPE_BINFO_BASETYPE (lhstype, i)))
- {
- if (basetype != NULL_TREE)
- {
- message_2_types (error, "base classes `%s' and `%s' both have operator ='",
- basetype,
- TYPE_BINFO_BASETYPE (lhstype, i));
- return error_mark_node;
- }
- basetype = TYPE_BINFO_BASETYPE (lhstype, i);
- }
- lhstype = basetype;
- }
- if (orig_lhstype != lhstype)
- {
- lhs = build_indirect_ref (convert_pointer_to (lhstype,
- build_unary_op (ADDR_EXPR, lhs, 0)), NULL);
- if (lhs == error_mark_node)
- {
- error_with_aggr_type (lhstype, "conversion to private basetype `%s'");
- return error_mark_node;
- }
- }
- result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
- if (result == NULL_TREE)
- return error_mark_node;
- return result;
- }
-#endif
- lhstype = olhstype;
- }
- else if (PROMOTES_TO_AGGR_TYPE (lhstype, REFERENCE_TYPE))
- {
- /* This case must convert to some sort of lvalue that
- can participate in an op= operation. */
- tree lhs_tmp = lhs;
- tree rhs_tmp = rhs;
- if (build_default_binary_type_conversion (modifycode, &lhs_tmp, &rhs_tmp))
- {
- lhs = stabilize_reference (lhs_tmp);
- /* Forget is was ever anything else. */
- olhstype = lhstype = TREE_TYPE (lhs);
- newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1);
- }
- else
- return error_mark_node;
- }
- else
- {
- lhs = stabilize_reference (lhs);
- newrhs = build_binary_op (modifycode, lhs, rhs, 1);
- }
-
- /* Handle a cast used as an "lvalue".
- We have already performed any binary operator using the value as cast.
- Now convert the result to the cast type of the lhs,
- and then true type of the lhs and store it there;
- then convert result back to the cast type to be the value
- of the assignment. */
-
- switch (TREE_CODE (lhs))
- {
- case NOP_EXPR:
- case CONVERT_EXPR:
- case FLOAT_EXPR:
- case FIX_TRUNC_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_CEIL_EXPR:
- if (TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (newrhs)) == METHOD_TYPE
- || TREE_CODE (TREE_TYPE (newrhs)) == OFFSET_TYPE)
- newrhs = default_conversion (newrhs);
- {
- tree inner_lhs = TREE_OPERAND (lhs, 0);
- tree result;
- result = build_modify_expr (inner_lhs, NOP_EXPR,
- convert (TREE_TYPE (inner_lhs),
- convert (lhstype, newrhs)));
- return convert (TREE_TYPE (lhs), result);
- }
- }
-
- if (TREE_CODE (lhs) == OFFSET_REF)
- if (TREE_OPERAND (lhs, 0) == NULL_TREE)
- {
- /* Static class member? */
- tree member = TREE_OPERAND (lhs, 1);
- if (TREE_CODE (member) == VAR_DECL)
- lhs = member;
- else
- {
- compiler_error ("invalid static class member");
- return error_mark_node;
- }
- }
- else
- lhs = resolve_offset_ref (lhs);
-
- /* Now we have handled acceptable kinds of LHS that are not truly lvalues.
- Reject anything strange now. */
-
- if (!lvalue_or_else (lhs, "assignment"))
- return error_mark_node;
-
- GNU_xref_assign (lhs);
-
- /* Warn about storing in something that is `const'. */
- /* For C++, don't warn if this is initialization. */
- if (modifycode != INIT_EXPR
- && (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
- || ((TREE_CODE (lhstype) == RECORD_TYPE
- || TREE_CODE (lhstype) == UNION_TYPE)
- && C_TYPE_FIELDS_READONLY (lhstype))
- || (TREE_CODE (lhstype) == REFERENCE_TYPE
- && TYPE_READONLY (TREE_TYPE (lhstype)))))
- readonly_error (lhs, "assignment", 0);
-
- /* If storing into a structure or union member,
- it has probably been given type `int'.
- Compute the type that would go with
- the actual amount of storage the member occupies. */
-
- if (TREE_CODE (lhs) == COMPONENT_REF
- && (TREE_CODE (lhstype) == INTEGER_TYPE
- || TREE_CODE (lhstype) == REAL_TYPE
- || TREE_CODE (lhstype) == ENUMERAL_TYPE))
- lhstype = TREE_TYPE (get_unwidened (lhs, 0));
-
- /* check to see if there is an assignment to `this' */
- if (lhs == current_class_decl)
- {
- if (flag_this_is_variable > 0
- && DECL_NAME (current_function_decl) != NULL_TREE
- && current_class_name != DECL_NAME (current_function_decl))
- warning ("assignment to `this' not in constructor or destructor");
- current_function_just_assigned_this = 1;
- }
-
- /* The TREE_TYPE of RHS may be TYPE_UNKNOWN. This can happen
- when the type of RHS is not yet known, i.e. its type
- is inherited from LHS. */
- rhs = require_instantiated_type (lhstype, newrhs, error_mark_node);
- if (rhs == error_mark_node)
- return error_mark_node;
- newrhs = rhs;
-
- if (modifycode != INIT_EXPR)
- {
- /* Make modifycode now either a NOP_EXPR or an INIT_EXPR. */
- modifycode = NOP_EXPR;
- /* Reference-bashing */
- if (TREE_CODE (lhstype) == REFERENCE_TYPE)
- {
- tree tmp = convert_from_reference (lhs);
- lhstype = TREE_TYPE (tmp);
- if (TYPE_SIZE (lhstype) == 0)
- {
- incomplete_type_error (lhs, lhstype);
- return error_mark_node;
- }
- lhs = tmp;
- olhstype = lhstype;
- }
- if (TREE_CODE (TREE_TYPE (newrhs)) == REFERENCE_TYPE)
- {
- tree tmp = convert_from_reference (newrhs);
- if (TYPE_SIZE (TREE_TYPE (tmp)) == 0)
- {
- incomplete_type_error (newrhs, TREE_TYPE (tmp));
- return error_mark_node;
- }
- newrhs = tmp;
- }
- }
-
- if (TREE_SIDE_EFFECTS (lhs))
- lhs = stabilize_reference (lhs);
- if (TREE_SIDE_EFFECTS (newrhs))
- newrhs = stabilize_reference (newrhs);
-
- /* C++: The semantics of C++ differ from those of C when an
- assignment of an aggregate is desired. Assignment in C++ is
- now defined as memberwise assignment of non-static members
- and base class objects. This rule applies recursively
- until a member of a built-in type is found.
-
- Also, we cannot do a bit-wise copy of aggregates which
- contain virtual function table pointers. Those
- pointer values must be preserved through the copy.
- However, this is handled in expand_expr, and not here.
- This is because much better code can be generated at
- that stage than this one. */
- if (TREE_CODE (lhstype) == RECORD_TYPE
- && (TYPE_USES_VIRTUAL_BASECLASSES (lhstype)
- || (modifycode != INIT_EXPR && TYPE_GETS_ASSIGNMENT (lhstype))
- || (modifycode == INIT_EXPR && TYPE_GETS_INIT_REF (lhstype)))
- && (TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))
- || (TREE_CODE (TREE_TYPE (newrhs)) == RECORD_TYPE
- && UNIQUELY_DERIVED_FROM_P (lhstype, TREE_TYPE (newrhs)))))
- {
- tree vbases = CLASSTYPE_VBASECLASSES (lhstype);
- tree lhs_addr = build_unary_op (ADDR_EXPR, lhs, 0);
- tree rhs_addr;
-
- /* Memberwise assignment would cause NEWRHS to be
- evaluated for every member that gets assigned.
- By wrapping side-effecting exprs in a SAVE_EXPR,
- NEWRHS will only be evaluated once. */
- if (IS_AGGR_TYPE (TREE_TYPE (newrhs))
- && TREE_SIDE_EFFECTS (newrhs)
- /* This are things we don't have to save. */
- && TREE_CODE (newrhs) != TARGET_EXPR
- && TREE_CODE (newrhs) != WITH_CLEANUP_EXPR)
- /* Call `break_out_cleanups' on NEWRHS in case there are cleanups.
- If NEWRHS is a CALL_EXPR that needs a cleanup, failure to do so
- will result in expand_expr expanding the call without knowing
- that it should run the cleanup. */
- newrhs = save_expr (break_out_cleanups (newrhs));
-
- rhs_addr = build_unary_op (ADDR_EXPR, newrhs, 0);
- result = NULL_TREE;
-
- if (! comptypes (TREE_TYPE (lhs_addr), TREE_TYPE (rhs_addr), 1))
- rhs_addr = convert_pointer_to (TREE_TYPE (TREE_TYPE (lhs_addr)), rhs_addr);
- /* Once we have our hands on an address, we must change NEWRHS
- to work from there. Otherwise we can get multiple evaluations
- of NEWRHS. */
- if (TREE_CODE (newrhs) != SAVE_EXPR)
- newrhs = build_indirect_ref (rhs_addr, NULL);
-
- while (vbases)
- {
- tree elt_lhs = convert_pointer_to (vbases, lhs_addr);
- tree elt_rhs = convert_pointer_to (vbases, rhs_addr);
- result
- = tree_cons (NULL_TREE,
- build_modify_expr_1 (build_indirect_ref (elt_lhs, NULL),
- modifycode,
- build_indirect_ref (elt_rhs, NULL),
- TYPE_BINFO (lhstype)),
- result);
- if (TREE_VALUE (result) == error_mark_node)
- return error_mark_node;
- vbases = TREE_CHAIN (vbases);
- }
- result = tree_cons (NULL_TREE,
- build_modify_expr_1 (lhs,
- modifycode,
- newrhs,
- TYPE_BINFO (lhstype)),
- result);
- return build_compound_expr (result);
- }
-
- /* It is now illegal to assign unions which contain members that
- have non-default assignment operators. */
- if (! flag_traditional && TREE_CODE (lhstype) == UNION_TYPE)
- {
- if (modifycode == INIT_EXPR && TYPE_GETS_INIT_REF (lhstype))
- {
- error ("invalid initialization of union containing members with X(X&) constructor");
- return error_mark_node;
- }
- else if (modifycode == NOP_EXPR && TYPE_GETS_ASSIGNMENT (lhstype))
- {
- error ("invalid assignment of union containing members with non-default operator=");
- return error_mark_node;
- }
- }
-
- /* If storing in a field that is in actuality a short or narrower than one,
- we must store in the field in its actual type. */
-
- if (lhstype != TREE_TYPE (lhs))
- {
- lhs = copy_node (lhs);
- TREE_TYPE (lhs) = lhstype;
- }
-
- /* Convert new value to destination type. */
-
- if (TREE_CODE (lhstype) == ARRAY_TYPE)
- {
- /* Have to wrap this in RTL_EXPR for two cases:
- in base or member initialization and if we
- are a branch of a ?: operator. Since we
- can't easily know the latter, just do it always. */
-
- result = make_node (RTL_EXPR);
-
- TREE_TYPE (result) = void_type_node;
- do_pending_stack_adjust ();
- start_sequence ();
-
- /* As a matter of principle, `start_sequence' should do this. */
- emit_note (0, -1);
-
- expand_vec_init (lhs, lhs, array_type_nelts (lhstype), newrhs,
- 1 + (modifycode != INIT_EXPR));
-
- do_pending_stack_adjust ();
-
- TREE_SIDE_EFFECTS (result) = 1;
- RTL_EXPR_SEQUENCE (result) = get_insns ();
- RTL_EXPR_RTL (result) = const0_rtx;
- end_sequence ();
- return result;
- }
-
- if (modifycode == INIT_EXPR)
- {
- newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
- "assignment", NULL_TREE, 0);
- if (lhs == DECL_RESULT (current_function_decl))
- {
- if (DECL_INITIAL (lhs))
- warning ("return value from function receives multiple initializations");
- DECL_INITIAL (lhs) = newrhs;
- }
- }
- else
- {
- if (IS_AGGR_TYPE (lhstype))
- {
- if (TYPE_GETS_ASSIGNMENT (lhstype)
- && ! TYPE_HAS_ASSIGNMENT (lhstype))
- {
- error_with_aggr_type (lhstype, "assignment not defined for type `%s'");
- return error_mark_node;
- }
- if (result = build_opfncall (MODIFY_EXPR,
- LOOKUP_NORMAL, lhs, newrhs,
- make_node (NOP_EXPR)))
- return result;
- }
- newrhs = convert_for_assignment (lhstype, newrhs, "assignment",
- NULL_TREE, 0);
- if (flag_elide_constructors == 0
- && TREE_CODE (newrhs) == CALL_EXPR
- && TREE_ADDRESSABLE (lhstype))
- {
- /* Can't initialized directly from a CALL_EXPR, since
- we don't know about what doesn't alias what. */
-
- tree temp = get_temp_name (lhstype, 0);
- newrhs = build (COMPOUND_EXPR, lhstype,
- build_modify_expr (temp, INIT_EXPR, newrhs),
- temp);
- }
- }
-
- if (TREE_CODE (newrhs) == ERROR_MARK)
- return error_mark_node;
-
- if (TREE_CODE (newrhs) == COND_EXPR)
- {
- tree lhs1;
- tree cond = TREE_OPERAND (newrhs, 0);
-
- if (TREE_SIDE_EFFECTS (lhs))
- cond = build_compound_expr (tree_cons
- (NULL_TREE, lhs,
- build_tree_list (NULL_TREE, cond)));
-
- /* Cannot have two identical lhs on this one tree (result) as preexpand
- calls will rip them out and fill in RTL for them, but when the
- rtl is generated, the calls will only be in the first side of the
- condition, not on both, or before the conditional jump! (mrs) */
- lhs1 = break_out_calls (lhs);
-
- if (lhs == lhs1)
- /* If there's no change, the COND_EXPR behaves like any other rhs. */
- result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
- lhstype, lhs, newrhs);
- else
- {
- tree result_type = TREE_TYPE (newrhs);
- /* We have to convert each arm to the proper type because the
- types may have been munged by constant folding. */
- result
- = build (COND_EXPR, result_type, cond,
- build_modify_expr (lhs, modifycode,
- convert (result_type,
- TREE_OPERAND (newrhs, 1))),
- build_modify_expr (lhs1, modifycode,
- convert (result_type,
- TREE_OPERAND (newrhs, 2))));
- }
- }
- else if (modifycode != INIT_EXPR && TREE_CODE (newrhs) == WITH_CLEANUP_EXPR)
- {
- tree cleanup = TREE_OPERAND (newrhs, 2);
- tree slot;
-
- /* Finish up by running cleanups and having the "value" of the lhs. */
- tree exprlist = tree_cons (NULL_TREE, cleanup,
- build_tree_list (NULL_TREE, lhs));
- newrhs = TREE_OPERAND (newrhs, 0);
- if (TREE_CODE (newrhs) == TARGET_EXPR)
- slot = TREE_OPERAND (newrhs, 0);
- else if (TREE_CODE (newrhs) == ADDR_EXPR)
- {
- /* Bad but legal. */
- slot = newrhs;
- warning ("address taken of temporary object");
- }
- else
- my_friendly_abort (118);
-
- /* Copy the value computed in SLOT into LHS. */
- exprlist = tree_cons (NULL_TREE,
- build_modify_expr (lhs, modifycode, slot),
- exprlist);
- /* Evaluate the expression that needs CLEANUP. This will
- compute the value into SLOT. */
- exprlist = tree_cons (NULL_TREE, newrhs, exprlist);
- result = convert (lhstype, build_compound_expr (exprlist));
- }
- else
- result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
- lhstype, lhs, newrhs);
- TREE_SIDE_EFFECTS (result) = 1;
-
- /* If we got the LHS in a different type for storing in,
- convert the result back to the nominal type of LHS
- so that the value we return always has the same type
- as the LHS argument. */
-
- if (olhstype == TREE_TYPE (result))
- return result;
- return convert_for_assignment (olhstype, result, "assignment",
- NULL_TREE, 0);
-}
-
-
-/* Return 0 if EXP is not a valid lvalue in this language
- even though `lvalue_or_else' would accept it. */
-
-int
-language_lvalue_valid (exp)
- tree exp;
-{
- return 1;
-}
-
-/* Convert value RHS to type TYPE as preparation for an assignment
- to an lvalue of type TYPE.
- The real work of conversion is done by `convert'.
- The purpose of this function is to generate error messages
- for assignments that are not allowed in C.
- ERRTYPE is a string to use in error messages:
- "assignment", "return", etc.
-
- C++: attempts to allow `convert' to find conversions involving
- implicit type conversion between aggregate and scalar types
- as per 8.5.6 of C++ manual. Does not randomly dereference
- pointers to aggregates! */
-
-static tree
-convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
- tree type, rhs;
- char *errtype;
- tree fndecl;
- int parmnum;
-{
- register enum tree_code codel = TREE_CODE (type);
- register tree rhstype;
- register enum tree_code coder = TREE_CODE (TREE_TYPE (rhs));
-
- if (coder == UNKNOWN_TYPE)
- rhs = instantiate_type (type, rhs, 1);
-
- if (coder == ERROR_MARK)
- return error_mark_node;
-
- if (codel == OFFSET_TYPE)
- {
- type = TREE_TYPE (type);
- codel = TREE_CODE (type);
- }
-
- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
- if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
- rhs = TREE_OPERAND (rhs, 0);
-
- if (rhs == error_mark_node)
- return error_mark_node;
-
- if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
- {
- rhs = resolve_offset_ref (rhs);
- if (rhs == error_mark_node)
- return error_mark_node;
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
- }
-
- if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
- rhs = default_conversion (rhs);
- else if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
- rhs = convert_from_reference (rhs);
-
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
-
- /* This should no longer change types on us. */
- if (TREE_CODE (rhs) == CONST_DECL)
- rhs = DECL_INITIAL (rhs);
- else if (TREE_READONLY_DECL_P (rhs))
- rhs = decl_constant_value (rhs);
-
- if (type == rhstype)
- return rhs;
-
- if (coder == VOID_TYPE)
- {
- error ("void value not ignored as it ought to be");
- return error_mark_node;
- }
- /* Arithmetic types all interconvert. */
- if ((codel == INTEGER_TYPE || codel == REAL_TYPE)
- && (coder == INTEGER_TYPE || coder == REAL_TYPE))
- {
- /* But we should warn if assigning REAL_TYPE to INTEGER_TYPE. */
- if (coder == REAL_TYPE && codel == INTEGER_TYPE)
- warn_for_assignment ("float or double assigned to integer data type",
- "float or double used for argument %d of `%s'",
- errtype, fndecl, parmnum, 0);
- /* And we should warn if assigning a negative value to
- an unsigned variable. */
- else if (TREE_UNSIGNED (type))
- {
- if (TREE_CODE (rhs) == INTEGER_CST
- && TREE_NEGATED_INT (rhs))
- warn_for_assignment ("negative value assigned to unsigned quantity",
- "negative value passed as argument %d of `%s'",
- errtype, fndecl, parmnum, 0);
- if (TREE_CONSTANT (rhs))
- rhs = fold (rhs);
- }
-
- return convert (type, rhs);
- }
- /* Conversions involving enums. */
- else if ((codel == ENUMERAL_TYPE
- && (coder == ENUMERAL_TYPE || coder == INTEGER_TYPE || coder == REAL_TYPE))
- || (coder == ENUMERAL_TYPE
- && (codel == ENUMERAL_TYPE || codel == INTEGER_TYPE || codel == REAL_TYPE)))
- {
- extern int warn_enum_clash;
-
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
- return convert (type, rhs);
- if (warn_enum_clash)
- {
- if (codel == ENUMERAL_TYPE && coder == ENUMERAL_TYPE)
- message_2_types (warning, "conversion between incompatible enumeral types `%s' and `%s'",
- type, rhstype);
- else if (coder == REAL_TYPE)
- warn_for_assignment ("float or double assigned to enumeral data type",
- "float or double passed as enumeral data type for argument %d of `%s'",
- errtype, fndecl, parmnum, pedantic);
- else if (codel == REAL_TYPE)
- warn_for_assignment ("enumeral value assigned to real data type",
- "enumeral value passed as real data type for argument %d of `%s'",
- errtype, fndecl, parmnum, pedantic);
- else if (coder == INTEGER_TYPE)
- warn_for_assignment ("assignment of integer to enumeral data type",
- "passing integer as enumeral data type for argument %d of `%s'",
- errtype, fndecl, parmnum, pedantic);
- }
- return convert (type, rhs);
- }
- /* Conversions among pointers */
- else if (codel == POINTER_TYPE && coder == POINTER_TYPE)
- {
- register tree ttl = TREE_TYPE (type);
- register tree ttr = TREE_TYPE (rhstype);
-
- /* If both pointers are of aggregate type, then we
- can give better error messages, and save some work
- as well. */
- if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
- {
- tree binfo;
-
- if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr)
- || type == class_star_type_node
- || rhstype == class_star_type_node)
- binfo = TYPE_BINFO (ttl);
- else
- binfo = get_binfo (ttl, ttr, 1);
-
- if (binfo == error_mark_node)
- return error_mark_node;
- if (binfo == 0)
- return (tree) error_not_base_type (ttl, ttr);
-
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- warn_for_assignment ("%s of non-`const *' pointer from `const *'",
- "pointer to const given for argument %d of `%s'",
- errtype, fndecl, parmnum, 0);
- if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s of non-`volatile *' pointer from `volatile *'",
- "pointer to volatile given for argument %d of `%s'",
- errtype, fndecl, parmnum, 0);
- }
-
- /* Any non-function converts to a [const][volatile] void *
- and vice versa; otherwise, targets must be the same.
- Meanwhile, the lhs target must have all the qualifiers of the rhs. */
- else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
- || TYPE_MAIN_VARIANT (ttr) == void_type_node
- || comp_target_types (type, rhstype, 1))
- {
- if (TYPE_MAIN_VARIANT (ttl) != void_type_node
- && TYPE_MAIN_VARIANT (ttr) == void_type_node
- && rhs != null_pointer_node)
- pedwarn ("ANSI C++ forbids implicit conversion from `void *' in %s",
- errtype);
- else if (pedantic
- && ((TYPE_MAIN_VARIANT (ttl) == void_type_node
- && (TREE_CODE (ttr) == FUNCTION_TYPE
- || TREE_CODE (ttr) == METHOD_TYPE))
- ||
- (TYPE_MAIN_VARIANT (ttr) == void_type_node
- && (TREE_CODE (ttl) == FUNCTION_TYPE
- || TREE_CODE (ttl) == METHOD_TYPE))))
- warn_for_assignment ("%s between function pointer and `void *'",
- "function pointer and `void *' incompatible; argument %d of `%s'",
- errtype, fndecl, parmnum, flag_pedantic_errors);
- /* Const and volatile mean something different for function types,
- so the usual warnings are not appropriate. */
- else if ((TREE_CODE (ttr) != FUNCTION_TYPE && TREE_CODE (ttr) != METHOD_TYPE)
- || (TREE_CODE (ttl) != FUNCTION_TYPE && TREE_CODE (ttl) != METHOD_TYPE))
- {
- if (TREE_CODE (ttl) == OFFSET_TYPE
- && binfo_member (TYPE_OFFSET_BASETYPE (ttr),
- CLASSTYPE_VBASECLASSES (TYPE_OFFSET_BASETYPE (ttl))))
- {
- sorry ("%s between pointer to members converting across virtual baseclasses", errtype);
- return error_mark_node;
- }
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- warn_for_assignment ("%s of non-`const *' pointer from `const *'",
- "pointer to const given for argument %d of `%s'",
- errtype, fndecl, parmnum, flag_pedantic_errors);
- if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s of non-`volatile *' pointer from `volatile *'",
- "pointer to volatile given for argument %d of `%s'",
- errtype, fndecl, parmnum, flag_pedantic_errors);
- }
- }
- else if (TREE_CODE (ttr) == OFFSET_TYPE
- && TREE_CODE (ttl) != OFFSET_TYPE)
- {
- /* Normally, pointers to different type codes (other
- than void) are not compatible, but we perform
- some type instantiation if that resolves the
- ambiguity of (X Y::*) and (X *). */
-
- if (current_class_decl)
- {
- if (TREE_CODE (rhs) == INTEGER_CST)
- {
- rhs = build (PLUS_EXPR, build_pointer_type (TREE_TYPE (ttr)),
- current_class_decl, rhs);
- return convert_for_assignment (type, rhs,
- errtype, fndecl, parmnum);
- }
- }
- if (TREE_CODE (ttl) == METHOD_TYPE)
- error ("%s between pointer-to-method and pointer-to-member types",
- errtype);
- else
- error ("%s between pointer and pointer-to-member types", errtype);
- return error_mark_node;
- }
- else
- {
- int const_parity = TYPE_READONLY (type) ^ TYPE_READONLY (rhstype);
- int volatile_parity = TYPE_VOLATILE (type) ^ TYPE_VOLATILE (rhstype);
- int unsigned_parity;
- int nptrs = 0;
-
- while (TREE_CODE (ttl) == POINTER_TYPE
- && TREE_CODE (ttr) == POINTER_TYPE)
- {
- nptrs -= 1;
- const_parity |= TYPE_READONLY (ttl) ^ TYPE_READONLY (ttr);
- volatile_parity |= TYPE_VOLATILE (ttl) ^ TYPE_VOLATILE (ttr);
- ttl = TREE_TYPE (ttl);
- ttr = TREE_TYPE (ttr);
- }
- unsigned_parity = TREE_UNSIGNED (ttl) - TREE_UNSIGNED (ttr);
- if (unsigned_parity)
- if (TREE_UNSIGNED (ttl))
- ttr = unsigned_type (ttr);
- else
- ttl = unsigned_type (ttl);
-
- if (comp_target_types (ttl, ttr, nptrs))
- {
- if (const_parity)
- warn_for_assignment ("%s of non-`const *' pointer from `const *'",
- "pointer to const given for argument %d of `%s'",
- errtype, fndecl, parmnum, 0);
- if (volatile_parity)
- warn_for_assignment ("%s of non-`volatile *' pointer from volatile *",
- "pointer to volatile given for argument %d of `%s'",
- errtype, fndecl, parmnum, 0);
- if (unsigned_parity > 0)
- warn_for_assignment ("%s of unsigned pointer from signed pointer",
- "passing signed pointer to unsigned pointer argument %d of `%s'",
- errtype, fndecl, parmnum, flag_pedantic_errors);
- else if (unsigned_parity < 0)
- warn_for_assignment ("%s of signed pointer from unsigned pointer",
- "passing unsigned pointer to signed pointer argument %d of `%s'",
- errtype, fndecl, parmnum, flag_pedantic_errors);
-
- /* C++ is not so friendly about converting function and
- member function pointers as C. Emit warnings here. */
- if (TREE_CODE (ttl) == FUNCTION_TYPE
- || TREE_CODE (ttl) == METHOD_TYPE)
- if (! comptypes (ttl, ttr, 0))
- {
- char *tmpbuf, *lhsbuf;
- char *rhsbuf;
- tree null_name = get_identifier ("");
- tree lhs = build_decl (FUNCTION_DECL, null_name, ttl);
- tree rhs = build_decl (FUNCTION_DECL, null_name, ttr);
- tmpbuf = fndecl_as_string (0, lhs, 1);
- lhsbuf = (char *) alloca (strlen (tmpbuf));
- strcpy (lhsbuf, tmpbuf);
- rhsbuf = fndecl_as_string (0, rhs, 1);
- warning ("conflicting function types in %s:", errtype);
- warning ("\t`%s' != `%s'", lhsbuf, rhsbuf);
- }
- }
- else if (TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
- {
- /* When does this happen? */
- my_friendly_abort (119);
- /* Conversion of a pointer-to-member type to void *. */
- rhs = build_unary_op (ADDR_EXPR, rhs, 0);
- TREE_TYPE (rhs) = type;
- return rhs;
- }
- else if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
- {
- /* When does this happen? */
- my_friendly_abort (120);
- /* Conversion of a pointer-to-member type to void *. */
- rhs = build_unary_op (ADDR_EXPR, rhs, 0);
- TREE_TYPE (rhs) = type;
- return rhs;
- }
- else
- {
- if (fndecl)
- error ("incompatible pointer types for argument %d of `%s'",
- parmnum + 1, lang_printable_name (fndecl));
- else
- error ("%s between incompatible pointer types", errtype);
- return error_mark_node;
- }
- }
- return convert (type, rhs);
- }
- else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
- {
- if (! integer_zerop (rhs))
- {
- warn_for_assignment ("%s of pointer from integer lacks a cast",
- "passing integer to pointer argument %d of `%s' lacks a cast",
- errtype, fndecl, parmnum, flag_pedantic_errors);
- return convert (type, rhs);
- }
- return null_pointer_node;
- }
- else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
- {
- warn_for_assignment ("%s of integer from pointer lacks a cast",
- "passing pointer to integer argument %d of `%s' lacks a cast",
- errtype, fndecl, parmnum, flag_pedantic_errors);
- return convert (type, rhs);
- }
-
- /* C++ */
- else if (codel == ERROR_MARK || coder == ERROR_MARK)
- return error_mark_node;
-
- /* This should no longer happen. References are initialized via
- `convert_for_initialization'. They should otherwise be
- bashed before coming here. */
- else if (codel == REFERENCE_TYPE)
- /* Force an abort. */
- my_friendly_assert (codel != REFERENCE_TYPE, 317);
- else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (rhs)))
- return build1 (NOP_EXPR, type, rhs);
- else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
- return convert (type, rhs);
-
- error ("incompatible types in %s", errtype);
- return error_mark_node;
-}
-
-/* Print a warning using either ANON_MSG or NAMED_MSG.
- ANON_MSG is used if DECL and FUNCTION are 0; it gets one parameter, OPNAME.
- NAMED_MSG is used if DECL is non-0;
- it gets two parameters, the name of DECL and that of FUNCTION.
- FUNCTION_MSG is used if DECL is 0 and FUNCTION is non-0;
- it gets one parameter, the name FUNCTION.
-
- If SEVERE is non-0, the report an error instead of a warning.
-
- If FNDECL is nonzero, the message concerns an argument in a call
- to that function. ARGNUM is the number of the argument, origin 0. */
-
-void
-warn_for_assignment (anon_msg, arg_msg, opname, fndecl, argnum, severe)
- char *anon_msg;
- char *arg_msg;
- char *opname;
- tree fndecl;
- int argnum;
- int severe;
-{
- if (fndecl)
- {
- if (argnum < 0)
- {
- char *buf = (char *)alloca (strlen (arg_msg) + 1);
- char *p;
- strcpy (buf, arg_msg);
- for (p = buf; *p; p++)
- if (p[0] == '%' && p[1] == 'd')
- {
- p[1] = 's';
- if (severe)
- error (buf, "`this'", lang_printable_name (fndecl));
- else
- warning (buf, "`this'", lang_printable_name (fndecl));
- break;
- }
- }
- else if (severe)
- error (arg_msg, argnum + 1, lang_printable_name (fndecl));
- else
- warning (arg_msg, argnum + 1, lang_printable_name (fndecl));
- }
- else if (severe)
- error (anon_msg, opname);
- else
- warning (anon_msg, opname);
-}
-
-/* Convert RHS to be of type TYPE. If EXP is non-zero,
- it is the target of the initialization.
- ERRTYPE is a string to use in error messages.
-
- Two major differences between the behavior of
- `convert_for_assignment' and `convert_for_initialization'
- are that references are bashed in the former, while
- copied in the latter, and aggregates are assigned in
- the former (operator=) while initialized in the
- latter (X(X&)).
-
- If using constructor make sure no conversion operator exists, if one does
- exist, an ambiguity exists. */
-tree
-convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
- tree exp, type, rhs;
- int flags;
- char *errtype;
- tree fndecl;
- int parmnum;
-{
- register enum tree_code codel = TREE_CODE (type);
- register tree rhstype;
- register enum tree_code coder;
-
- /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
- Strip such NOP_EXPRs, since RHS is used in non-lvalue context. */
- if (TREE_CODE (rhs) == NOP_EXPR
- && TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0)))
- rhs = TREE_OPERAND (rhs, 0);
-
- if (rhs == error_mark_node
- || (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node))
- return error_mark_node;
-
- if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
- {
- rhs = resolve_offset_ref (rhs);
- if (rhs == error_mark_node)
- return error_mark_node;
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
- }
-
- if ((TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
- && TREE_CODE (type) != ARRAY_TYPE && TREE_CODE (type) != REFERENCE_TYPE)
- || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
- rhs = default_conversion (rhs);
-
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
-
- if (coder == UNKNOWN_TYPE)
- {
- rhs = instantiate_type (type, rhs, 1);
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
- }
-
- if (coder == ERROR_MARK)
- return error_mark_node;
-
-#if 0
- /* This is *not* the quick way out! It is the way to disaster. */
- if (type == rhstype)
- goto converted;
-#endif
-
- /* We accept references to incomplete types, so we can
- return here before checking if RHS is of complete type. */
-
- if (codel == REFERENCE_TYPE)
- return convert_to_reference ((exp ? exp : error_mark_node),
- type, rhs, fndecl, parmnum, errtype,
- 0, flags);
-
- rhs = require_complete_type (rhs);
- if (rhs == error_mark_node)
- return error_mark_node;
-
- if (exp != 0) exp = require_complete_type (exp);
- if (exp == error_mark_node)
- return error_mark_node;
-
- if (TREE_CODE (rhstype) == REFERENCE_TYPE)
- rhstype = TREE_TYPE (rhstype);
-
- if (IS_AGGR_TYPE (type) && TYPE_NEEDS_CONSTRUCTOR (type))
- {
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
- {
- /* This is sufficient to perform initialization. No need, apparently,
- to go through X(X&) to do first-cut initialization. Return through
- a TARGET_EXPR so that we get cleanups if it is used. */
- if (TREE_CODE (rhs) == CALL_EXPR)
- {
- rhs = build_cplus_new (type, rhs, 0);
- return rhs;
- }
- /* Handle the case of default parameter initialization and
- initialization of static variables. */
- else if (TREE_CODE (rhs) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (rhs))
- {
- my_friendly_assert (TREE_CODE (TREE_OPERAND (rhs, 0)) == CALL_EXPR, 318);
- if (exp)
- {
- my_friendly_assert (TREE_VALUE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 1)) == NULL_TREE, 316);
- TREE_VALUE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 1))
- = build_unary_op (ADDR_EXPR, exp, 0);
- }
- else
- rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0), 0);
- return rhs;
- }
- }
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)
- || (IS_AGGR_TYPE (rhstype) && UNIQUELY_DERIVED_FROM_P (type, rhstype)))
- {
- if (TYPE_HAS_INIT_REF (type))
- {
- /* We have to check for template classes here, or else
- build_method_call won't be able to see the constructor. */
- tree id = TYPE_IDENTIFIER (type);
- tree name
- = IDENTIFIER_TEMPLATE (id) ? id : constructor_name (type);
- tree init = build_method_call (exp, name,
- build_tree_list (NULL_TREE, rhs),
- NULL_TREE, LOOKUP_NORMAL);
-
- if (init == error_mark_node)
- return error_mark_node;
-
- if (exp == 0)
- {
- exp = build_cplus_new (type, init, 0);
- return exp;
- }
-
- return build (COMPOUND_EXPR, type, init, exp);
- }
-
-#if 0
- /* ??? The following warnings are turned off because
- this is another place where the default X(X&) constructor
- is implemented. */
- if (TYPE_HAS_ASSIGNMENT (type))
- warning ("bitwise copy: `%s' defines operator=()",
- TYPE_NAME_STRING (type));
- else if (TYPE_GETS_ASSIGNMENT (type))
- warning ("bitwise copy: `%s' has a member with operator=()",
- TYPE_NAME_STRING (type));
-#endif
-
- if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
- rhs = convert_from_reference (rhs);
- if (type != rhstype)
- return build1 (NOP_EXPR, type, rhs);
- return rhs;
- }
-
- return convert (type, rhs);
- }
-#if 0
- /* ??? The following warnings are turned off because
- this is another place where the default X(X&) constructor
- is implemented. */
- if (TYPE_LANG_SPECIFIC (type))
- {
- if (TYPE_HAS_ASSIGNMENT (type))
- warning ("bitwise copy: `%s' defines operator=()",
- TYPE_NAME_STRING (type));
- else if (TYPE_GETS_ASSIGNMENT (type))
- warning ("bitwise copy: `%s' has a member with operator=()",
- TYPE_NAME_STRING (type));
- }
-#endif
-
- if (type == TREE_TYPE (rhs))
- {
- if (TREE_READONLY_DECL_P (rhs))
- rhs = decl_constant_value (rhs);
- return rhs;
- }
-
- return convert_for_assignment (type, rhs, errtype, fndecl, parmnum);
-}
-
-/* Expand an ASM statement with operands, handling output operands
- that are not variables or INDIRECT_REFS by transforming such
- cases into cases that expand_asm_operands can handle.
-
- Arguments are same as for expand_asm_operands.
-
- We don't do default conversions on all inputs, because it can screw
- up operands that are expected to be in memory. */
-
-void
-c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
- tree string, outputs, inputs, clobbers;
- int vol;
- char *filename;
- int line;
-{
- int noutputs = list_length (outputs);
- register int i;
- /* o[I] is the place that output number I should be written. */
- register tree *o = (tree *) alloca (noutputs * sizeof (tree));
- register tree tail;
-
- /* Record the contents of OUTPUTS before it is modified. */
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- o[i] = TREE_VALUE (tail);
-
- /* Generate the ASM_OPERANDS insn;
- store into the TREE_VALUEs of OUTPUTS some trees for
- where the values were actually stored. */
- expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
-
- /* Copy all the intermediate outputs into the specified outputs. */
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- {
- if (o[i] != TREE_VALUE (tail))
- {
- expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
- const0_rtx, VOIDmode, 0);
- free_temp_slots ();
- }
- /* Detect modification of read-only values.
- (Otherwise done by build_modify_expr.) */
- else
- {
- tree type = TREE_TYPE (o[i]);
- if (TYPE_READONLY (type)
- || ((TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE)
- && C_TYPE_FIELDS_READONLY (type)))
- readonly_error (o[i], "modification by `asm'", 1);
- }
- }
-
- /* Those MODIFY_EXPRs could do autoincrements. */
- emit_queue ();
-}
-
-/* Expand a C `return' statement.
- RETVAL is the expression for what to return,
- or a null pointer for `return;' with no value.
-
- C++: upon seeing a `return', we must call destructors on all
- variables in scope which had constructors called on them.
- This means that if in a destructor, the base class destructors
- must be called before returning.
-
- The RETURN statement in C++ has initialization semantics. */
-
-void
-c_expand_return (retval)
- tree retval;
-{
- extern struct nesting *cond_stack, *loop_stack, *case_stack;
- extern tree dtor_label, ctor_label;
- tree result = DECL_RESULT (current_function_decl);
- tree valtype = TREE_TYPE (result);
- register int use_temp = 0;
-
- if (TREE_THIS_VOLATILE (current_function_decl))
- warning ("function declared `volatile' has a `return' statement");
-
- if (retval == error_mark_node)
- {
- current_function_returns_null = 1;
- return;
- }
-
- if (retval == NULL_TREE)
- {
- /* A non-named return value does not count. */
-
- /* Can't just return from a destructor. */
- if (dtor_label)
- {
- expand_goto (dtor_label);
- return;
- }
-
- if (DECL_CONSTRUCTOR_P (current_function_decl))
- retval = current_class_decl;
- else if (DECL_NAME (result) != 0 && TREE_CODE (valtype) != VOID_TYPE)
- retval = result;
- else
- {
- current_function_returns_null = 1;
- if (valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
- {
- if (DECL_NAME (DECL_RESULT (current_function_decl)) == 0)
- warning ("`return' with no value, in function returning non-void");
- }
-
- expand_null_return ();
- return;
- }
- }
- else if (DECL_CONSTRUCTOR_P (current_function_decl)
- && retval != current_class_decl)
- {
- error ("return from a constructor: use `this = ...' instead");
- retval = current_class_decl;
- }
-
- if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
- {
- current_function_returns_null = 1;
- if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
- pedwarn ("ANSI C++ forbids `return' with a value, in function returning void");
- expand_return (retval);
- }
- /* Add some useful error checking for C++. */
- else if (TREE_CODE (valtype) == REFERENCE_TYPE)
- {
- tree whats_returned;
- tree tmp_result = result;
-
- /* Don't initialize directly into a non-BLKmode retval, since that
- could lose when being inlined by another caller. (GCC can't
- read the function return register in an inline function when
- the return value is being ignored). */
- if (result && TYPE_MODE (TREE_TYPE (tmp_result)) != BLKmode)
- tmp_result = 0;
-
- /* convert to reference now, so we can give error if we
- return an reference to a non-lvalue. */
- retval = convert_for_initialization (tmp_result, valtype, retval,
- LOOKUP_NORMAL, "return",
- NULL_TREE, 0);
-
- /* Sort through common things to see what it is
- we are returning. */
- whats_returned = retval;
- if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
- {
- whats_returned = TREE_OPERAND (whats_returned, 1);
- if (TREE_CODE (whats_returned) == ADDR_EXPR)
- whats_returned = TREE_OPERAND (whats_returned, 0);
- }
- if (TREE_CODE (whats_returned) == ADDR_EXPR)
- {
- whats_returned = TREE_OPERAND (whats_returned, 0);
- while (TREE_CODE (whats_returned) == NEW_EXPR
- || TREE_CODE (whats_returned) == TARGET_EXPR
- || TREE_CODE (whats_returned) == WITH_CLEANUP_EXPR)
- /* Get the target. */
- whats_returned = TREE_OPERAND (whats_returned, 0);
- }
-
- if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
- {
- if (TEMP_NAME_P (DECL_NAME (whats_returned)))
- warning ("reference to non-lvalue returned");
- else if (! TREE_STATIC (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned)))
- warning_with_decl (whats_returned,
- "reference to local variable `%s' returned");
- }
- }
- else if (TREE_CODE (retval) == ADDR_EXPR)
- {
- tree whats_returned = TREE_OPERAND (retval, 0);
-
- if (TREE_CODE (whats_returned) == TREE_LIST)
- whats_returned = TREE_VALUE (whats_returned);
-
- if (DECL_NAME (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
- && !TREE_STATIC (whats_returned))
- warning_with_decl (whats_returned,
- "address of local variable `%s' returned");
- }
-
- /* Now deal with possible C++ hair:
- (1) Compute the return value.
- (2) If there are aggregate values with destructors which
- must be cleaned up, clean them (taking care
- not to clobber the return value).
- (3) If an X(X&) constructor is defined, the return
- value must be returned via that. */
-
- if (retval == result
- /* Watch out for constructors, which "return" aggregates
- via initialization, but which otherwise "return" a pointer. */
- || DECL_CONSTRUCTOR_P (current_function_decl))
- {
- /* This is just an error--it's already been reported. */
- if (TYPE_SIZE (valtype) == NULL_TREE)
- return;
-
- if (TYPE_MODE (valtype) != BLKmode
- && any_pending_cleanups (1))
- {
- retval = get_temp_regvar (valtype, retval);
- use_temp = obey_regdecls;
- }
- }
- else if (IS_AGGR_TYPE (valtype) && TYPE_NEEDS_CONSTRUCTOR (valtype))
- {
- /* Throw away the cleanup that `build_functional_cast' gave us. */
- if (TREE_CODE (retval) == WITH_CLEANUP_EXPR
- && TREE_CODE (TREE_OPERAND (retval, 0)) == TARGET_EXPR)
- retval = TREE_OPERAND (retval, 0);
- expand_aggr_init (result, retval, 0);
- DECL_INITIAL (result) = NULL_TREE;
- retval = 0;
- }
- else
- {
- if (TYPE_MODE (valtype) == VOIDmode)
- {
- if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode
- && warn_return_type)
- warning ("return of void value in function returning non-void");
- expand_expr_stmt (retval);
- retval = 0;
- result = 0;
- }
- else if (TYPE_MODE (valtype) != BLKmode
- && any_pending_cleanups (1))
- {
- retval = get_temp_regvar (valtype, retval);
- use_temp = obey_regdecls;
- result = 0;
- }
- else
- {
- retval = convert_for_initialization (result, valtype, retval,
- LOOKUP_NORMAL,
- "return", NULL_TREE, 0);
- DECL_INITIAL (result) = NULL_TREE;
- }
- if (retval == error_mark_node)
- return;
- }
-
- emit_queue ();
-
- if (retval != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (retval)) == 'd'
- && cond_stack == 0 && loop_stack == 0 && case_stack == 0)
- current_function_return_value = retval;
-
- if (result)
- {
- /* Everything's great--RETVAL is in RESULT. */
- if (original_result_rtx)
- store_expr (result, original_result_rtx, 0);
- else if (retval && retval != result)
- {
- /* Clear this out so the later call to decl_function_context
- won't end up bombing on us. */
- if (DECL_CONTEXT (result) == error_mark_node)
- DECL_CONTEXT (result) = NULL_TREE;
- /* Here is where we finally get RETVAL into RESULT.
- `expand_return' does the magic of protecting
- RESULT from cleanups. */
- retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
- TREE_SIDE_EFFECTS (retval) = 1;
- expand_return (retval);
- }
- else
- expand_return (result);
-
- use_variable (DECL_RTL (result));
- if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
- expand_goto (ctor_label);
- else
- expand_null_return ();
- }
- else
- {
- /* We may still need to put RETVAL into RESULT. */
- result = DECL_RESULT (current_function_decl);
- if (original_result_rtx)
- {
- /* Here we have a named return value that went
- into memory. We can compute RETVAL into that. */
- if (retval)
- expand_assignment (result, retval, 0, 0);
- else
- store_expr (result, original_result_rtx, 0);
- result = make_tree (TREE_TYPE (result), original_result_rtx);
- }
- else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
- {
- /* Here RETVAL is CURRENT_CLASS_DECL, so there's nothing to do. */
- expand_goto (ctor_label);
- }
- else if (retval)
- {
- /* Here is where we finally get RETVAL into RESULT.
- `expand_return' does the magic of protecting
- RESULT from cleanups. */
- result = build (INIT_EXPR, TREE_TYPE (result), result, retval);
- TREE_SIDE_EFFECTS (result) = 1;
- expand_return (result);
- }
- else if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode)
- expand_return (result);
- }
-
- current_function_returns_value = 1;
- if (original_result_rtx)
- use_variable (original_result_rtx);
- if (use_temp)
- use_variable (DECL_RTL (DECL_RESULT (current_function_decl)));
-
- /* One way to clear out cleanups that EXPR might
- generate. Note that this code will really be
- dead code, but that is ok--cleanups that were
- needed were handled by the magic of `return'. */
- expand_cleanups_to (NULL_TREE);
-}
-
-/* Start a C switch statement, testing expression EXP.
- Return EXP if it is valid, an error node otherwise. */
-
-tree
-c_expand_start_case (exp)
- tree exp;
-{
- tree type = TREE_TYPE (exp);
- register enum tree_code code = TREE_CODE (type);
-
- if (IS_AGGR_TYPE_CODE (code))
- exp = build_type_conversion (CONVERT_EXPR, integer_type_node, exp, 1);
- else
- exp = default_conversion (exp);
- if (exp == NULL_TREE)
- {
- error ("switch quantity not an integer");
- exp = error_mark_node;
- }
- type = TREE_TYPE (exp);
- code = TREE_CODE (type);
-
- if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK)
- {
- error ("switch quantity not an integer");
- exp = error_mark_node;
- }
- else
- {
- tree index;
-
- exp = default_conversion (exp);
- type = TREE_TYPE (exp);
- index = get_unwidened (exp, 0);
- /* We can't strip a conversion from a signed type to an unsigned,
- because if we did, int_fits_type_p would do the wrong thing
- when checking case values for being in range,
- and it's too hard to do the right thing. */
- if (TREE_UNSIGNED (TREE_TYPE (exp))
- == TREE_UNSIGNED (TREE_TYPE (index)))
- exp = index;
- }
-
- expand_start_case (1, exp, type, "switch statement");
-
- return exp;
-}
-
-/* C++ does not yet support type checking of format strings. */
-
-void
-record_format_info (function_ident, is_scan, format_num, first_arg_num)
- tree function_ident;
- int is_scan;
- int format_num;
- int first_arg_num;
-{}
diff --git a/gnu/gcc2/cc1plus/cp-xref.c b/gnu/gcc2/cc1plus/cp-xref.c
deleted file mode 100644
index 0d4ce96bfc2e..000000000000
--- a/gnu/gcc2/cc1plus/cp-xref.c
+++ /dev/null
@@ -1,825 +0,0 @@
-/* Code for handling XREF output from GNU C++.
- Copyright (C) 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. */
-
-
-#include "config.h"
-#include "tree.h"
-#include <stdio.h>
-#include "cp-tree.h"
-#include "input.h"
-
-#include <ctype.h>
-
-extern char *getpwd ();
-
-extern char *index ();
-extern char *rindex ();
-
-/* The character(s) used to join a directory specification (obtained with
- getwd or equivalent) with a non-absolute file name. */
-
-#ifndef FILE_NAME_JOINER
-#define FILE_NAME_JOINER "/"
-#endif
-
-/* Nonzero if NAME as a file name is absolute. */
-#ifndef FILE_NAME_ABSOLUTE_P
-#define FILE_NAME_ABSOLUTE_P(NAME) (NAME[0] == '/')
-#endif
-
-/* For cross referencing. */
-
-int flag_gnu_xref;
-
-/************************************************************************/
-/* */
-/* Common definitions */
-/* */
-/************************************************************************/
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef NULL
-#define NULL 0
-#endif
-
-#define PALLOC(typ) ((typ *) calloc(1,sizeof(typ)))
-
-
-/* Return a malloc'd copy of STR. */
-#define SALLOC(str) \
- ((char *) ((str) == NULL ? NULL \
- : (char *) strcpy ((char *) malloc (strlen ((str)) + 1), (str))))
-#define SFREE(str) (str != NULL && (free(str),0))
-
-#define STREQL(s1,s2) (strcmp((s1),(s2)) == 0)
-#define STRNEQ(s1,s2) (strcmp((s1),(s2)) != 0)
-#define STRLSS(s1,s2) (strcmp((s1),(s2)) < 0)
-#define STRLEQ(s1,s2) (strcmp((s1),(s2)) <= 0)
-#define STRGTR(s1,s2) (strcmp((s1),(s2)) > 0)
-#define STRGEQ(s1,s2) (strcmp((s1),(s2)) >= 0)
-
-/************************************************************************/
-/* */
-/* Type definitions */
-/* */
-/************************************************************************/
-
-
-typedef struct _XREF_FILE * XREF_FILE;
-typedef struct _XREF_SCOPE * XREF_SCOPE;
-
-typedef struct _XREF_FILE
-{
- char *name;
- char *outname;
- XREF_FILE next;
-} XREF_FILE_INFO;
-
-typedef struct _XREF_SCOPE
-{
- int gid;
- int lid;
- XREF_FILE file;
- int start;
- XREF_SCOPE outer;
-} XREF_SCOPE_INFO;
-
-/************************************************************************/
-/* */
-/* Local storage */
-/* */
-/************************************************************************/
-
-static char doing_xref = 0;
-static FILE * xref_file = NULL;
-static char xref_name[1024];
-static XREF_FILE all_files = NULL;
-static char * wd_name = NULL;
-static XREF_SCOPE cur_scope = NULL;
-static int scope_ctr = 0;
-static XREF_FILE last_file = NULL;
-static tree last_fndecl = NULL;
-
-/************************************************************************/
-/* */
-/* Forward definitions */
-/* */
-/************************************************************************/
-
-extern void GNU_xref_begin();
-extern void GNU_xref_end();
-extern void GNU_xref_file();
-extern void GNU_xref_start_scope();
-extern void GNU_xref_end_scope();
-extern void GNU_xref_ref();
-extern void GNU_xref_decl();
-extern void GNU_xref_call();
-extern void GNU_xref_function();
-extern void GNU_xref_assign();
-extern void GNU_xref_hier();
-extern void GNU_xref_member();
-
-static void gen_assign();
-static XREF_FILE find_file();
-static char * filename();
-static char * fctname();
-static char * declname();
-static void simplify_type();
-static char * fixname();
-static void open_xref_file();
-
-extern char * type_as_string();
-
-/* Start cross referencing. FILE is the name of the file we xref. */
-
-void
-GNU_xref_begin (file)
- char *file;
-{
- doing_xref = 1;
-
- if (file != NULL && STRNEQ (file,"-"))
- {
- open_xref_file(file);
- GNU_xref_file(file);
- }
-}
-
-/* Finish cross-referencing. ERRCNT is the number of errors
- we encountered. */
-
-void
-GNU_xref_end (ect)
- int ect;
-{
- XREF_FILE xf;
-
- if (!doing_xref) return;
-
- xf = find_file (input_filename);
- if (xf == NULL) return;
-
- while (cur_scope != NULL)
- GNU_xref_end_scope(cur_scope->gid,0,0,0,0);
-
- doing_xref = 0;
-
- if (xref_file == NULL) return;
-
- fclose (xref_file);
-
- xref_file = NULL;
- all_files = NULL;
-
- if (ect > 0) unlink (xref_name);
-}
-
-/* Write out xref for file named NAME. */
-
-void
-GNU_xref_file (name)
- char *name;
-{
- XREF_FILE xf;
-
- if (!doing_xref || name == NULL) return;
-
- if (xref_file == NULL)
- {
- open_xref_file (name);
- if (!doing_xref) return;
- }
-
- if (all_files == NULL)
- fprintf(xref_file,"SCP * 0 0 0 0 RESET\n");
-
- xf = find_file (name);
- if (xf != NULL) return;
-
- xf = PALLOC (XREF_FILE_INFO);
- xf->name = SALLOC (name);
- xf->next = all_files;
- all_files = xf;
-
- if (wd_name == NULL)
- wd_name = getpwd ();
-
- if (FILE_NAME_ABSOLUTE_P (name) || ! wd_name)
- xf->outname = xf->name;
- else
- {
- char *nmbuf
- = (char *) malloc (strlen (wd_name) + strlen (FILE_NAME_JOINER)
- + strlen (name) + 1);
- sprintf (nmbuf, "%s%s%s", wd_name, FILE_NAME_JOINER, name);
- name = nmbuf;
- xf->outname = nmbuf;
- }
-
- fprintf (xref_file, "FIL %s %s 0\n", name, wd_name);
-
- filename (xf);
- fctname (NULL);
-}
-
-/* Start a scope identified at level ID. */
-
-void
-GNU_xref_start_scope (id)
- HOST_WIDE_INT id;
-{
- XREF_SCOPE xs;
- XREF_FILE xf;
-
- if (!doing_xref) return;
- xf = find_file (input_filename);
-
- xs = PALLOC (XREF_SCOPE_INFO);
- xs->file = xf;
- xs->start = lineno;
- if (xs->start <= 0) xs->start = 1;
- xs->gid = id;
- xs->lid = ++scope_ctr;
- xs->outer = cur_scope;
- cur_scope = xs;
-}
-
-/* Finish a scope at level ID.
- INID is ???
- PRM is ???
- KEEP is nonzero iff this scope is retained (nonzero if it's
- a compiler-generated invisible scope).
- TRNS is ??? */
-
-void
-GNU_xref_end_scope (id,inid,prm,keep,trns)
- HOST_WIDE_INT id;
- HOST_WIDE_INT inid;
- int prm,keep,trns;
-{
- XREF_FILE xf;
- XREF_SCOPE xs,lxs,oxs;
- char *stype;
-
- if (!doing_xref) return;
- xf = find_file (input_filename);
- if (xf == NULL) return;
-
- lxs = NULL;
- for (xs = cur_scope; xs != NULL; xs = xs->outer)
- {
- if (xs->gid == id) break;
- lxs = xs;
- }
- if (xs == NULL) return;
-
- if (inid != 0) {
- for (oxs = cur_scope; oxs != NULL; oxs = oxs->outer) {
- if (oxs->gid == inid) break;
- }
- if (oxs == NULL) return;
- inid = oxs->lid;
- }
-
- if (prm == 2) stype = "SUE";
- else if (prm != 0) stype = "ARGS";
- else if (keep == 2 || inid != 0) stype = "INTERN";
- else stype = "EXTERN";
-
- fprintf (xref_file,"SCP %s %d %d %d %d %s\n",
- filename (xf), xs->start, lineno,xs->lid, inid, stype);
-
- if (lxs == NULL) cur_scope = xs->outer;
- else lxs->outer = xs->outer;
-
- free (xs);
-}
-
-/* Output a reference to NAME in FNDECL. */
-
-void
-GNU_xref_ref (fndecl,name)
- tree fndecl;
- char *name;
-{
- XREF_FILE xf;
-
- if (!doing_xref) return;
- xf = find_file (input_filename);
- if (xf == NULL) return;
-
- fprintf (xref_file, "REF %s %d %s %s\n",
- filename (xf), lineno, fctname (fndecl), name);
-}
-
-/* Output a reference to DECL in FNDECL. */
-
-void
-GNU_xref_decl (fndecl,decl)
- tree fndecl;
- tree decl;
-{
- XREF_FILE xf,xf1;
- char *cls;
- char *name;
- char buf[10240];
- int uselin;
-
- if (!doing_xref) return;
- xf = find_file (input_filename);
- if (xf == NULL) return;
-
- uselin = FALSE;
-
- if (TREE_CODE (decl) == TYPE_DECL) cls = "TYPEDEF";
- else if (TREE_CODE (decl) == FIELD_DECL) cls = "FIELD";
- else if (TREE_CODE (decl) == VAR_DECL)
- {
- if (fndecl == NULL && TREE_STATIC(decl)
- && TREE_READONLY(decl) && DECL_INITIAL(decl) != 0
- && !TREE_PUBLIC(decl) && !DECL_EXTERNAL(decl)
- && DECL_MODE(decl) != BLKmode) cls = "CONST";
- else if (DECL_EXTERNAL(decl)) cls = "EXTERN";
- else if (TREE_PUBLIC(decl)) cls = "EXTDEF";
- else if (TREE_STATIC(decl)) cls = "STATIC";
- else if (DECL_REGISTER(decl)) cls = "REGISTER";
- else cls = "AUTO";
- }
- else if (TREE_CODE (decl) == PARM_DECL) cls = "PARAM";
- else if (TREE_CODE (decl) == FIELD_DECL) cls = "FIELD";
- else if (TREE_CODE (decl) == CONST_DECL) cls = "CONST";
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- if (DECL_EXTERNAL (decl)) cls = "EXTERN";
- else if (TREE_PUBLIC (decl)) cls = "EFUNCTION";
- else cls = "SFUNCTION";
- }
- else if (TREE_CODE (decl) == LABEL_DECL) cls = "LABEL";
- else if (TREE_CODE (decl) == UNION_TYPE)
- {
- cls = "UNIONID";
- decl = TYPE_NAME (decl);
- uselin = TRUE;
- }
- else if (TREE_CODE (decl) == RECORD_TYPE)
- {
- if (CLASSTYPE_DECLARED_CLASS (decl)) cls = "CLASSID";
- else cls = "STRUCTID";
- decl = TYPE_NAME (decl);
- uselin = TRUE;
- }
- else if (TREE_CODE (decl) == ENUMERAL_TYPE)
- {
- cls = "ENUMID";
- decl = TYPE_NAME (decl);
- uselin = TRUE;
- }
- else cls = "UNKNOWN";
-
- if (decl == NULL || DECL_NAME (decl) == NULL) return;
-
- if (uselin && decl->decl.linenum > 0 && decl->decl.filename != NULL)
- {
- xf1 = find_file (decl->decl.filename);
- if (xf1 != NULL)
- {
- lineno = decl->decl.linenum;
- xf = xf1;
- }
- }
-
- if (DECL_ASSEMBLER_NAME (decl))
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- else
- name = IDENTIFIER_POINTER (DECL_NAME (decl));
-
- strcpy (buf, type_as_string (TREE_TYPE (decl)));
- simplify_type (buf);
-
- fprintf (xref_file, "DCL %s %d %s %d %s %s %s\n",
- filename(xf), lineno, name,
- (cur_scope != NULL ? cur_scope->lid : 0),
- cls, fctname(fndecl), buf);
-
- if (STREQL (cls, "STRUCTID") || STREQL (cls, "UNIONID"))
- {
- cls = "CLASSID";
- fprintf (xref_file, "DCL %s %d %s %d %s %s %s\n",
- filename(xf), lineno,name,
- (cur_scope != NULL ? cur_scope->lid : 0),
- cls, fctname(fndecl), buf);
- }
-}
-
-/* Output a reference to a call to NAME in FNDECL. */
-
-void
-GNU_xref_call (fndecl, name)
- tree fndecl;
- char *name;
-{
- XREF_FILE xf;
- char buf[1024];
- char *s;
-
- if (!doing_xref) return;
- xf = find_file (input_filename);
- if (xf == NULL) return;
- name = fixname (name, buf);
-
- for (s = name; *s != 0; ++s)
- if (*s == '_' && s[1] == '_') break;
- if (*s != 0) GNU_xref_ref (fndecl, name);
-
- fprintf (xref_file, "CAL %s %d %s %s\n",
- filename (xf), lineno, name, fctname (fndecl));
-}
-
-/* Output cross-reference info about FNDECL. If non-NULL,
- ARGS are the arguments for the function (i.e., before the FUNCTION_DECL
- has been fully built). */
-
-void
-GNU_xref_function (fndecl, args)
- tree fndecl;
- tree args;
-{
- XREF_FILE xf;
- int ct;
- char buf[1024];
-
- if (!doing_xref) return;
- xf = find_file (input_filename);
- if (xf == NULL) return;
-
- ct = 0;
- buf[0] = 0;
- if (args == NULL) args = DECL_ARGUMENTS (fndecl);
-
- GNU_xref_decl (NULL, fndecl);
-
- for ( ; args != NULL; args = TREE_CHAIN (args))
- {
- GNU_xref_decl (fndecl,args);
- if (ct != 0) strcat (buf,",");
- strcat (buf, declname (args));
- ++ct;
- }
-
- fprintf (xref_file, "PRC %s %d %s %d %d %s\n",
- filename(xf), lineno, declname(fndecl),
- (cur_scope != NULL ? cur_scope->lid : 0),
- ct, buf);
-}
-
-/* Output cross-reference info about an assignment to NAME. */
-
-void
-GNU_xref_assign(name)
- tree name;
-{
- XREF_FILE xf;
-
- if (!doing_xref) return;
- xf = find_file(input_filename);
- if (xf == NULL) return;
-
- gen_assign(xf, name);
-}
-
-static void
-gen_assign(xf, name)
- XREF_FILE xf;
- tree name;
-{
- char *s;
-
- s = NULL;
-
- switch (TREE_CODE (name))
- {
- case IDENTIFIER_NODE :
- s = IDENTIFIER_POINTER(name);
- break;
- case VAR_DECL :
- s = declname(name);
- break;
- case COMPONENT_REF :
- gen_assign(xf, TREE_OPERAND(name, 0));
- gen_assign(xf, TREE_OPERAND(name, 1));
- break;
- case INDIRECT_REF :
- case OFFSET_REF :
- case ARRAY_REF :
- case BUFFER_REF :
- gen_assign(xf, TREE_OPERAND(name, 0));
- break;
- case COMPOUND_EXPR :
- gen_assign(xf, TREE_OPERAND(name, 1));
- break;
- default :
- break;
- }
-
- if (s != NULL)
- fprintf(xref_file, "ASG %s %d %s\n", filename(xf), lineno, s);
-}
-
-/* Output cross-reference info about a class hierarchy.
- CLS is the class type of interest. BASE is a baseclass
- for CLS. PUB and VIRT give the visibility info about
- the class derivation. FRND is nonzero iff BASE is a friend
- of CLS.
-
- ??? Needs to handle nested classes. */
-void
-GNU_xref_hier(cls, base, pub, virt, frnd)
- char *cls;
- char *base;
- int pub;
- int virt;
- int frnd;
-{
- XREF_FILE xf;
-
- if (!doing_xref) return;
- xf = find_file(input_filename);
- if (xf == NULL) return;
-
- fprintf(xref_file, "HIE %s %d %s %s %d %d %d\n",
- filename(xf), lineno, cls, base, pub, virt, frnd);
-}
-
-/* Output cross-reference info about class members. CLS
- is the containing type; FLD is the class member. */
-
-void
-GNU_xref_member(cls, fld)
- tree cls;
- tree fld;
-{
- XREF_FILE xf;
- char *prot;
- int confg, pure;
- char *d;
- int i;
- char buf[1024], bufa[1024];
-
- if (!doing_xref) return;
- xf = find_file(fld->decl.filename);
- if (xf == NULL) return;
-
- if (TREE_PRIVATE (fld)) prot = "PRIVATE";
- else if (TREE_PROTECTED(fld)) prot = "PROTECTED";
- else prot = "PUBLIC";
-
- confg = 0;
- if (TREE_CODE (fld) == FUNCTION_DECL && DECL_CONST_MEMFUNC_P(fld))
- confg = 1;
- else if (TREE_CODE (fld) == CONST_DECL)
- confg = 1;
-
- pure = 0;
- if (TREE_CODE (fld) == FUNCTION_DECL && DECL_ABSTRACT_VIRTUAL_P(fld))
- pure = 1;
-
- d = IDENTIFIER_POINTER(cls);
- sprintf(buf, "%d%s", strlen(d), d);
- i = strlen(buf);
- strcpy(bufa, declname(fld));
-
-#ifdef XREF_SHORT_MEMBER_NAMES
- for (p = &bufa[1]; *p != 0; ++p)
- {
- if (p[0] == '_' && p[1] == '_' && p[2] >= '0' && p[2] <= '9') {
- if (strncmp(&p[2], buf, i) == 0) *p = 0;
- break;
- }
- else if (p[0] == '_' && p[1] == '_' && p[2] == 'C' && p[3] >= '0' && p[3] <= '9') {
- if (strncmp(&p[3], buf, i) == 0) *p = 0;
- break;
- }
- }
-#endif
-
- fprintf(xref_file, "MEM %s %d %s %s %s %d %d %d %d %d %d %d\n",
- filename(xf), fld->decl.linenum, d, bufa, prot,
- (TREE_CODE (fld) == FUNCTION_DECL ? 0 : 1),
- (DECL_INLINE (fld) ? 1 : 0),
- (DECL_FRIEND_P(fld) ? 1 : 0),
- (DECL_VINDEX(fld) ? 1 : 0),
- (TREE_STATIC(fld) ? 1 : 0),
- pure, confg);
-}
-
-/* Find file entry given name. */
-
-static XREF_FILE
-find_file(name)
- char *name;
-{
- XREF_FILE xf;
-
- for (xf = all_files; xf != NULL; xf = xf->next) {
- if (STREQL(name, xf->name)) break;
- }
-
- return xf;
-}
-
-/* Return filename for output purposes. */
-
-static char *
-filename(xf)
- XREF_FILE xf;
-{
- if (xf == NULL) {
- last_file = NULL;
- return "*";
- }
-
- if (last_file == xf) return "*";
-
- last_file = xf;
-
- return xf->outname;
-}
-
-/* Return function name for output purposes. */
-
-static char *
-fctname(fndecl)
- tree fndecl;
-{
- static char fctbuf[1024];
- char *s;
-
- if (fndecl == NULL && last_fndecl == NULL) return "*";
-
- if (fndecl == NULL)
- {
- last_fndecl = NULL;
- return "*TOP*";
- }
-
- if (fndecl == last_fndecl) return "*";
-
- last_fndecl = fndecl;
-
- s = declname(fndecl);
- s = fixname(s, fctbuf);
-
- return s;
-}
-
-/* Return decl name for output purposes. */
-
-static char *
-declname(dcl)
- tree dcl;
-{
- if (DECL_NAME (dcl) == NULL) return "?";
-
- if (DECL_ASSEMBLER_NAME (dcl))
- return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (dcl));
- else
- return IDENTIFIER_POINTER (DECL_NAME (dcl));
-}
-
-/* Simplify a type string by removing unneeded parenthesis. */
-
-static void
-simplify_type(typ)
- char *typ;
-{
- char *s;
- int lvl, i;
-
- i = strlen(typ);
- while (i > 0 && isspace(typ[i-1])) typ[--i] = 0;
-
- if (i > 7 && STREQL(&typ[i-5], "const"))
- {
- typ[i-5] = 0;
- i -= 5;
- }
-
- if (typ[i-1] != ')') return;
-
- s = &typ[i-2];
- lvl = 1;
- while (*s != 0) {
- if (*s == ')') ++lvl;
- else if (*s == '(')
- {
- --lvl;
- if (lvl == 0)
- {
- s[1] = ')';
- s[2] = 0;
- break;
- }
- }
- --s;
- }
-
- if (*s != 0 && s[-1] == ')')
- {
- --s;
- --s;
- if (*s == '(') s[2] = 0;
- else if (*s == ':') {
- while (*s != '(') --s;
- s[1] = ')';
- s[2] = 0;
- }
- }
-}
-
-/* Fixup a function name (take care of embedded spaces). */
-
-static char *
-fixname(nam, buf)
- char *nam;
- char *buf;
-{
- char *s, *t;
- int fg;
-
- s = nam;
- t = buf;
- fg = 0;
-
- while (*s != 0)
- {
- if (*s == ' ')
- {
- *t++ = '\36';
- ++fg;
- }
- else *t++ = *s;
- ++s;
- }
- *t = 0;
-
- if (fg == 0) return nam;
-
- return buf;
-}
-
-/* Open file for xrefing. */
-
-static void
-open_xref_file(file)
- char *file;
-{
- char *s, *t;
-
-#ifdef XREF_FILE_NAME
- XREF_FILE_NAME (xref_name, file);
-#else
- s = rindex (file, '/');
- if (s == NULL)
- sprintf (xref_name, ".%s.gxref", file);
- else
- {
- ++s;
- strcpy (xref_name, file);
- t = rindex (xref_name, '/');
- ++t;
- *t++ = '.';
- strcpy (t, s);
- strcat (t, ".gxref");
- }
-#endif /* no XREF_FILE_NAME */
-
- xref_file = fopen(xref_name, "w");
-
- if (xref_file == NULL)
- {
- error("Can't create cross-reference file `%s'", xref_name);
- doing_xref = 0;
- }
-}
diff --git a/gnu/gcc2/cc1plus/stack.h b/gnu/gcc2/cc1plus/stack.h
deleted file mode 100644
index c5d9a2512a91..000000000000
--- a/gnu/gcc2/cc1plus/stack.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* stack.h - structed access to object stacks
- Copyright (C) 1988 Free Software Foundation, Inc.
- Contributed by Michael Tiemann (tiemann@cygnus.com).
-
-This program 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.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* Summary: this file contains additional structures that layer
- on top of obstacks for GNU C++. */
-
-/* Stack of data placed on obstacks. */
-
-struct stack_level
-{
- /* Pointer back to previous such level. */
- struct stack_level *prev;
-
- /* Point to obstack we should return to. */
- struct obstack *obstack;
-
- /* First place we start putting data. */
- tree *first;
-
- /* Number of entries we can have from `first'.
- Right now we are dumb: if we overflow, abort. */
- int limit;
-};
-
-struct stack_level *push_stack_level PROTO((struct obstack *, char *, int));
-struct stack_level *pop_stack_level PROTO((struct stack_level *));