diff options
Diffstat (limited to 'gnu/gcc2/cc1plus/cp-decl2.c')
| -rw-r--r-- | gnu/gcc2/cc1plus/cp-decl2.c | 2451 |
1 files changed, 0 insertions, 2451 deletions
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 (); -} |
