diff options
| author | svn2git <svn2git@FreeBSD.org> | 1994-05-01 08:00:00 +0000 |
|---|---|---|
| committer | svn2git <svn2git@FreeBSD.org> | 1994-05-01 08:00:00 +0000 |
| commit | a16f65c7d117419bd266c28a1901ef129a337569 (patch) | |
| tree | 2626602f66dc3551e7a7c7bc9ad763c3bc7ab40a /gnu/gcc2/cc1plus | |
| parent | 8503f4f13f77abf7adc8f7e329c6f9c1d52b6a20 (diff) | |
Release FreeBSD 1.1upstream/1.1.0_cvsrelease/1.1.0_cvs
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')
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 *)); |
