diff options
Diffstat (limited to 'gcc/cp/decl2.c')
-rwxr-xr-x | gcc/cp/decl2.c | 5040 |
1 files changed, 0 insertions, 5040 deletions
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c deleted file mode 100755 index 91c38da..0000000 --- a/gcc/cp/decl2.c +++ /dev/null @@ -1,5040 +0,0 @@ -/* Process declarations and variables for C compiler. - Copyright (C) 1988, 92-98, 1999 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, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, 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 "system.h" -#include "tree.h" -#include "rtl.h" -#include "flags.h" -#include "cp-tree.h" -#include "decl.h" -#include "lex.h" -#include "output.h" -#include "except.h" -#include "expr.h" -#include "defaults.h" -#include "toplev.h" -#include "dwarf2out.h" -#include "dwarfout.h" - -#if USE_CPPLIB -#include "cpplib.h" -extern cpp_reader parse_in; -#endif - -static tree get_sentry PROTO((tree)); -static void mark_vtable_entries PROTO((tree)); -static void grok_function_init PROTO((tree, tree)); -static int finish_vtable_vardecl PROTO((tree, tree)); -static int prune_vtable_vardecl PROTO((tree, tree)); -static void finish_sigtable_vardecl PROTO((tree, tree)); -static int is_namespace_ancestor PROTO((tree, tree)); -static void add_using_namespace PROTO((tree, tree, int)); -static tree ambiguous_decl PROTO((tree, tree, tree,int)); -static tree build_anon_union_vars PROTO((tree, tree*, int, int)); -static void check_decl_namespace PROTO((void)); - -extern int current_class_depth; - -/* 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; - -/* A list of functions which were declared inline, but which we - may need to emit outline anyway. */ -static tree saved_inlines; - -/* Used to help generate temporary names which are unique within - a function. Reset to 0 by start_function. */ - -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; - -/* Flag used when debugging spew.c */ - -extern int spew_debug; - -/* Nonzero if we're done parsing and into end-of-file activities. */ - -int at_eof; - -/* Functions called along with real static constructors and destructors. */ - -tree static_ctors, static_dtors; - -/* The current open namespace, and ::. */ - -tree current_namespace; -tree global_namespace; - -/* The stack for namespaces of current declarations. */ - -static tree decl_namespace_list; - - -/* 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 any extension keywords. */ - -int flag_no_gnu_keywords; - -/* Nonzero means don't recognize the non-ANSI builtin functions. */ - -int flag_no_builtin; - -/* Nonzero means don't recognize the non-ANSI builtin functions. - -ansi sets this. */ - -int flag_no_nonansi_builtin; - -/* Nonzero means do some things the same way PCC does. Only provided so - the compiler will link. */ - -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; - -/* Nonzero means enable obscure ANSI features and disable GNU extensions - that might cause ANSI-compliant code to be miscompiled. */ - -int flag_ansi; - -/* Nonzero means do emit exported implementations of functions even if - they can be inlined. */ - -int flag_implement_inlines = 1; - -/* Nonzero means do emit exported implementations of templates, instead of - multiple static copies in each file that needs a definition. */ - -int flag_external_templates; - -/* Nonzero means that the decision to emit or not emit the implementation of a - template depends on where the template is instantiated, rather than where - it is defined. */ - -int flag_alt_external_templates; - -/* Nonzero means that implicit instantiations will be emitted if needed. */ - -int flag_implicit_templates = 1; - -/* Nonzero means that implicit instantiations of inline templates will be - emitted if needed, even if instantiations of non-inline templates - aren't. */ - -int flag_implicit_inline_templates = 1; - -/* Nonzero means warn about implicit declarations. */ - -int warn_implicit = 1; - -/* Nonzero means warn about usage of long long when `-pedantic'. */ - -int warn_long_long = 1; - -/* Nonzero means warn when all ctors or dtors are private, and the class - has no friends. */ - -int warn_ctor_dtor_privacy = 1; - -/* True if we want to implement vtables using "thunks". - The default is off. */ - -#ifndef DEFAULT_VTABLE_THUNKS -#define DEFAULT_VTABLE_THUNKS 0 -#endif -int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS; - -/* True if we want to deal with repository information. */ - -int flag_use_repository; - -/* Nonzero if we want to issue diagnostics that the standard says are not - required. */ - -int flag_optional_diags = 1; - -/* Nonzero means give string constants the type `const char *', as mandated - by the standard. */ - -int flag_const_strings = 1; - -/* Nonzero means warn about deprecated conversion from string constant to - `char *'. */ - -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 about sizeof(function) or addition/subtraction - of function pointers. */ - -int warn_pointer_arith = 1; - -/* 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 if initializer is not completely bracketed. */ - -int warn_missing_braces; - -/* Warn about comparison of signed and unsigned values. */ - -int warn_sign_compare; - -/* Warn about *printf or *scanf format/argument anomalies. */ - -int warn_format; - -/* Warn about a subscript that has type char. */ - -int warn_char_subscripts; - -/* Warn if a type conversion is done that might have confusing results. */ - -int warn_conversion; - -/* Warn if adding () is suggested. */ - -int warn_parentheses; - -/* 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 declaring a class that has a non virtual - destructor, when it really ought to have a virtual one. */ -int warn_nonvdtor; - -/* Non-zero means warn when a function is declared extern and later inline. */ -int warn_extern_inline; - -/* Non-zero means warn when the compiler will reorder code. */ -int warn_reorder; - -/* Non-zero means warn when synthesis behavior differs from Cfront's. */ -int warn_synth; - -/* Non-zero means warn when we convert a pointer to member function - into a pointer to (void or function). */ -int warn_pmf2ptr = 1; - -/* Nonzero means warn about violation of some Effective C++ style rules. */ - -int warn_ecpp; - -/* Nonzero means warn where overload resolution chooses a promotion from - unsigned to signed over a conversion to an unsigned of the same size. */ - -int warn_sign_promo; - -/* Nonzero means warn when an old-style cast is used. */ - -int warn_old_style_cast; - -/* Warn about #pragma directives that are not recognised. */ - -int warn_unknown_pragmas; /* Tri state variable. */ - -/* Nonzero means warn about use of multicharacter literals. */ - -int warn_multichar = 1; - -/* Nonzero means warn when non-templatized friend functions are - declared within a template */ - -int warn_nontemplate_friend = 1; - -/* Nonzero means `$' can be in an identifier. */ - -#ifndef DOLLARS_IN_IDENTIFIERS -#define DOLLARS_IN_IDENTIFIERS 1 -#endif -int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; - -/* Nonzero for -fno-strict-prototype switch: do not consider empty - argument prototype to mean function takes no arguments. */ - -int flag_strict_prototype = 2; -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. */ -/* 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; - -/* 3 means write out only virtuals function tables `defined' - in this implementation file. - 0 means write out virtual function tables and give them - (C) static access (default). */ - -int write_virtuals; - -/* Nonzero means we should attempt to elide constructors when possible. */ - -int flag_elide_constructors = 1; - -/* Nonzero means recognize and handle signature language constructs. */ - -int flag_handle_signatures; - -/* Nonzero means that member functions defined in class scope are - inline by default. */ - -int flag_default_inline = 1; - -/* Controls whether compiler generates 'type descriptor' that give - run-time type information. */ -int flag_rtti = 1; - -/* Nonzero if we wish to output cross-referencing information - for the GNU class browser. */ -extern int flag_gnu_xref; - -/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes) - objects. */ - -int flag_huge_objects; - -/* Nonzero if we want to conserve space in the .o files. We do this - by putting uninitialized data and runtime initialized data into - .common instead of .data at the expense of not flagging multiple - definitions. */ - -int flag_conserve_space; - -/* Nonzero if we want to obey access control semantics. */ - -int flag_access_control = 1; - -/* Nonzero if we want to understand the operator names, i.e. 'bitand'. */ - -int flag_operator_names; - -/* Nonzero if we want to check the return value of new and avoid calling - constructors if it is a null pointer. */ - -int flag_check_new; - -/* Nonzero if we want the new ANSI rules for pushing a new scope for `for' - initialization variables. - 0: Old rules, set by -fno-for-scope. - 2: New ANSI rules, set by -ffor-scope. - 1: Try to implement new ANSI rules, but with backup compatibility - (and warnings). This is the default, for now. */ - -int flag_new_for_scope = 1; - -/* Nonzero if we want to emit defined symbols with common-like linkage as - weak symbols where possible, in order to conform to C++ semantics. - Otherwise, emit them as local symbols. */ - -int flag_weak = 1; - -/* CYGNUS LOCAL Embedded C++ */ -/* Nonzero if we want to adhere to the language rules of the Embedded C++ - specification. */ - -int flag_embedded_cxx = 0; -/* END CYGNUS LOCAL Embedded C++ */ - -/* Nonzero to enable experimental ABI changes. */ - -int flag_new_abi; - -/* Nonzero to not ignore namespace std. */ - -int flag_honor_std; - -/* Maximum template instantiation depth. Must be at least 17 for ANSI - compliance. */ - -int max_tinst_depth = 17; - -/* The name-mangling scheme to use. Must be 1 or greater to support - template functions with identical types, but different template - arguments. */ -int name_mangling_version = 2; - -/* Nonzero means that guiding declarations are allowed. */ -int flag_guiding_decls; - -/* Nonzero if squashed mangling is to be performed. - This uses the B and K codes to reference previously seen class types - and class qualifiers. */ -int flag_do_squangling; - -/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */ - -int flag_vtable_gc; - -/* Nonzero means make the default pedwarns warnings instead of errors. - The value of this flag is ignored if -pedantic is specified. */ - -int flag_permissive; - -/* 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[] = -{ - /* C/C++ 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}, - -/* CYGNUS LOCAL Embedded C++ */ - {"embedded-cxx", &flag_embedded_cxx, 1}, -/* END CYGNUS LOCAL Embedded C++ */ - - /* C++-only options. */ - {"access-control", &flag_access_control, 1}, - {"check-new", &flag_check_new, 1}, - {"conserve-space", &flag_conserve_space, 1}, - {"const-strings", &flag_const_strings, 1}, - {"default-inline", &flag_default_inline, 1}, - {"dollars-in-identifiers", &dollars_in_ident, 1}, - {"elide-constructors", &flag_elide_constructors, 1}, - {"external-templates", &flag_external_templates, 1}, - {"for-scope", &flag_new_for_scope, 2}, - {"gnu-keywords", &flag_no_gnu_keywords, 0}, - {"handle-exceptions", &flag_exceptions, 1}, - {"handle-signatures", &flag_handle_signatures, 1}, - {"honor-std", &flag_honor_std, 1}, - {"huge-objects", &flag_huge_objects, 1}, - {"implement-inlines", &flag_implement_inlines, 1}, - {"implicit-inline-templates", &flag_implicit_inline_templates, 1}, - {"implicit-templates", &flag_implicit_templates, 1}, - {"labels-ok", &flag_labels_ok, 1}, - {"nonansi-builtins", &flag_no_nonansi_builtin, 0}, - {"operator-names", &flag_operator_names, 1}, - {"optional-diags", &flag_optional_diags, 1}, - {"permissive", &flag_permissive, 1}, - {"repo", &flag_use_repository, 1}, - {"rtti", &flag_rtti, 1}, - {"squangle", &flag_do_squangling, 1}, - {"stats", &flag_detailed_statistics, 1}, - {"strict-prototype", &flag_strict_prototype, 1}, - {"this-is-variable", &flag_this_is_variable, 1}, - {"vtable-gc", &flag_vtable_gc, 1}, - {"vtable-thunks", &flag_vtable_thunks, 1}, - {"weak", &flag_weak, 1}, - {"xref", &flag_gnu_xref, 1} -}; - -/* Decode the string P as a language-specific option. - Return the number of strings consumed for a valid option. - Otherwise return 0. */ - -int -lang_decode_option (argc, argv) - int argc -#if !USE_CPPLIB - ATTRIBUTE_UNUSED -#endif - ; - char **argv; - -{ - int strings_processed; - char *p = argv[0]; -#if USE_CPPLIB - strings_processed = cpp_handle_option (&parse_in, argc, argv); -#else - strings_processed = 0; -#endif /* ! USE_CPPLIB */ - - if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional")) - /* ignore */; - 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; - size_t j; - - p += 2; - /* Try special -f options. */ - - if (!strcmp (p, "handle-exceptions") - || !strcmp (p, "no-handle-exceptions")) - warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)"); - - if (!strcmp (p, "memoize-lookups") - || !strcmp (p, "no-memoize-lookups") - || !strcmp (p, "save-memoized") - || !strcmp (p, "no-save-memoized") - || !strcmp (p, "no-all-virtual") - || !strcmp (p, "no-enum-int-equiv") - || !strcmp (p, "nonnull-objects") - || !strcmp (p, "ansi-overloading")) - { - /* ignore */ - found = 1; - } - else if (!strcmp (p, "all-virtual") - || !strcmp (p, "enum-int-equiv") - || !strcmp (p, "no-nonnull-objects") - || !strcmp (p, "no-ansi-overloading")) - { - warning ("-f%s is no longer supported", p); - found = 1; - } - else if (! strcmp (p, "alt-external-templates")) - { - flag_external_templates = 1; - flag_alt_external_templates = 1; - found = 1; - } - else if (! strcmp (p, "no-alt-external-templates")) - { - flag_alt_external_templates = 0; - found = 1; - } - else if (!strcmp (p, "repo")) - { - flag_use_repository = 1; - flag_implicit_templates = 0; - found = 1; - } - else if (!strcmp (p, "guiding-decls")) - { - flag_guiding_decls = 1; - name_mangling_version = 0; - found = 1; - } - else if (!strcmp (p, "no-guiding-decls")) - { - flag_guiding_decls = 0; - found = 1; - } -/* CYGNUS LOCAL Embedded C++ */ - else if (!strcmp (p, "embedded-cxx")) - { - flag_embedded_cxx = 1; - flag_rtti = flag_exceptions = 0; - flag_vtable_thunks = 1; - found = 1; - } - else if (!strcmp (p, "no-embedded-cxx")) - { - flag_embedded_cxx = 0; - found = 1; - } -/* END CYGNUS LOCAL Embedded C++ */ - else if (!strcmp (p, "new-abi")) - { - flag_new_abi = 1; - flag_do_squangling = 1; - flag_honor_std = 1; - flag_vtable_thunks = 1; - } - else if (!strcmp (p, "no-new-abi")) - { - flag_new_abi = 0; - flag_do_squangling = 0; - flag_honor_std = 0; - } - else if (!strncmp (p, "template-depth-", 15)) - { - char *endp = p + 15; - while (*endp) - { - if (*endp >= '0' && *endp <= '9') - endp++; - else - { - error ("Invalid option `%s'", p - 2); - goto template_depth_lose; - } - } - max_tinst_depth = atoi (p + 15); - template_depth_lose: ; - } - else if (!strncmp (p, "name-mangling-version-", 22)) - { - char *endp = p + 22; - while (*endp) - { - if (*endp >= '0' && *endp <= '9') - endp++; - else - { - error ("Invalid option `%s'", p - 2); - goto mangling_version_lose; - } - } - name_mangling_version = atoi (p + 22); - mangling_version_lose: ; - } - 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, "long-long")) - warn_long_long = setting; - else if (!strcmp (p, "return-type")) - warn_return_type = setting; - else if (!strcmp (p, "ctor-dtor-privacy")) - warn_ctor_dtor_privacy = 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, "char-subscripts")) - warn_char_subscripts = setting; - else if (!strcmp (p, "pointer-arith")) - warn_pointer_arith = 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, "missing-braces")) - warn_missing_braces = setting; - else if (!strcmp (p, "sign-compare")) - warn_sign_compare = 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, "non-virtual-dtor")) - warn_nonvdtor = setting; - else if (!strcmp (p, "extern-inline")) - warn_extern_inline = setting; - else if (!strcmp (p, "reorder")) - warn_reorder = setting; - else if (!strcmp (p, "synth")) - warn_synth = setting; - else if (!strcmp (p, "pmf-conversions")) - warn_pmf2ptr = setting; - else if (!strcmp (p, "effc++")) - warn_ecpp = setting; - else if (!strcmp (p, "sign-promo")) - warn_sign_promo = setting; - else if (!strcmp (p, "old-style-cast")) - warn_old_style_cast = setting; - else if (!strcmp (p, "overloaded-virtual")) - warn_overloaded_virtual = setting; - else if (!strcmp (p, "multichar")) - warn_multichar = setting; - else if (!strcmp (p, "unknown-pragmas")) - /* Set to greater than 1, so that even unknown pragmas in - system headers will be warned about. */ - warn_unknown_pragmas = setting * 2; - else if (!strcmp (p, "non-template-friend")) - warn_nontemplate_friend = 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")) - { - warn_return_type = setting; - warn_unused = setting; - warn_implicit = setting; - warn_ctor_dtor_privacy = setting; - warn_switch = setting; - warn_format = setting; - warn_parentheses = setting; - warn_missing_braces = setting; - warn_sign_compare = setting; - warn_extern_inline = setting; - warn_nonvdtor = setting; - warn_multichar = 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_reorder = setting; - warn_sign_promo = setting; - /* Only warn about unknown pragmas that are not in system - headers. */ - warn_unknown_pragmas = 1; - warn_nontemplate_friend = setting; - } - else return strings_processed; - } - else if (!strcmp (p, "-ansi")) - flag_no_nonansi_builtin = 1, flag_ansi = 1, - flag_no_gnu_keywords = 1, flag_operator_names = 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 strings_processed; - - 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); - int type_quals = TYPE_UNQUALIFIED; - int dup_quals = TYPE_UNQUALIFIED; - - do - { - int tq = cp_type_qual_from_rid (TREE_VALUE (quals)); - - if (type_quals & tq) - dup_quals |= tq; - else - type_quals |= tq; - quals = TREE_CHAIN (quals); - } - while (quals); - - if (dup_quals != TYPE_UNQUALIFIED) - cp_error ("duplicate type qualifiers in %s declaration", - TREE_CODE (function) == FUNCTION_DECL - ? "member function" : "type"); - - ctype = cp_build_qualified_type (ctype, type_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 (fntype, raises); - - TREE_TYPE (function) = fntype; - return ctype; -} - -/* Warn when -fexternal-templates is used and #pragma - interface/implementation is not used all the times it should be, - inform the user. */ - -void -warn_if_unknown_interface (decl) - tree decl; -{ - static int already_warned = 0; - if (already_warned++) - return; - - if (flag_alt_external_templates) - { - struct tinst_level *til = tinst_for_decl (); - int sl = lineno; - char *sf = input_filename; - - if (til) - { - lineno = til->line; - input_filename = til->file; - } - cp_warning ("template `%#D' instantiated in file without #pragma interface", - decl); - lineno = sl; - input_filename = sf; - } - else - cp_warning_at ("template `%#D' defined in file without #pragma interface", - decl); -} - -/* A subroutine of the parser, to handle a component list. */ - -void -grok_x_components (specs) - tree specs; -{ - struct pending_inline **p; - tree t; - - specs = strip_attrs (specs); - - check_tag_decl (specs); - t = groktypename (build_decl_list (specs, NULL_TREE)); - - /* The only case where we need to do anything additional here is an - anonymous union field, e.g.: `struct S { union { int i; }; };'. */ - if (t == NULL_TREE || !ANON_UNION_TYPE_P (t)) - return; - - fixup_anonymous_union (t); - finish_member_declaration (build_lang_field_decl (FIELD_DECL, - NULL_TREE, - t)); - - /* Ignore any inline function definitions in the anonymous union - since an anonymous union may not have function members. */ - p = &pending_inlines; - for (; *p; *p = (*p)->next) - if (DECL_CONTEXT ((*p)->fndecl) != t) - break; -} - -/* Constructors for types with virtual baseclasses need an "in-charge" flag - saying whether this constructor is responsible for initialization of - virtual baseclasses or not. All destructors also need this "in-charge" - flag, which additionally determines whether or not the destructor should - free the memory for the object. - - This function adds the "in-charge" flag to member function FN if - appropriate. It is called from grokclassfn and tsubst. - FN must be either a constructor or destructor. */ - -void -maybe_retrofit_in_chrg (fn) - tree fn; -{ - tree basetype, arg_types, parms, parm, fntype; - - if (DECL_CONSTRUCTOR_P (fn) - && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn)) - && ! DECL_CONSTRUCTOR_FOR_VBASE_P (fn)) - /* OK */; - else if (! DECL_CONSTRUCTOR_P (fn) - && TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE) - /* OK */; - else - return; - - if (DECL_CONSTRUCTOR_P (fn)) - DECL_CONSTRUCTOR_FOR_VBASE_P (fn) = 1; - - /* First add it to DECL_ARGUMENTS... */ - parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); - /* Mark the artificial `__in_chrg' parameter as "artificial". */ - SET_DECL_ARTIFICIAL (parm); - DECL_ARG_TYPE (parm) = integer_type_node; - TREE_READONLY (parm) = 1; - parms = DECL_ARGUMENTS (fn); - TREE_CHAIN (parm) = TREE_CHAIN (parms); - TREE_CHAIN (parms) = parm; - - /* ...and then to TYPE_ARG_TYPES. */ - arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); - basetype = TREE_TYPE (TREE_VALUE (arg_types)); - arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types)); - fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), - arg_types); - if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) - fntype = build_exception_variant (fntype, - TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))); - TREE_TYPE (fn) = fntype; -} - -/* 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, function, flags, quals) - tree ctype, function; - enum overload_flags flags; - tree quals; -{ - tree fn_name = DECL_NAME (function); - tree arg_types; - tree parm; - tree qualtype; - - if (fn_name == NULL_TREE) - { - error ("name missing for member function"); - fn_name = get_identifier ("<anonymous>"); - DECL_NAME (function) = fn_name; - } - - if (quals) - qualtype = grok_method_quals (ctype, function, quals); - else - qualtype = ctype; - - 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); - int constp = 1; - - if ((flag_this_is_variable > 0) - && (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))) - constp = 0; - - parm = build_decl (PARM_DECL, this_identifier, type); - /* Mark the artificial `this' parameter as "artificial". */ - SET_DECL_ARTIFICIAL (parm); - 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 (constp) - TREE_READONLY (parm) = 1; - TREE_CHAIN (parm) = last_function_parms; - last_function_parms = parm; - } - - DECL_ARGUMENTS (function) = last_function_parms; - /* First approximations. */ - DECL_CONTEXT (function) = ctype; - DECL_CLASS_CONTEXT (function) = ctype; - - if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function)) - { - maybe_retrofit_in_chrg (function); - arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); - } - - if (flags == DTOR_FLAG) - { - DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype); - TYPE_HAS_DESTRUCTOR (ctype) = 1; - } - else - set_mangled_name_for_decl (function); -} - -/* Work on the expr used by alignof (this is only called by the parser). */ - -tree -grok_alignof (expr) - tree expr; -{ - tree best, t; - int bestalign; - - if (processing_template_decl) - return build_min (ALIGNOF_EXPR, sizetype, expr); - - if (TREE_CODE (expr) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1))) - error ("`__alignof__' applied to a bit-field"); - - if (TREE_CODE (expr) == INDIRECT_REF) - { - best = t = TREE_OPERAND (expr, 0); - 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; - } - return 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 (expr) == COMPOUND_EXPR - && (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)) - expr = default_conversion (expr); - return c_alignof (TREE_TYPE (expr)); - } -} - -/* Create an ARRAY_REF, checking for the user doing things backwards - along the way. */ - -tree -grok_array_decl (array_expr, index_exp) - tree array_expr, index_exp; -{ - tree type = TREE_TYPE (array_expr); - tree p1, p2, i1, i2; - - if (type == error_mark_node || index_exp == error_mark_node) - return error_mark_node; - if (processing_template_decl) - return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE, - array_expr, index_exp); - - 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?"); - return NULL_TREE; - } - - if (TREE_CODE (type) == OFFSET_TYPE - || TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); - - /* If they have an `operator[]', use that. */ - if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp))) - return build_opfncall (ARRAY_REF, LOOKUP_NORMAL, - array_expr, index_exp, NULL_TREE); - - /* Otherwise, create an ARRAY_REF for a pointer or array type. It - is a little-known fact that, if `a' is an array and `i' is an - int, you can write `i[a]', which means the same thing as `a[i]'. */ - - if (TREE_CODE (type) == ARRAY_TYPE) - p1 = array_expr; - else - p1 = build_expr_type_conversion (WANT_POINTER, array_expr, 0); - - if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE) - p2 = index_exp; - else - p2 = build_expr_type_conversion (WANT_POINTER, index_exp, 0); - - i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, 0); - i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, 0); - - if ((p1 && i2) && (i1 && p2)) - error ("ambiguous conversion for array subscript"); - - if (p1 && i2) - array_expr = p1, index_exp = i2; - else if (i1 && p2) - array_expr = p2, index_exp = i1; - else - { - cp_error ("invalid types `%T[%T]' for array subscript", - type, TREE_TYPE (index_exp)); - return error_mark_node; - } - - if (array_expr == error_mark_node || index_exp == error_mark_node) - error ("ambiguous conversion for array subscript"); - - return build_array_ref (array_expr, index_exp); -} - -/* Given the cast expression EXP, checking out its validity. Either return - an error_mark_node if there was an unavoidable error, return a cast to - void for trying to delete a pointer w/ the value 0, or return the - call to delete. If DOING_VEC is 1, we handle things differently - for doing an array delete. If DOING_VEC is 2, they gave us the - array size as an argument to delete. - Implements ARM $5.3.4. This is called from the parser. */ - -tree -delete_sanity (exp, size, doing_vec, use_global_delete) - tree exp, size; - int doing_vec, use_global_delete; -{ - tree t, type; - /* For a regular vector delete (aka, no size argument) we will pass - this down as a NULL_TREE into build_vec_delete. */ - tree maxindex = NULL_TREE; - - if (exp == error_mark_node) - return exp; - - if (processing_template_decl) - { - t = build_min (DELETE_EXPR, void_type_node, exp, size); - DELETE_EXPR_USE_GLOBAL (t) = use_global_delete; - DELETE_EXPR_USE_VEC (t) = doing_vec; - return t; - } - - if (TREE_CODE (exp) == OFFSET_REF) - exp = resolve_offset_ref (exp); - exp = convert_from_reference (exp); - t = stabilize_reference (exp); - t = build_expr_type_conversion (WANT_POINTER, t, 1); - - if (t == NULL_TREE || t == error_mark_node) - { - cp_error ("type `%#T' argument given to `delete', expected pointer", - TREE_TYPE (exp)); - return error_mark_node; - } - - if (doing_vec == 2) - { - maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1); - pedwarn ("anachronistic use of array size in vector delete"); - } - - type = TREE_TYPE (t); - - /* As of Valley Forge, you can delete a pointer to const. */ - - /* You can't delete functions. */ - if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) - { - error ("cannot delete a function"); - return error_mark_node; - } - - /* An array can't have been allocated by new, so complain. */ - if (TREE_CODE (t) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL - && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == ARRAY_TYPE) - cp_warning ("deleting array `%#D'", TREE_OPERAND (t, 0)); - - /* Deleting a pointer with the value zero is valid and has no effect. */ - if (integer_zerop (t)) - return build1 (NOP_EXPR, void_type_node, t); - - if (doing_vec) - return build_vec_delete (t, maxindex, integer_one_node, - integer_zero_node, use_global_delete); - else - { - if (IS_AGGR_TYPE (TREE_TYPE (type)) - && TYPE_GETS_REG_DELETE (TREE_TYPE (type))) - { - /* Only do access checking here; we'll be calling op delete - from the destructor. */ - tree tmp = build_op_delete_call (DELETE_EXPR, t, size_zero_node, - LOOKUP_NORMAL, NULL_TREE); - if (tmp == error_mark_node) - return error_mark_node; - } - - return build_delete (type, t, integer_three_node, - LOOKUP_NORMAL, use_global_delete); - } -} - -/* Report an error if the indicated template declaration is not the - sort of thing that should be a member template. */ - -void -check_member_template (tmpl) - tree tmpl; -{ - tree decl; - - my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); - decl = DECL_TEMPLATE_RESULT (tmpl); - - if (TREE_CODE (decl) == FUNCTION_DECL - || (TREE_CODE (decl) == TYPE_DECL - && IS_AGGR_TYPE (TREE_TYPE (decl)))) - { - if (current_function_decl) - /* 14.5.2.2 [temp.mem] - - A local class shall not have member templates. */ - cp_error ("declaration of member template `%#D' in local class", - decl); - - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl)) - { - /* 14.5.2.3 [temp.mem] - - A member function template shall not be virtual. */ - cp_error - ("invalid use of `virtual' in template declaration of `%#D'", - decl); - DECL_VIRTUAL_P (decl) = 0; - } - - /* The debug-information generating code doesn't know what to do - with member templates. */ - DECL_IGNORED_P (tmpl) = 1; - } - else - cp_error ("template declaration of `%#D'", decl); -} - -/* Return true iff TYPE is a valid Java parameter or return type. */ - -int -acceptable_java_type (type) - tree type; -{ - if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type)) - return 1; - if (TREE_CODE (type) == POINTER_TYPE) - { - type = TREE_TYPE (type); - if (TREE_CODE (type) == RECORD_TYPE) - { - tree args; int i; - if (! TYPE_FOR_JAVA (type)) - return 0; - if (! CLASSTYPE_TEMPLATE_INFO (type)) - return 1; - args = CLASSTYPE_TI_ARGS (type); - i = TREE_VEC_LENGTH (args); - while (--i >= 0) - { - type = TREE_VEC_ELT (args, i); - if (TREE_CODE (type) == POINTER_TYPE) - type = TREE_TYPE (type); - if (! TYPE_FOR_JAVA (type)) - return 0; - } - return 1; - } - } - return 0; -} - -/* For a METHOD in a Java class CTYPE, return 1 if - the parameter and return types are valid Java types. - Otherwise, print appropriate error messages, and return 0. */ - -int -check_java_method (method) - tree method; -{ - int jerr = 0; - tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (method)); - tree ret_type = TREE_TYPE (TREE_TYPE (method)); - if (! acceptable_java_type (ret_type)) - { - cp_error ("Java method '%D' has non-Java return type `%T'", - method, ret_type); - jerr++; - } - for (; arg_types != NULL_TREE; arg_types = TREE_CHAIN (arg_types)) - { - tree type = TREE_VALUE (arg_types); - if (! acceptable_java_type (type)) - { - cp_error ("Java method '%D' has non-Java parameter type `%T'", - method, type); - jerr++; - } - } - return jerr ? 0 : 1; -} - -/* Sanity check: report error if this function FUNCTION is not - really a member of the class (CTYPE) it is supposed to belong to. - CNAME is the same here as it is for grokclassfn above. */ - -tree -check_classfn (ctype, function) - tree ctype, function; -{ - tree fn_name = DECL_NAME (function); - tree fndecl, fndecls; - tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype)); - tree *methods = 0; - tree *end = 0; - tree templates = NULL_TREE; - - 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 == DECL_NAME (OVL_CURRENT (*methods)) - && DECL_CONSTRUCTOR_P (function)) - goto got_it; - if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods)) - && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))) - goto got_it; - - while (++methods != end && *methods) - { - fndecl = *methods; - if (fn_name == DECL_NAME (OVL_CURRENT (*methods))) - { - got_it: - for (fndecls = *methods; fndecls != NULL_TREE; - fndecls = OVL_NEXT (fndecls)) - { - fndecl = OVL_CURRENT (fndecls); - /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL, or - for a for member function of a template class, is - not mangled, so the check below does not work - correctly in that case. Since mangled destructor - names do not include the type of the arguments, - we can't use this short-cut for them, either. - (It's not legal to declare arguments for a - destructor, but some people try.) */ - if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)) - && (DECL_ASSEMBLER_NAME (function) - != DECL_NAME (function)) - && (DECL_ASSEMBLER_NAME (fndecl) - != DECL_NAME (fndecl)) - && (DECL_ASSEMBLER_NAME (function) - == DECL_ASSEMBLER_NAME (fndecl))) - return fndecl; - - /* We cannot simply call decls_match because this - doesn't work for static member functions that are - pretending to be methods, and because the name - may have been changed by asm("new_name"). */ - if (DECL_NAME (function) == DECL_NAME (fndecl)) - { - tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function)); - tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - - /* Get rid of the this parameter on functions that become - static. */ - if (DECL_STATIC_FUNCTION_P (fndecl) - && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) - p1 = TREE_CHAIN (p1); - - if (same_type_p (TREE_TYPE (TREE_TYPE (function)), - TREE_TYPE (TREE_TYPE (fndecl))) - && compparms (p1, p2) - && (DECL_TEMPLATE_SPECIALIZATION (function) - == DECL_TEMPLATE_SPECIALIZATION (fndecl)) - && (!DECL_TEMPLATE_SPECIALIZATION (function) - || (DECL_TI_TEMPLATE (function) - == DECL_TI_TEMPLATE (fndecl)))) - return fndecl; - - if (is_member_template (fndecl)) - /* This function might be an instantiation - or specialization of fndecl. */ - templates = - scratch_tree_cons (NULL_TREE, fndecl, templates); - } - } - break; /* loser */ - } - else if (TREE_CODE (OVL_CURRENT (fndecl)) == TEMPLATE_DECL - && DECL_CONV_FN_P (OVL_CURRENT (fndecl)) - && DECL_CONV_FN_P (function)) - /* The method in the class is a member template - conversion operator. We are declaring another - conversion operator. It is possible that even though - the names don't match, there is some specialization - occurring. */ - templates = - scratch_tree_cons (NULL_TREE, fndecl, templates); - } - } - - if (templates) - /* This function might be an instantiation or a specialization. - We should verify that this is possible. For now, we simply - return NULL_TREE, which lets the caller know that this function - is new, but we don't print an error message. */ - return NULL_TREE; - - if (methods != end && *methods) - { - tree fndecl = *methods; - cp_error ("prototype for `%#D' does not match any in class `%T'", - function, ctype); - cp_error_at ("candidate%s: %+#D", OVL_NEXT (fndecl) ? "s are" : " is", - OVL_CURRENT (fndecl)); - while (fndecl = OVL_NEXT (fndecl), fndecl) - cp_error_at (" %#D", OVL_CURRENT(fndecl)); - } - else - { - methods = 0; - if (TYPE_SIZE (ctype) == 0) - incomplete_type_error (function, ctype); - else - cp_error ("no `%#D' member function declared in class `%T'", - function, ctype); - } - - /* If we did not find the method in the class, add it to avoid - spurious errors (unless the CTYPE is not yet defined, in which - case we'll only confuse ourselves when the function is declared - properly within the class. */ - if (TYPE_SIZE (ctype)) - add_method (ctype, methods, function); - return NULL_TREE; -} - -/* 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, init, asmspec_tree, attrlist) - tree declarator, declspecs, init, asmspec_tree, attrlist; -{ - register tree value; - char *asmspec = 0; - int flags = LOOKUP_ONLYCONVERTING; - - /* 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); - flags = 0; - } - - if (declspecs == NULL_TREE - && TREE_CODE (declarator) == SCOPE_REF - && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE) - { - /* Access declaration */ - if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0)))) - ; - else if (TREE_COMPLEXITY (declarator) == current_class_depth) - pop_nested_class (1); - return do_class_using_decl (declarator); - } - - 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, NULL_TREE); - if (! value || value == error_mark_node) - /* friend or constructor went bad. */ - return value; - - /* 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")) - cp_error ("member `%D' conflicts with virtual function table field name", - value); - - /* Stash away type declarations. */ - if (TREE_CODE (value) == TYPE_DECL) - { - DECL_NONLOCAL (value) = 1; - DECL_CONTEXT (value) = current_class_type; - DECL_CLASS_CONTEXT (value) = current_class_type; - - /* Now that we've updated the context, we need to remangle the - name for this TYPE_DECL. */ - DECL_ASSEMBLER_NAME (value) = DECL_NAME (value); - if (!uses_template_parms (value)) - DECL_ASSEMBLER_NAME (value) = - get_identifier (build_overload_name (TREE_TYPE (value), 1, 1)); - - pushdecl_class_level (value); - return value; - } - - if (IS_SIGNATURE (current_class_type) - && TREE_CODE (value) != FUNCTION_DECL) - { - error ("field declaration not allowed in signature"); - return void_type_node; - } - - if (DECL_IN_AGGR_P (value)) - { - cp_error ("`%D' is already defined in `%T'", value, - DECL_CONTEXT (value)); - return void_type_node; - } - - if (asmspec_tree) - asmspec = TREE_STRING_POINTER (asmspec_tree); - - if (init) - { - if (IS_SIGNATURE (current_class_type) - && TREE_CODE (value) == FUNCTION_DECL) - { - error ("function declarations cannot have initializers in signature"); - init = NULL_TREE; - } - else if (TREE_CODE (value) == FUNCTION_DECL) - { - grok_function_init (value, init); - init = NULL_TREE; - } - else if (pedantic && TREE_CODE (value) != VAR_DECL) - /* Already complained in grokdeclarator. */ - 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 (processing_template_decl) - ; - 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 cp_finish_decl. */ - push_obstacks_nochange (); - - if (processing_template_decl && ! current_function_decl - && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL)) - value = push_template_decl (value); - - check_template_shadow (value); - - if (attrlist) - cplus_decl_attributes (value, TREE_PURPOSE (attrlist), - TREE_VALUE (attrlist)); - - if (TREE_CODE (value) == VAR_DECL) - { - my_friendly_assert (TREE_PUBLIC (value), 0); - - /* We cannot call pushdecl here, because that would - fill in the value of our TREE_CHAIN. Instead, we - modify cp_finish_decl to do the right thing, namely, to - put this decl out straight away. */ - /* current_class_type can be NULL_TREE in case of error. */ - if (asmspec == 0 && current_class_type) - { - TREE_PUBLIC (value) = 1; - DECL_INITIAL (value) = error_mark_node; - DECL_ASSEMBLER_NAME (value) - = build_static_name (current_class_type, DECL_NAME (value)); - } - if (! processing_template_decl) - 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 (CP_TYPE_CONST_P (TREE_TYPE (value)) && init == 0) - TREE_USED (value) = 1; - DECL_INITIAL (value) = init; - DECL_IN_AGGR_P (value) = 1; - DECL_CONTEXT (value) = current_class_type; - DECL_CLASS_CONTEXT (value) = current_class_type; - - cp_finish_decl (value, init, asmspec_tree, 1, flags); - pushdecl_class_level (value); - return value; - } - if (TREE_CODE (value) == FIELD_DECL) - { - if (asmspec) - { - /* This must override the asm specifier which was placed - by grokclassfn. Lay this out fresh. */ - DECL_RTL (value) = NULL_RTX; - DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec); - } - if (DECL_INITIAL (value) == error_mark_node) - init = error_mark_node; - cp_finish_decl (value, init, asmspec_tree, 1, flags); - DECL_INITIAL (value) = init; - DECL_IN_AGGR_P (value) = 1; - return value; - } - if (TREE_CODE (value) == FUNCTION_DECL) - { - if (asmspec) - { - /* This must override the asm specifier which was placed - by grokclassfn. Lay this out fresh. */ - DECL_RTL (value) = NULL_RTX; - DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec); - } - cp_finish_decl (value, init, asmspec_tree, 1, flags); - - /* Pass friends back this way. */ - if (DECL_FRIEND_P (value)) - return void_type_node; - -#if 0 /* Just because a fn is declared doesn't mean we'll try to define it. */ - if (current_function_decl && ! IS_SIGNATURE (current_class_type)) - cp_error ("method `%#D' of local class must be defined in class body", - value); -#endif - - 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) - { - cp_error ("cannot declare `%D' to be a bitfield type", value); - return NULL_TREE; - } - - /* Usually, finish_struct_1 catches bitifields with invalid types. - But, in the case of bitfields with function type, we confuse - ourselves into thinking they are member functions, so we must - check here. */ - if (TREE_CODE (value) == FUNCTION_DECL) - { - cp_error ("cannot declare bitfield `%D' with funcion type", - DECL_NAME (value)); - return NULL_TREE; - } - - if (IS_SIGNATURE (current_class_type)) - { - error ("field declaration not allowed in signature"); - return void_type_node; - } - - if (DECL_IN_AGGR_P (value)) - { - cp_error ("`%D' is already defined in the class %T", value, - DECL_CONTEXT (value)); - return void_type_node; - } - - GNU_xref_member (current_class_name, value); - - if (TREE_STATIC (value)) - { - cp_error ("static member `%D' cannot be a bitfield", value); - return NULL_TREE; - } - cp_finish_decl (value, NULL_TREE, NULL_TREE, 0, 0); - - if (width != error_mark_node) - { - constant_expression_warning (width); - DECL_INITIAL (value) = width; - SET_DECL_C_BIT_FIELD (value); - } - - DECL_IN_AGGR_P (value) = 1; - return value; -} - -tree -grokoptypename (declspecs, declarator) - tree declspecs, declarator; -{ - tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE); - return build_typename_overload (t); -} - -/* 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; - }; - -*/ - -int -copy_assignment_arg_p (parmtype, virtualp) - tree parmtype; - int virtualp ATTRIBUTE_UNUSED; -{ - if (current_class_type == NULL_TREE) - return 0; - - if (TREE_CODE (parmtype) == REFERENCE_TYPE) - parmtype = TREE_TYPE (parmtype); - - if ((TYPE_MAIN_VARIANT (parmtype) == current_class_type) -#if 0 - /* Non-standard hack to support old Booch components. */ - || (! virtualp && DERIVED_FROM_P (parmtype, current_class_type)) -#endif - ) - return 1; - - return 0; -} - -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); - - if (TREE_CODE (type) == FUNCTION_TYPE) - cp_error ("initializer specified for non-member function `%D'", decl); -#if 0 - /* We'll check for this in finish_struct_1. */ - else if (DECL_VINDEX (decl) == NULL_TREE) - cp_error ("initializer specified for non-virtual method `%D'", decl); -#endif - else if (integer_zerop (init)) - { -#if 0 - /* Mark this function as being "defined". */ - DECL_INITIAL (decl) = error_mark_node; - /* pure virtual destructors must be defined. */ - /* pure virtual needs to be defined (as abort) only when put in - vtbl. For wellformed call, it should be itself. pr4737 */ - if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))) - { - extern tree abort_fndecl; - /* Give this node rtl from `abort'. */ - DECL_RTL (decl) = DECL_RTL (abort_fndecl); - } -#endif - DECL_ABSTRACT_VIRTUAL_P (decl) = 1; - if (DECL_NAME (decl) == ansi_opname [(int) MODIFY_EXPR]) - { - tree parmtype - = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))); - - if (copy_assignment_arg_p (parmtype, 1)) - TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1; - } - } - else - cp_error ("invalid initializer for virtual method `%D'", decl); -} - -void -cplus_decl_attributes (decl, attributes, prefix_attributes) - tree decl, attributes, prefix_attributes; -{ - if (decl == NULL_TREE || decl == void_type_node) - return; - - if (TREE_CODE (decl) == TEMPLATE_DECL) - decl = DECL_TEMPLATE_RESULT (decl); - - decl_attributes (decl, attributes, prefix_attributes); - - if (TREE_CODE (decl) == TYPE_DECL) - SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (decl), TREE_TYPE (decl)); -} - -/* CONSTRUCTOR_NAME: - Return the name for the constructor (or destructor) for the - specified class. Argument can be RECORD_TYPE, TYPE_DECL, or - IDENTIFIER_NODE. When given a template, this routine doesn't - lose the specialization. */ - -tree -constructor_name_full (thing) - tree thing; -{ - if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM - || TREE_CODE (thing) == TEMPLATE_TEMPLATE_PARM - || TREE_CODE (thing) == TYPENAME_TYPE) - thing = TYPE_NAME (thing); - else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing))) - { - if (TYPE_WAS_ANONYMOUS (thing) && TYPE_HAS_CONSTRUCTOR (thing)) - thing = DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (thing), 0))); - else - thing = TYPE_NAME (thing); - } - if (TREE_CODE (thing) == TYPE_DECL - || (TREE_CODE (thing) == TEMPLATE_DECL - && TREE_CODE (DECL_TEMPLATE_RESULT (thing)) == TYPE_DECL)) - thing = DECL_NAME (thing); - my_friendly_assert (TREE_CODE (thing) == IDENTIFIER_NODE, 197); - return thing; -} - -/* CONSTRUCTOR_NAME: - Return the name for the constructor (or destructor) for the - specified class. Argument can be RECORD_TYPE, TYPE_DECL, or - IDENTIFIER_NODE. When given a template, return the plain - unspecialized name. */ - -tree -constructor_name (thing) - tree thing; -{ - tree t; - thing = constructor_name_full (thing); - t = IDENTIFIER_TEMPLATE (thing); - if (!t) - return thing; - return 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 tree base_init_expr; - - if (base_init_expr == 0 - && DECL_CONSTRUCTOR_P (current_function_decl)) - { - if (processing_template_decl) - add_tree (build_min_nt - (CTOR_INITIALIZER, - current_member_init_list, current_base_init_list)); - else - emit_base_init (current_class_type, 0); - } -} - -/* Record the existence of an addressable inline function. */ - -void -mark_inline_for_output (decl) - tree decl; -{ - decl = DECL_MAIN_VARIANT (decl); - if (DECL_SAVED_INLINE (decl)) - return; - my_friendly_assert (TREE_PERMANENT (decl), 363); - DECL_SAVED_INLINE (decl) = 1; -#if 0 - 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; - } -#endif - saved_inlines = perm_tree_cons (NULL_TREE, decl, saved_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 = toplevel_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; - DECL_ARTIFICIAL (decl) = 1; - - /* 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; -{ - tree decl; - - decl = build_decl (VAR_DECL, NULL_TREE, type); - TREE_USED (decl) = 1; - DECL_REGISTER (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - - DECL_RTL (decl) = assign_temp (type, 2, 0, 1); - /* We can expand these without fear, since they cannot need - constructors or destructors. */ - expand_expr (build_modify_expr (decl, INIT_EXPR, init), - NULL_RTX, VOIDmode, 0); - - return decl; -} - -/* Hunts through the global anonymous union ANON_DECL, building - appropriate VAR_DECLs. Stores cleanups on the list of ELEMS, and - returns a VAR_DECL whose size is the same as the size of the - ANON_DECL, if one is available. */ - -static tree -build_anon_union_vars (anon_decl, elems, static_p, external_p) - tree anon_decl; - tree* elems; - int static_p; - int external_p; -{ - tree type = TREE_TYPE (anon_decl); - tree main_decl = NULL_TREE; - tree field; - - for (field = TYPE_FIELDS (type); - field != NULL_TREE; - field = TREE_CHAIN (field)) - { - tree decl; - - if (DECL_ARTIFICIAL (field)) - continue; - if (TREE_CODE (field) != FIELD_DECL) - { - cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members", - field); - continue; - } - - if (TREE_PRIVATE (field)) - cp_pedwarn_at ("private member `%#D' in anonymous union", field); - else if (TREE_PROTECTED (field)) - cp_pedwarn_at ("protected member `%#D' in anonymous union", field); - - if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - { - decl = build_anon_union_vars (field, elems, static_p, external_p); - if (!decl) - continue; - } - else if (DECL_NAME (field) == NULL_TREE) - continue; - else - { - 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) = 0; - TREE_STATIC (decl) = static_p; - DECL_EXTERNAL (decl) = external_p; - decl = pushdecl (decl); - DECL_INITIAL (decl) = NULL_TREE; - } - - /* Only write out one anon union element--choose the one that - can hold them all. */ - if (main_decl == NULL_TREE - && simple_cst_equal (DECL_SIZE (decl), - DECL_SIZE (anon_decl)) == 1) - main_decl = decl; - else - /* ??? This causes there to be no debug info written out - about this decl. */ - TREE_ASM_WRITTEN (decl) = 1; - - if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - /* The remainder of the processing was already done in the - recursive call. */ - continue; - - /* If there's a cleanup to do, it belongs in the - TREE_PURPOSE of the following TREE_LIST. */ - *elems = scratch_tree_cons (NULL_TREE, decl, *elems); - TREE_TYPE (*elems) = type; - } - - return main_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 elems = NULL_TREE; - tree main_decl; - 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 (TYPE_FIELDS (type) == NULL_TREE) - return; - - if (public_p) - { - error ("global anonymous unions must be declared static"); - return; - } - - main_decl = build_anon_union_vars (anon_union_decl, &elems, - static_p, external_p); - - if (main_decl == NULL_TREE) - { - warning ("anonymous union with no members"); - return; - } - - if (static_p) - { - make_decl_rtl (main_decl, 0, toplevel_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); -} - -/* 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 minus one, or put another way, it is the maximum subscript - used 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 - TYPE_STUB_DECL (type) = TYPE_NAME (type); - 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. */ - -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 (! same_type_p (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 (! same_type_p (TREE_VALUE (TYPE_ARG_TYPES (type)), 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; -#if 0 - e3 = 0; -#endif - 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 - || ! same_type_p (TREE_VALUE (arg_types), ptr_type_node)) - e2 = 1, error ("`operator delete' takes type `void *' as first parameter"); - -#if 0 - 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 (! same_type_p (t2, 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 = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - else - arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types)); - } - else e3 |= e1; -#endif - - if (e2) - arg_types = tree_cons (NULL_TREE, ptr_type_node, - arg_types ? TREE_CHAIN (arg_types): NULL_TREE); - if (e2 || e1) - type = build_function_type (void_type_node, arg_types); - - return type; -} - -extern tree abort_fndecl; - -static void -mark_vtable_entries (decl) - tree decl; -{ - tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl)); - - if (flag_rtti) - { - tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (TREE_CHAIN (entries)) - : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries))); - tree fn = TREE_OPERAND (fnaddr, 0); - TREE_ADDRESSABLE (fn) = 1; - mark_used (fn); - } - skip_rtti_stuff (&entries); - - for (; entries; entries = TREE_CHAIN (entries)) - { - tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) - : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries))); - tree fn = TREE_OPERAND (fnaddr, 0); - TREE_ADDRESSABLE (fn) = 1; - if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn)) - { - TREE_OPERAND (fnaddr, 0) = fn = copy_node (fn); - DECL_RTL (fn) = DECL_RTL (abort_fndecl); - mark_used (abort_fndecl); - } - if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn)) - { - DECL_EXTERNAL (fn) = 0; - emit_thunk (fn); - } - mark_used (fn); - } -} - -/* Set DECL up to have the closest approximation of "initialized common" - linkage available. */ - -void -comdat_linkage (decl) - tree decl; -{ - if (flag_weak) - make_decl_one_only (decl); - else - TREE_PUBLIC (decl) = 0; - - if (DECL_LANG_SPECIFIC (decl)) - DECL_COMDAT (decl) = 1; -} - -/* For win32 we also want to put explicit instantiations in - linkonce sections, so that they will be merged with implicit - instantiations; otherwise we get duplicate symbol errors. */ - -void -maybe_make_one_only (decl) - tree decl; -{ - /* This is not necessary on targets that support weak symbols, because - the implicit instantiations will defer to the explicit one. */ - if (! supports_one_only () || SUPPORTS_WEAK) - return; - - /* We can't set DECL_COMDAT on functions, or finish_file will think - we can get away with not emitting them if they aren't used. - We can't use make_decl_one_only for variables, because their - DECL_INITIAL may not have been set properly yet. */ - - if (TREE_CODE (decl) == FUNCTION_DECL) - make_decl_one_only (decl); - else - comdat_linkage (decl); -} - -/* Set TREE_PUBLIC and/or DECL_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. */ - -void -import_export_vtable (decl, type, final) - tree decl, type; - int final; -{ - if (DECL_INTERFACE_KNOWN (decl)) - return; - - if (TYPE_FOR_JAVA (type)) - { - TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = 1; - DECL_INTERFACE_KNOWN (decl) = 1; - } - else if (CLASSTYPE_INTERFACE_KNOWN (type)) - { - TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type); - DECL_INTERFACE_KNOWN (decl) = 1; - } - else - { - /* We can only wait to decide if we have real non-inline virtual - functions in our class, or if we come from a template. */ - - int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type); - - if (! found && ! final) - { - tree method; - for (method = TYPE_METHODS (type); method != NULL_TREE; - method = TREE_CHAIN (method)) - if (DECL_VINDEX (method) != NULL_TREE - && ! DECL_THIS_INLINE (method) - && ! DECL_ABSTRACT_VIRTUAL_P (method)) - { - found = 1; - break; - } - } - - if (final || ! found) - { - comdat_linkage (decl); - DECL_EXTERNAL (decl) = 0; - } - else - { - TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = 1; - } - } -} - -/* Determine whether or not we want to specifically import or export CTYPE, - using various heuristics. */ - -void -import_export_class (ctype) - tree ctype; -{ - /* -1 for imported, 1 for exported. */ - int import_export = 0; - - if (CLASSTYPE_INTERFACE_KNOWN (ctype)) - return; - -#ifdef VALID_MACHINE_TYPE_ATTRIBUTE - /* FIXME this should really use some sort of target-independent macro. */ - if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype))) - import_export = -1; - else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype))) - import_export = 1; -#endif - - /* If we got -fno-implicit-templates, we import template classes that - weren't explicitly instantiated. */ - if (import_export == 0 - && CLASSTYPE_IMPLICIT_INSTANTIATION (ctype) - && ! flag_implicit_templates) - import_export = -1; - - /* Base our import/export status on that of the first non-inline, - non-abstract virtual function, if any. */ - if (import_export == 0 - && TYPE_VIRTUAL_P (ctype) - && ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)) - { - tree method; - for (method = TYPE_METHODS (ctype); method != NULL_TREE; - method = TREE_CHAIN (method)) - { - if (DECL_VINDEX (method) != NULL_TREE - && !DECL_THIS_INLINE (method) - && !DECL_ABSTRACT_VIRTUAL_P (method)) - { - import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1); - break; - } - } - } - -#ifdef MULTIPLE_SYMBOL_SPACES - if (import_export == -1) - import_export = 0; -#endif - - if (import_export) - { - SET_CLASSTYPE_INTERFACE_KNOWN (ctype); - CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = (import_export > 0); - CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0); - } -} - -/* We need to describe to the assembler the relationship between - a vtable and the vtable of the parent class. */ - -static void -output_vtable_inherit (vars) - tree vars; -{ - tree parent; - rtx op[2]; - - op[0] = XEXP (DECL_RTL (vars), 0); /* strip the mem ref */ - - parent = binfo_for_vtable (vars); - - if (parent == TYPE_BINFO (DECL_CONTEXT (vars))) - op[1] = const0_rtx; - else if (parent) - { - parent = TYPE_BINFO_VTABLE (BINFO_TYPE (parent)); - op[1] = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */ - } - else - my_friendly_abort (980826); - - output_asm_insn (".vtable_inherit %c0, %c1", op); -} - -static int -finish_vtable_vardecl (prev, vars) - tree prev, vars; -{ - tree ctype = DECL_CONTEXT (vars); - import_export_class (ctype); - import_export_vtable (vars, ctype, 1); - - if (! DECL_EXTERNAL (vars) - && (DECL_INTERFACE_KNOWN (vars) - || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)) - || (hack_decl_function_context (vars) && TREE_USED (vars))) - && ! TREE_ASM_WRITTEN (vars)) - { - /* Write it out. */ - mark_vtable_entries (vars); - if (TREE_TYPE (DECL_INITIAL (vars)) == 0) - store_init_value (vars, DECL_INITIAL (vars)); - - if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG) - { - /* Mark the VAR_DECL node representing the vtable itself as a - "gratuitous" one, thereby forcing dwarfout.c to ignore it. - It is rather important that such things be ignored because - any effort to actually generate DWARF for them will run - into trouble when/if we encounter code like: - - #pragma interface - struct S { virtual void member (); }; - - because the artificial declaration of the vtable itself (as - manufactured by the g++ front end) will say that the vtable - is a static member of `S' but only *after* the debug output - for the definition of `S' has already been output. This causes - grief because the DWARF entry for the definition of the vtable - will try to refer back to an earlier *declaration* of the - vtable as a static member of `S' and there won't be one. - We might be able to arrange to have the "vtable static member" - attached to the member list for `S' before the debug info for - `S' get written (which would solve the problem) but that would - require more intrusive changes to the g++ front end. */ - - DECL_IGNORED_P (vars) = 1; - } - - /* Always make vtables weak. */ - if (flag_weak) - comdat_linkage (vars); - - rest_of_decl_compilation (vars, NULL_PTR, 1, 1); - - if (flag_vtable_gc) - output_vtable_inherit (vars); - - return 1; - } - else if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars))) - /* We don't know what to do with this one yet. */ - return 0; - - /* We know that PREV must be non-zero here. */ - TREE_CHAIN (prev) = TREE_CHAIN (vars); - return 0; -} - -static int -prune_vtable_vardecl (prev, vars) - tree prev, vars; -{ - /* We know that PREV must be non-zero here. */ - TREE_CHAIN (prev) = TREE_CHAIN (vars); - return 1; -} - -int -walk_vtables (typedecl_fn, vardecl_fn) - register void (*typedecl_fn) PROTO ((tree, tree)); - register int (*vardecl_fn) PROTO ((tree, tree)); -{ - tree prev, vars; - int flag = 0; - - for (prev = 0, vars = getdecls (); vars; vars = TREE_CHAIN (vars)) - { - register tree type = TREE_TYPE (vars); - - if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars)) - { - if (vardecl_fn) - flag |= (*vardecl_fn) (prev, vars); - - if (prev && TREE_CHAIN (prev) != vars) - continue; - } - else if (TREE_CODE (vars) == TYPE_DECL - && type != error_mark_node - && TYPE_LANG_SPECIFIC (type) - && CLASSTYPE_VSIZE (type)) - { - if (typedecl_fn) (*typedecl_fn) (prev, vars); - } - - prev = vars; - } - - return flag; -} - -static void -finish_sigtable_vardecl (prev, vars) - tree prev, vars; -{ - /* We don't need to mark sigtable entries as addressable here as is done - for vtables. Since sigtables, unlike vtables, are always written out, - that was already done in build_signature_table_constructor. */ - - rest_of_decl_compilation (vars, NULL_PTR, 1, 1); - - /* We know that PREV must be non-zero here. */ - TREE_CHAIN (prev) = TREE_CHAIN (vars); -} - -void -walk_sigtables (typedecl_fn, vardecl_fn) - register void (*typedecl_fn) PROTO((tree, tree)); - register void (*vardecl_fn) PROTO((tree, tree)); -{ - tree prev, vars; - - for (prev = 0, vars = getdecls (); vars; vars = TREE_CHAIN (vars)) - { - register tree type = TREE_TYPE (vars); - - if (TREE_CODE (vars) == TYPE_DECL - && type != error_mark_node - && IS_SIGNATURE (type)) - { - if (typedecl_fn) (*typedecl_fn) (prev, vars); - } - else if (TREE_CODE (vars) == VAR_DECL - && TREE_TYPE (vars) != error_mark_node - && IS_SIGNATURE (TREE_TYPE (vars))) - { - if (vardecl_fn) (*vardecl_fn) (prev, vars); - } - else - prev = vars; - } -} - -/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an - inline function or template instantiation at end-of-file. */ - -void -import_export_decl (decl) - tree decl; -{ - if (DECL_INTERFACE_KNOWN (decl)) - return; - - if (DECL_TEMPLATE_INSTANTIATION (decl) - || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) - { - DECL_NOT_REALLY_EXTERN (decl) = 1; - if ((DECL_IMPLICIT_INSTANTIATION (decl) - || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) - && (flag_implicit_templates - || (flag_implicit_inline_templates && DECL_THIS_INLINE (decl)))) - { - if (!TREE_PUBLIC (decl)) - /* Templates are allowed to have internal linkage. See - [basic.link]. */ - ; - else if (TREE_CODE (decl) == FUNCTION_DECL) - comdat_linkage (decl); - else - DECL_COMDAT (decl) = 1; - } - else - DECL_NOT_REALLY_EXTERN (decl) = 0; - } - else if (DECL_FUNCTION_MEMBER_P (decl)) - { - tree ctype = DECL_CLASS_CONTEXT (decl); - import_export_class (ctype); - if (CLASSTYPE_INTERFACE_KNOWN (ctype) - && (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl))) - { - DECL_NOT_REALLY_EXTERN (decl) - = ! (CLASSTYPE_INTERFACE_ONLY (ctype) - || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines)); - - /* Always make artificials weak. */ - if (DECL_ARTIFICIAL (decl) && flag_weak) - comdat_linkage (decl); - else - maybe_make_one_only (decl); - } - else - comdat_linkage (decl); - } - /* tinfo function */ - else if (DECL_ARTIFICIAL (decl) && DECL_MUTABLE_P (decl)) - { - tree ctype = TREE_TYPE (DECL_NAME (decl)); - - if (IS_AGGR_TYPE (ctype)) - import_export_class (ctype); - - if (IS_AGGR_TYPE (ctype) && CLASSTYPE_INTERFACE_KNOWN (ctype) - && TYPE_VIRTUAL_P (ctype) - /* If the type is a cv-qualified variant of a type, then we - must emit the tinfo function in this translation unit - since it will not be emitted when the vtable for the type - is output (which is when the unqualified version is - generated). */ - && ctype == TYPE_MAIN_VARIANT (ctype)) - { - DECL_NOT_REALLY_EXTERN (decl) - = ! (CLASSTYPE_INTERFACE_ONLY (ctype) - || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines)); - - /* Always make artificials weak. */ - if (flag_weak) - comdat_linkage (decl); - } - else if (TYPE_BUILT_IN (ctype) && ctype == TYPE_MAIN_VARIANT (ctype)) - DECL_NOT_REALLY_EXTERN (decl) = 0; - else - comdat_linkage (decl); - } - else - comdat_linkage (decl); - - DECL_INTERFACE_KNOWN (decl) = 1; -} - -tree -build_cleanup (decl) - tree decl; -{ - tree temp; - tree type = TREE_TYPE (decl); - - if (TREE_CODE (type) == ARRAY_TYPE) - temp = decl; - else - { - mark_addressable (decl); - temp = build1 (ADDR_EXPR, build_pointer_type (type), decl); - } - temp = build_delete (TREE_TYPE (temp), temp, - integer_two_node, - LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); - return temp; -} - -extern int parse_time, varconst_time; -extern tree pending_templates; -extern tree maybe_templates; - -static tree -get_sentry (base) - tree base; -{ - tree sname = get_id_2 ("__sn", base); - /* For struct X foo __attribute__((weak)), there is a counter - __snfoo. Since base is already an assembler name, sname should - be globally unique */ - tree sentry = IDENTIFIER_GLOBAL_VALUE (sname); - if (! sentry) - { - push_obstacks_nochange (); - end_temporary_allocation (); - sentry = build_decl (VAR_DECL, sname, integer_type_node); - TREE_PUBLIC (sentry) = 1; - DECL_ARTIFICIAL (sentry) = 1; - TREE_STATIC (sentry) = 1; - TREE_USED (sentry) = 1; - DECL_COMMON (sentry) = 1; - pushdecl_top_level (sentry); - cp_finish_decl (sentry, NULL_TREE, NULL_TREE, 0, 0); - pop_obstacks (); - } - return sentry; -} - -/* 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_initp; - -/* Set up the static_aggregates* lists for processing. Subroutine of - finish_file. Note that this function changes the format of - static_aggregates_initp, from (priority . decl) to - (priority . ((initializer . decl) ...)). */ - -static void -setup_initp () -{ - tree t, *p, next_t; - - /* First, remove any entries from static_aggregates that are also in - static_aggregates_initp, and update the entries in _initp to - include the initializer. */ - p = &static_aggregates; - for (; *p; ) - { - /* We check for symbol equivalence rather than identical decls - because decl_attributes is run before duplicate_decls. */ - for (t = static_aggregates_initp; t; t = TREE_CHAIN (t)) - if (DECL_ASSEMBLER_NAME (TREE_VALUE (t)) - == DECL_ASSEMBLER_NAME (TREE_VALUE (*p))) - break; - - if (t) - { - TREE_VALUE (t) = *p; - *p = TREE_CHAIN (*p); - TREE_CHAIN (TREE_VALUE (t)) = NULL_TREE; - } - else - p = &TREE_CHAIN (*p); - } - - /* Then, group static_aggregates_initp. After this step, there will only - be one entry for each priority, with a chain coming off it. */ - t = static_aggregates_initp; - static_aggregates_initp = NULL_TREE; - - for (; t; t = next_t) - { - next_t = TREE_CHAIN (t); - - for (p = &static_aggregates_initp; ; p = &TREE_CHAIN (*p)) - { - if (*p == NULL_TREE - || tree_int_cst_lt (TREE_PURPOSE (*p), TREE_PURPOSE (t))) - { - TREE_CHAIN (t) = *p; - *p = t; - break; - } - else if (tree_int_cst_equal (TREE_PURPOSE (*p), TREE_PURPOSE (t))) - { - TREE_CHAIN (TREE_VALUE (t)) = TREE_VALUE (*p); - TREE_VALUE (*p) = TREE_VALUE (t); - break; - } - } - } - - /* Reverse each list to preserve the order (currently reverse declaration - order, for destructors). */ - for (t = static_aggregates_initp; t; t = TREE_CHAIN (t)) - TREE_VALUE (t) = nreverse (TREE_VALUE (t)); -} - -/* Start the process of running a particular set of global constructors - or destructors. Subroutine of do_[cd]tors. */ - -static void -start_objects (method_type, initp) - int method_type, initp; -{ - tree fnname; - char type[10]; - - /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */ - - if (initp != DEFAULT_INIT_PRIORITY) - { - char joiner; - -#ifdef JOINER - joiner = JOINER; -#else - joiner = '_'; -#endif - - sprintf (type, "%c%c%.5u", method_type, joiner, initp); - } - else - sprintf (type, "%c", method_type); - - fnname = get_file_function_name_long (type); - - start_function (void_list_node, - make_call_declarator (fnname, void_list_node, NULL_TREE, - NULL_TREE), - NULL_TREE, 0); - - store_parm_decls (); - pushlevel (0); - clear_last_expr (); - push_momentary (); - expand_start_bindings (0); -} - -/* Finish the process of running a particular set of global constructors - or destructors. Subroutine of do_[cd]tors. */ - -static void -finish_objects (method_type, initp) - int method_type, initp; -{ - char *fnname; - - if (! initp) - { - tree list = (method_type == 'I' ? static_ctors : static_dtors); - - if (! current_function_decl && list) - start_objects (method_type, initp); - - for (; list; list = TREE_CHAIN (list)) - expand_expr_stmt (build_function_call (TREE_VALUE (list), NULL_TREE)); - } - - if (! current_function_decl) - return; - - fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); - - /* Finish up. */ - expand_end_bindings (getdecls (), 1, 0); - poplevel (1, 0, 0); - pop_momentary (); - finish_function (lineno, 0, 0); - - if (initp == DEFAULT_INIT_PRIORITY) - { - if (method_type == 'I') - assemble_constructor (fnname); - else - assemble_destructor (fnname); - } - -#ifdef ASM_OUTPUT_SECTION_NAME - /* If we're using init priority we can't use assemble_*tor, but on ELF - targets we can stick the references into named sections for GNU ld - to collect. */ - else - { - char buf[15]; - sprintf (buf, ".%ctors.%.5u", method_type == 'I' ? 'c' : 'd', - /* invert the numbering so the linker puts us in the proper - order; constructors are run from right to left, and the - linker sorts in increasing order. */ - MAX_INIT_PRIORITY - initp); - named_section (NULL_TREE, buf, 0); - assemble_integer (gen_rtx_SYMBOL_REF (Pmode, fnname), - POINTER_SIZE / BITS_PER_UNIT, 1); - } -#endif -} - -/* Generate a function to run a set of global destructors. START is either - NULL_TREE or a node indicating a set of destructors with the same - init priority. Subroutine of finish_file. */ - -static void -do_dtors (start) - tree start; -{ - tree vars; - int initp; - - if (start) - { - initp = TREE_INT_CST_LOW (TREE_PURPOSE (start)); - vars = TREE_VALUE (start); - } - else - { - initp = DEFAULT_INIT_PRIORITY; - vars = static_aggregates; - } - - for (; vars; vars = TREE_CHAIN (vars)) - { - tree decl = TREE_VALUE (vars); - tree type = TREE_TYPE (decl); - tree temp; - - if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars) - && ! DECL_EXTERNAL (decl)) - { - int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl) - || DECL_ONE_ONLY (decl) - || DECL_WEAK (decl))); - - if (! current_function_decl) - start_objects ('D', initp); - - /* 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); - - /* Because of: - - [class.access.spec] - - Access control for implicit calls to the constructors, - the conversion functions, or the destructor called to - create and destroy a static data member is performed as - if these calls appeared in the scope of the member's - class. - - we must convince enforce_access to let us access the - DECL. */ - if (member_p (decl)) - { - DECL_CLASS_CONTEXT (current_function_decl) - = DECL_CONTEXT (decl); - DECL_STATIC_FUNCTION_P (current_function_decl) = 1; - } - - temp = build_cleanup (decl); - - if (protect) - { - tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl)); - sentry = build_unary_op (PREDECREMENT_EXPR, sentry, 0); - sentry = build_binary_op (EQ_EXPR, sentry, integer_zero_node, 1); - expand_start_cond (sentry, 0); - } - - expand_expr_stmt (temp); - - if (protect) - expand_end_cond (); - - /* Now that we're done with DECL we don't need to pretend to - be a member of its class any longer. */ - DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE; - DECL_STATIC_FUNCTION_P (current_function_decl) = 0; - } - } - - finish_objects ('D', initp); -} - -/* Generate a function to run a set of global constructors. START is - either NULL_TREE or a node indicating a set of constructors with the - same init priority. Subroutine of finish_file. */ - -static void -do_ctors (start) - tree start; -{ - tree vars; - int initp; - - if (start) - { - initp = TREE_INT_CST_LOW (TREE_PURPOSE (start)); - vars = TREE_VALUE (start); - } - else - { - initp = DEFAULT_INIT_PRIORITY; - vars = static_aggregates; - } - - /* Reverse the list so it's in the right order for ctors. */ - vars = nreverse (vars); - - for (; vars; vars = TREE_CHAIN (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) - || DECL_EXTERNAL (decl) - || (init && TREE_CODE (init) == TREE_LIST - && value_member (error_mark_node, init))) - continue; - - if (TREE_CODE (decl) == VAR_DECL) - { - int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl) - || DECL_ONE_ONLY (decl) - || DECL_WEAK (decl))); - - if (! current_function_decl) - start_objects ('I', initp); - - /* 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); - - /* 9.5p5: The initializer of a static member of a class has - the same access rights as a member function. */ - if (member_p (decl)) - { - DECL_CLASS_CONTEXT (current_function_decl) - = DECL_CONTEXT (decl); - DECL_STATIC_FUNCTION_P (current_function_decl) = 1; - } - - if (protect) - { - tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl)); - sentry = build_unary_op (PREINCREMENT_EXPR, sentry, 0); - sentry = build_binary_op - (EQ_EXPR, sentry, integer_one_node, 1); - expand_start_cond (sentry, 0); - } - - expand_start_target_temps (); - - if (IS_AGGR_TYPE (TREE_TYPE (decl)) - || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) - expand_aggr_init (decl, init, 0); - 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, EXPAND_NORMAL); - } - else - expand_assignment (decl, init, 0, 0); - - /* The expression might have involved increments and - decrements. */ - emit_queue (); - - /* Cleanup any temporaries needed for the initial value. */ - expand_end_target_temps (); - - if (protect) - expand_end_cond (); - - DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE; - DECL_STATIC_FUNCTION_P (current_function_decl) = 0; - } - else if (decl == error_mark_node) - /* OK */; - else - my_friendly_abort (22); - } - - finish_objects ('I', initp); -} - -/* 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; - - tree fnname; - tree vars; - int needs_cleaning = 0, needs_messing_up = 0; - - at_eof = 1; - - /* Bad parse errors. Just forget about it. */ - if (! global_bindings_p () || current_class_type) - return; - - check_decl_namespace (); - - start_time = get_run_time (); - - /* Otherwise, GDB can get confused, because in only knows - about source for LINENO-1 lines. */ - lineno -= 1; - - interface_unknown = 1; - interface_only = 0; - - for (fnname = pending_templates; fnname; fnname = TREE_CHAIN (fnname)) - { - tree srcloc = TREE_PURPOSE (fnname); - tree decl = TREE_VALUE (fnname); - - input_filename = SRCLOC_FILE (srcloc); - lineno = SRCLOC_LINE (srcloc); - - if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't') - { - instantiate_class_template (decl); - if (CLASSTYPE_TEMPLATE_INSTANTIATION (decl)) - for (vars = TYPE_METHODS (decl); vars; vars = TREE_CHAIN (vars)) - if (! DECL_ARTIFICIAL (vars)) - instantiate_decl (vars); - } - else - instantiate_decl (decl); - } - - for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname)) - { - tree args, fn, decl = TREE_VALUE (fnname); - - if (DECL_INITIAL (decl)) - continue; - - fn = TREE_PURPOSE (fnname); - args = get_bindings (fn, decl, NULL_TREE); - fn = instantiate_template (fn, args); - instantiate_decl (fn); - } - - cat_namespace_levels(); - - /* Push into C language context, because that's all - we'll need here. */ - push_lang_context (lang_name_c); - -#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 - 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; - SET_DECL_ARTIFICIAL (vars); - pushdecl (vars); -#endif - - for (vars = static_aggregates; vars; vars = TREE_CHAIN (vars)) - if (! TREE_ASM_WRITTEN (TREE_VALUE (vars))) - rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1); - vars = static_aggregates; - - if (static_ctors || vars) - needs_messing_up = 1; - if (static_dtors || vars) - needs_cleaning = 1; - - setup_initp (); - - /* After setup_initp, the aggregates are listed in reverse declaration - order, for cleaning. */ - if (needs_cleaning) - { - do_dtors (NULL_TREE); - - for (vars = static_aggregates_initp; vars; vars = TREE_CHAIN (vars)) - do_dtors (vars); - } - - /* do_ctors will reverse the lists for messing up. */ - if (needs_messing_up) - { - do_ctors (NULL_TREE); - - for (vars = static_aggregates_initp; vars; vars = TREE_CHAIN (vars)) - do_ctors (vars); - } - - permanent_allocation (1); - - /* 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); - - /* Output DWARF debug information. */ -#ifdef DWARF_DEBUGGING_INFO - if (write_symbols == DWARF_DEBUG) - dwarfout_file_scope_decl (decl, 1); -#endif -#ifdef DWARF2_DEBUGGING_INFO - if (write_symbols == DWARF2_DEBUG) - dwarf2out_decl (decl); -#endif - - DECL_DEFER_OUTPUT (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; - - start_time = get_run_time (); - - if (flag_handle_signatures) - walk_sigtables ((void (*) PROTO ((tree, tree))) 0, - finish_sigtable_vardecl); - - for (fnname = saved_inlines; fnname; fnname = TREE_CHAIN (fnname)) - { - tree decl = TREE_VALUE (fnname); - import_export_decl (decl); - } - - mark_all_runtime_matches (); - - /* Now write out inline functions which had their addresses taken and - which were not declared virtual and which were not declared `extern - inline'. */ - { - int reconsider = 1; /* More may be referenced; check again */ - - while (reconsider) - { - tree *p = &saved_inlines; - reconsider = 0; - - /* We need to do this each time so that newly completed template - types don't wind up at the front of the list. Sigh. */ - vars = build_decl (TYPE_DECL, make_anon_name (), integer_type_node); - DECL_IGNORED_P (vars) = 1; - SET_DECL_ARTIFICIAL (vars); - pushdecl (vars); - - reconsider |= walk_vtables ((void (*) PROTO((tree, tree))) 0, - finish_vtable_vardecl); - - while (*p) - { - tree decl = TREE_VALUE (*p); - - if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) - && TREE_USED (decl) - && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl))) - { - if (DECL_MUTABLE_P (decl)) - synthesize_tinfo_fn (decl); - else - synthesize_method (decl); - reconsider = 1; - } - - /* Catch new template instantiations. */ - if (decl != TREE_VALUE (*p)) - continue; - - if (TREE_ASM_WRITTEN (decl) - || (DECL_SAVED_INSNS (decl) == 0 && ! DECL_ARTIFICIAL (decl))) - *p = TREE_CHAIN (*p); - else if (DECL_INITIAL (decl) == 0) - p = &TREE_CHAIN (*p); - else if ((TREE_PUBLIC (decl) && ! DECL_COMDAT (decl)) - || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) - || flag_keep_inline_functions) - { - if (DECL_NOT_REALLY_EXTERN (decl)) - { - DECL_EXTERNAL (decl) = 0; - reconsider = 1; - /* We can't inline this function after it's been - emitted. We want a variant of - output_inline_function that doesn't prevent - subsequent integration... */ - DECL_INLINE (decl) = 0; - output_inline_function (decl); - permanent_allocation (1); - } - - *p = TREE_CHAIN (*p); - } - else - p = &TREE_CHAIN (*p); - } - } - - /* It's possible that some of the remaining inlines will still be - needed. For example, a static inline whose address is used in - the initializer for a file-scope static variable will be - needed. Code in compile_file will handle this, but we mustn't - pretend that there are no definitions for the inlines, or it - won't be able to. - - FIXME: This won't catch member functions. We should really - unify this stuff with the compile_file stuff. */ - for (vars = saved_inlines; vars != NULL_TREE; vars = TREE_CHAIN (vars)) - { - tree decl = TREE_VALUE (vars); - - if (DECL_NOT_REALLY_EXTERN (decl) - && !DECL_COMDAT (decl) - && DECL_INITIAL (decl) != NULL_TREE) - DECL_EXTERNAL (decl) = 0; - } - } - - /* Now delete from the chain of variables all virtual function tables. - We output them all ourselves, because each will be treated specially. */ - - walk_vtables ((void (*) PROTO((tree, tree))) 0, - prune_vtable_vardecl); - - finish_repo (); - - this_time = get_run_time (); - parse_time -= this_time - start_time; - varconst_time += this_time - start_time; - - if (flag_detailed_statistics) - { - dump_tree_statistics (); - dump_time_statistics (); - } -} - -/* This is something of the form 'A()()()()()+1' that has turned out to be an - expr. Since it was parsed like a type, we need to wade through and fix - that. Unfortunately, since operator() is left-associative, we can't use - tail recursion. In the above example, TYPE is `A', and DECL is - `()()()()()'. - - Maybe this shouldn't be recursive, but how often will it actually be - used? (jason) */ - -tree -reparse_absdcl_as_expr (type, decl) - tree type, decl; -{ - /* do build_functional_cast (type, NULL_TREE) at bottom */ - if (TREE_OPERAND (decl, 0) == NULL_TREE) - return build_functional_cast (type, NULL_TREE); - - /* recurse */ - decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0)); - - decl = build_x_function_call (decl, NULL_TREE, current_class_ref); - - if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node) - decl = require_complete_type (decl); - - return decl; -} - -/* This is something of the form `int ((int)(int)(int)1)' that has turned - out to be an expr. Since it was parsed like a type, we need to wade - through and fix that. Since casts are right-associative, we are - reversing the order, so we don't have to recurse. - - In the above example, DECL is the `(int)(int)(int)', and EXPR is the - `1'. */ - -tree -reparse_absdcl_as_casts (decl, expr) - tree decl, expr; -{ - tree type; - - if (TREE_CODE (expr) == CONSTRUCTOR - && TREE_TYPE (expr) == 0) - { - type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1))); - decl = TREE_OPERAND (decl, 0); - - if (IS_SIGNATURE (type)) - { - error ("cast specifies signature type"); - return error_mark_node; - } - - expr = digest_init (type, expr, (tree *) 0); - if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) - { - int failure = complete_array_type (type, expr, 1); - if (failure) - my_friendly_abort (78); - } - } - - while (decl) - { - type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1))); - decl = TREE_OPERAND (decl, 0); - expr = build_c_cast (type, expr); - } - - if (warn_old_style_cast) - warning ("use of old-style cast"); - - return expr; -} - -/* Given plain tree nodes for an expression, build up the full semantics. */ - -tree -build_expr_from_tree (t) - tree t; -{ - if (t == NULL_TREE || t == error_mark_node) - return t; - - switch (TREE_CODE (t)) - { - case IDENTIFIER_NODE: - return do_identifier (t, 0, NULL_TREE); - - case LOOKUP_EXPR: - if (LOOKUP_EXPR_GLOBAL (t)) - return do_scoped_id (TREE_OPERAND (t, 0), 0); - else - return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE); - - case TEMPLATE_ID_EXPR: - return (lookup_template_function - (build_expr_from_tree (TREE_OPERAND (t, 0)), - build_expr_from_tree (TREE_OPERAND (t, 1)))); - - case INDIRECT_REF: - return build_x_indirect_ref - (build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *"); - - case CAST_EXPR: - return build_functional_cast - (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); - - case REINTERPRET_CAST_EXPR: - return build_reinterpret_cast - (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); - - case CONST_CAST_EXPR: - return build_const_cast - (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); - - case DYNAMIC_CAST_EXPR: - return build_dynamic_cast - (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); - - case STATIC_CAST_EXPR: - return build_static_cast - (TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0))); - - case PREDECREMENT_EXPR: - case PREINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - case NEGATE_EXPR: - case BIT_NOT_EXPR: - case ABS_EXPR: - case TRUTH_NOT_EXPR: - case ADDR_EXPR: - case CONVERT_EXPR: /* Unary + */ - if (TREE_TYPE (t)) - return t; - return build_x_unary_op (TREE_CODE (t), - build_expr_from_tree (TREE_OPERAND (t, 0))); - - case PLUS_EXPR: - case MINUS_EXPR: - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case CEIL_DIV_EXPR: - case FLOOR_DIV_EXPR: - case ROUND_DIV_EXPR: - case EXACT_DIV_EXPR: - case BIT_AND_EXPR: - case BIT_ANDTC_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case TRUNC_MOD_EXPR: - case FLOOR_MOD_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case RSHIFT_EXPR: - case LSHIFT_EXPR: - case RROTATE_EXPR: - case LROTATE_EXPR: - case EQ_EXPR: - case NE_EXPR: - case MAX_EXPR: - case MIN_EXPR: - case LE_EXPR: - case GE_EXPR: - case LT_EXPR: - case GT_EXPR: - case MEMBER_REF: - return build_x_binary_op - (TREE_CODE (t), - build_expr_from_tree (TREE_OPERAND (t, 0)), - build_expr_from_tree (TREE_OPERAND (t, 1))); - - case DOTSTAR_EXPR: - return build_m_component_ref - (build_expr_from_tree (TREE_OPERAND (t, 0)), - build_expr_from_tree (TREE_OPERAND (t, 1))); - - case SCOPE_REF: - return build_offset_ref (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)); - - case ARRAY_REF: - if (TREE_OPERAND (t, 0) == NULL_TREE) - /* new-type-id */ - return build_parse_node (ARRAY_REF, NULL_TREE, - build_expr_from_tree (TREE_OPERAND (t, 1))); - return grok_array_decl (build_expr_from_tree (TREE_OPERAND (t, 0)), - build_expr_from_tree (TREE_OPERAND (t, 1))); - - case SIZEOF_EXPR: - case ALIGNOF_EXPR: - { - tree r = build_expr_from_tree (TREE_OPERAND (t, 0)); - if (TREE_CODE_CLASS (TREE_CODE (r)) != 't') - r = TREE_TYPE (r); - return TREE_CODE (t) == SIZEOF_EXPR ? c_sizeof (r) : c_alignof (r); - } - - case MODOP_EXPR: - return build_x_modify_expr - (build_expr_from_tree (TREE_OPERAND (t, 0)), - TREE_CODE (TREE_OPERAND (t, 1)), - build_expr_from_tree (TREE_OPERAND (t, 2))); - - case ARROW_EXPR: - return build_x_arrow - (build_expr_from_tree (TREE_OPERAND (t, 0))); - - case NEW_EXPR: - return build_new - (build_expr_from_tree (TREE_OPERAND (t, 0)), - build_expr_from_tree (TREE_OPERAND (t, 1)), - build_expr_from_tree (TREE_OPERAND (t, 2)), - NEW_EXPR_USE_GLOBAL (t)); - - case DELETE_EXPR: - return delete_sanity - (build_expr_from_tree (TREE_OPERAND (t, 0)), - build_expr_from_tree (TREE_OPERAND (t, 1)), - DELETE_EXPR_USE_VEC (t), DELETE_EXPR_USE_GLOBAL (t)); - - case COMPOUND_EXPR: - if (TREE_OPERAND (t, 1) == NULL_TREE) - return build_x_compound_expr - (build_expr_from_tree (TREE_OPERAND (t, 0))); - else - my_friendly_abort (42); - - case METHOD_CALL_EXPR: - if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF) - { - tree ref = TREE_OPERAND (t, 0); - return build_scoped_method_call - (build_expr_from_tree (TREE_OPERAND (t, 1)), - build_expr_from_tree (TREE_OPERAND (ref, 0)), - TREE_OPERAND (ref, 1), - build_expr_from_tree (TREE_OPERAND (t, 2))); - } - else - { - tree fn = TREE_OPERAND (t, 0); - - /* We can get a TEMPLATE_ID_EXPR here on code like: - - x->f<2>(); - - so we must resolve that. However, we can also get things - like a BIT_NOT_EXPR here, when referring to a destructor, - and things like that are not correctly resolved by - build_expr_from_tree. So, just use build_expr_from_tree - when we really need it. */ - if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) - fn = build_expr_from_tree (fn); - - return build_method_call - (build_expr_from_tree (TREE_OPERAND (t, 1)), - fn, - build_expr_from_tree (TREE_OPERAND (t, 2)), - NULL_TREE, LOOKUP_NORMAL); - } - - case CALL_EXPR: - if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF) - { - tree ref = TREE_OPERAND (t, 0); - return build_member_call - (build_expr_from_tree (TREE_OPERAND (ref, 0)), - TREE_OPERAND (ref, 1), - build_expr_from_tree (TREE_OPERAND (t, 1))); - } - else - { - tree name = TREE_OPERAND (t, 0); - tree id; - tree args = build_expr_from_tree (TREE_OPERAND (t, 1)); - if (args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR - && !LOOKUP_EXPR_GLOBAL (name) - && TREE_CODE ((id = TREE_OPERAND (name, 0))) == IDENTIFIER_NODE - && (!current_class_type - || !lookup_member (current_class_type, id, 0, 0))) - { - /* Do Koenig lookup if there are no class members. */ - name = do_identifier (id, 0, args); - } - else if (TREE_CODE (name) == TEMPLATE_ID_EXPR - || ! really_overloaded_fn (name)) - name = build_expr_from_tree (name); - return build_x_function_call (name, args, current_class_ref); - } - - case COND_EXPR: - return build_x_conditional_expr - (build_expr_from_tree (TREE_OPERAND (t, 0)), - build_expr_from_tree (TREE_OPERAND (t, 1)), - build_expr_from_tree (TREE_OPERAND (t, 2))); - - case TREE_LIST: - { - tree purpose, value, chain; - - if (t == void_list_node) - return t; - - purpose = TREE_PURPOSE (t); - if (purpose) - purpose = build_expr_from_tree (purpose); - value = TREE_VALUE (t); - if (value) - value = build_expr_from_tree (value); - chain = TREE_CHAIN (t); - if (chain && chain != void_type_node) - chain = build_expr_from_tree (chain); - return expr_tree_cons (purpose, value, chain); - } - - case COMPONENT_REF: - return build_x_component_ref - (build_expr_from_tree (TREE_OPERAND (t, 0)), - TREE_OPERAND (t, 1), NULL_TREE, 1); - - case THROW_EXPR: - return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0))); - - case CONSTRUCTOR: - { - tree r; - - /* digest_init will do the wrong thing if we let it. */ - if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) - return t; - - r = build_nt (CONSTRUCTOR, NULL_TREE, - build_expr_from_tree (CONSTRUCTOR_ELTS (t))); - TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t); - - if (TREE_TYPE (t)) - return digest_init (TREE_TYPE (t), r, 0); - return r; - } - - case TYPEID_EXPR: - if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't') - return get_typeid (TREE_OPERAND (t, 0)); - return build_x_typeid (build_expr_from_tree (TREE_OPERAND (t, 0))); - - case VAR_DECL: - return convert_from_reference (t); - - default: - return t; - } -} - -/* This is something of the form `int (*a)++' that has turned out to be an - expr. It was only converted into parse nodes, so we need to go through - and build up the semantics. Most of the work is done by - build_expr_from_tree, above. - - In the above example, TYPE is `int' and DECL is `*a'. */ - -tree -reparse_decl_as_expr (type, decl) - tree type, decl; -{ - decl = build_expr_from_tree (decl); - if (type) - return build_functional_cast (type, build_expr_list (NULL_TREE, decl)); - else - return decl; -} - -/* This is something of the form `int (*a)' that has turned out to be a - decl. It was only converted into parse nodes, so we need to do the - checking that make_{pointer,reference}_declarator do. */ - -tree -finish_decl_parsing (decl) - tree decl; -{ - extern int current_class_depth; - - switch (TREE_CODE (decl)) - { - case IDENTIFIER_NODE: - return decl; - case INDIRECT_REF: - return make_pointer_declarator - (NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0))); - case ADDR_EXPR: - return make_reference_declarator - (NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0))); - case BIT_NOT_EXPR: - TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0)); - return decl; - case SCOPE_REF: - push_nested_class (TREE_TYPE (TREE_OPERAND (decl, 0)), 3); - TREE_COMPLEXITY (decl) = current_class_depth; - return decl; - case ARRAY_REF: - TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0)); - return decl; - case TREE_LIST: - /* For attribute handling. */ - TREE_VALUE (decl) = finish_decl_parsing (TREE_VALUE (decl)); - return decl; - default: - my_friendly_abort (5); - return NULL_TREE; - } -} - -tree -check_cp_case_value (value) - tree value; -{ - if (value == NULL_TREE) - return value; - - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - STRIP_TYPE_NOPS (value); - - if (TREE_READONLY_DECL_P (value)) - { - value = decl_constant_value (value); - STRIP_TYPE_NOPS (value); - } - value = fold (value); - - if (TREE_CODE (value) != INTEGER_CST - && value != error_mark_node) - { - cp_error ("case label `%E' does not reduce to an integer constant", - value); - value = error_mark_node; - } - else - /* Promote char or short to int. */ - value = default_conversion (value); - - constant_expression_warning (value); - - return value; -} - -/* Return 1 if root encloses child. */ - -static int -is_namespace_ancestor (root, child) - tree root, child; -{ - if (root == child) - return 1; - if (root == global_namespace) - return 1; - if (child == global_namespace) - return 0; - return is_namespace_ancestor (root, CP_DECL_CONTEXT (child)); -} - - -/* Return the namespace that is the common ancestor - of two given namespaces. */ - -tree -namespace_ancestor (ns1, ns2) - tree ns1, ns2; -{ - if (is_namespace_ancestor (ns1, ns2)) - return ns1; - return namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2); -} - -/* Insert used into the using list of user. Set indirect_flag if this - directive is not directly from the source. Also find the common - ancestor and let our users know about the new namespace */ -static void -add_using_namespace (user, used, indirect) - tree user; - tree used; - int indirect; -{ - tree t; - /* Using oneself is a no-op. */ - if (user == used) - return; - my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380); - my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380); - /* Check if we already have this. */ - t = purpose_member (used, DECL_NAMESPACE_USING (user)); - if (t != NULL_TREE) - { - if (!indirect) - /* Promote to direct usage. */ - TREE_INDIRECT_USING (t) = 0; - return; - } - - /* Add used to the user's using list. */ - DECL_NAMESPACE_USING (user) - = perm_tree_cons (used, namespace_ancestor (user, used), - DECL_NAMESPACE_USING (user)); - - TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect; - - /* Add user to the used's users list. */ - DECL_NAMESPACE_USERS (used) - = perm_tree_cons (user, 0, DECL_NAMESPACE_USERS (used)); - - /* Recursively add all namespaces used. */ - for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t)) - /* indirect usage */ - add_using_namespace (user, TREE_PURPOSE (t), 1); - - /* Tell everyone using us about the new used namespaces. */ - for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t)) - add_using_namespace (TREE_PURPOSE (t), used, 1); -} - -/* Combines two sets of overloaded functions into an OVERLOAD chain, removing - duplicates. The first list becomes the tail of the result. - - The algorithm is O(n^2). We could get this down to O(n log n) by - doing a sort on the addresses of the functions, if that becomes - necessary. */ - -static tree -merge_functions (s1, s2) - tree s1; - tree s2; -{ - for (; s2; s2 = OVL_NEXT (s2)) - { - tree fn = OVL_CURRENT (s2); - if (! ovl_member (fn, s1)) - s1 = build_overload (fn, s1); - } - return s1; -} - -/* This should return an error not all definitions define functions. - It is not an error if we find two functions with exactly the - same signature, only if these are selected in overload resolution. - old is the current set of bindings, new the freshly-found binding. - XXX Do we want to give *all* candidates in case of ambiguity? - XXX In what way should I treat extern declarations? - XXX I don't want to repeat the entire duplicate_decls here */ - -static tree -ambiguous_decl (name, old, new, flags) - tree name; - tree old; - tree new; - int flags; -{ - tree val, type; - my_friendly_assert (old != NULL_TREE, 393); - /* Copy the value. */ - val = BINDING_VALUE (new); - if (val) - switch (TREE_CODE (val)) - { - case TEMPLATE_DECL: - /* If we expect types or namespaces, and not templates, - or this is not a template class. */ - if (LOOKUP_QUALIFIERS_ONLY (flags) - && (!(flags & LOOKUP_TEMPLATES_EXPECTED) - || !DECL_CLASS_TEMPLATE_P (val))) - val = NULL_TREE; - break; - case TYPE_DECL: - if (LOOKUP_NAMESPACES_ONLY (flags)) - val = NULL_TREE; - break; - case NAMESPACE_DECL: - if (LOOKUP_TYPES_ONLY (flags)) - val = NULL_TREE; - break; - default: - if (LOOKUP_QUALIFIERS_ONLY (flags)) - val = NULL_TREE; - } - - if (!BINDING_VALUE (old)) - BINDING_VALUE (old) = val; - else if (val && val != BINDING_VALUE (old)) - { - if (is_overloaded_fn (BINDING_VALUE (old)) - && is_overloaded_fn (val)) - { - BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old), - val); - } - else - { - /* Some declarations are functions, some are not. */ - if (flags & LOOKUP_COMPLAIN) - { - /* If we've already given this error for this lookup, - BINDING_VALUE (old) is error_mark_node, so let's not - repeat ourselves. */ - if (BINDING_VALUE (old) != error_mark_node) - { - cp_error ("use of `%D' is ambiguous", name); - cp_error_at (" first declared as `%#D' here", - BINDING_VALUE (old)); - } - cp_error_at (" also declared as `%#D' here", val); - } - return error_mark_node; - } - } - /* ... and copy the type. */ - type = BINDING_TYPE (new); - if (LOOKUP_NAMESPACES_ONLY (flags)) - type = NULL_TREE; - if (!BINDING_TYPE (old)) - BINDING_TYPE (old) = type; - else if (type && BINDING_TYPE (old) != type) - { - if (flags & LOOKUP_COMPLAIN) - { - cp_error ("`%D' denotes an ambiguous type",name); - cp_error_at (" first type here", BINDING_TYPE (old)); - cp_error_at (" other type here", type); - } - } - return old; -} - -/* Add the bindings of name in used namespaces to val. - The using list is defined by usings, and the lookup goes to scope. - Returns zero on errors. */ - -int -lookup_using_namespace (name, val, usings, scope, flags) - tree name, val, usings, scope; - int flags; -{ - tree iter; - tree val1; - /* Iterate over all used namespaces in current, searching for using - directives of scope. */ - for (iter = usings; iter; iter = TREE_CHAIN (iter)) - if (TREE_VALUE (iter) == scope) - { - val1 = binding_for_name (name, TREE_PURPOSE (iter)); - /* Resolve ambiguities. */ - val = ambiguous_decl (name, val, val1, flags); - } - return val != error_mark_node; -} - -/* [namespace.qual] - Excepts the name to lookup and its qualifying scope. - Returns the name/type pair found into the CPLUS_BINDING result, - or 0 on error. */ - -int -qualified_lookup_using_namespace (name, scope, result, flags) - tree name; - tree scope; - tree result; - int flags; -{ - /* Maintain a list of namespaces visited... */ - tree seen = NULL_TREE; - /* ... and a list of namespace yet to see. */ - tree todo = NULL_TREE; - tree usings; - while (scope && (result != error_mark_node)) - { - seen = temp_tree_cons (scope, NULL_TREE, seen); - result = ambiguous_decl (name, result, - binding_for_name (name, scope), flags); - if (!BINDING_VALUE (result) && !BINDING_TYPE (result)) - /* Consider using directives. */ - for (usings = DECL_NAMESPACE_USING (scope); usings; - usings = TREE_CHAIN (usings)) - /* If this was a real directive, and we have not seen it. */ - if (!TREE_INDIRECT_USING (usings) - && !purpose_member (TREE_PURPOSE (usings), seen)) - todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo); - if (todo) - { - scope = TREE_PURPOSE (todo); - todo = TREE_CHAIN (todo); - } - else - scope = NULL_TREE; /* If there never was a todo list. */ - } - return result != error_mark_node; -} - -/* [namespace.memdef]/2 */ - -/* Set the context of a declaration to scope. Complain if we are not - outside scope. */ - -void -set_decl_namespace (decl, scope) - tree decl; - tree scope; -{ - tree old; - if (scope == std_node) - scope = global_namespace; - /* Get rid of namespace aliases. */ - scope = ORIGINAL_NAMESPACE (scope); - - if (!is_namespace_ancestor (current_namespace, scope)) - cp_error ("declaration of `%D' not in a namespace surrounding `%D'", - decl, scope); - DECL_CONTEXT (decl) = FROB_CONTEXT (scope); - if (scope != current_namespace) - { - /* See whether this has been declared in the namespace. */ - old = namespace_binding (DECL_NAME (decl), scope); - if (!old) - /* No old declaration at all. */ - goto complain; - if (!is_overloaded_fn (decl)) - /* Don't compare non-function decls with decls_match here, - since it can't check for the correct constness at this - point. pushdecl will find those errors later. */ - return; - /* Since decl is a function, old should contain a function decl. */ - if (!is_overloaded_fn (old)) - goto complain; - for (; old; old = OVL_NEXT (old)) - if (decls_match (decl, OVL_CURRENT (old))) - return; - } - else - return; - complain: - cp_error ("`%D' should have been declared inside `%D'", - decl, scope); -} - -/* Compute the namespace where a declaration is defined. */ - -tree -decl_namespace (decl) - tree decl; -{ - while (DECL_CONTEXT (decl)) - { - decl = DECL_CONTEXT (decl); - if (TREE_CODE (decl) == NAMESPACE_DECL) - return decl; - if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't') - decl = TYPE_STUB_DECL (decl); - my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 390); - } - - return global_namespace; -} - -/* Return the namespace where the current declaration is declared. */ - -tree -current_decl_namespace () -{ - tree result; - /* If we have been pushed into a different namespace, use it. */ - if (decl_namespace_list) - return TREE_PURPOSE (decl_namespace_list); - - if (current_class_type) - result = decl_namespace (TYPE_STUB_DECL (current_class_type)); - else if (current_function_decl) - result = decl_namespace (current_function_decl); - else - result = current_namespace; - return result; -} - -/* Temporarily set the namespace for the current declaration. */ - -void -push_decl_namespace (decl) - tree decl; -{ - if (TREE_CODE (decl) != NAMESPACE_DECL) - decl = decl_namespace (decl); - decl_namespace_list = tree_cons (decl, NULL_TREE, decl_namespace_list); -} - -void -pop_decl_namespace () -{ - decl_namespace_list = TREE_CHAIN (decl_namespace_list); -} - -static void -check_decl_namespace () -{ - my_friendly_assert (decl_namespace_list == NULL_TREE, 980711); -} - -/* Enter a class or namespace scope. */ - -void -push_scope (t) - tree t; -{ - if (TREE_CODE (t) == NAMESPACE_DECL) - push_decl_namespace (t); - else - pushclass (t, 2); -} - -/* Leave scope pushed by push_scope. */ - -void -pop_scope (t) - tree t; -{ - if (TREE_CODE (t) == NAMESPACE_DECL) - pop_decl_namespace (); - else - popclass (1); -} - -/* [basic.lookup.koenig] */ -/* A non-zero return value in the functions below indicates an error. - All nodes allocated in the procedure are on the scratch obstack. */ - -struct arg_lookup -{ - tree name; - tree namespaces; - tree classes; - tree functions; -}; - -static int arg_assoc PROTO((struct arg_lookup*, tree)); -static int arg_assoc_args PROTO((struct arg_lookup*, tree)); -static int arg_assoc_type PROTO((struct arg_lookup*, tree)); - -/* Add a function to the lookup structure. - Returns 1 on error. */ - -static int -add_function (k, fn) - struct arg_lookup *k; - tree fn; -{ - if (ovl_member (fn, k->functions)) - return 0; - /* We must find only functions, or exactly one non-function. */ - if (k->functions && is_overloaded_fn (k->functions) - && is_overloaded_fn (fn)) - k->functions = build_overload (fn, k->functions); - else - if(k->functions) - { - tree f1 = OVL_CURRENT (k->functions); - tree f2 = fn; - if (is_overloaded_fn (f1)) - { - fn = f1; f1 = f2; f2 = fn; - } - cp_error_at ("`%D' is not a function,", f1); - cp_error_at (" conflict with `%D'", f2); - cp_error (" in call to `%D'", k->name); - return 1; - } - else - k->functions = fn; - return 0; -} - -/* Add functions of a namespace to the lookup structure. - Returns 1 on error. */ - -static int -arg_assoc_namespace (k, scope) - struct arg_lookup *k; - tree scope; -{ - tree value; - - if (purpose_member (scope, k->namespaces)) - return 0; - k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces); - - value = namespace_binding (k->name, scope); - if (!value) - return 0; - - for (; value; value = OVL_NEXT (value)) - if (add_function (k, OVL_CURRENT (value))) - return 1; - - return 0; -} - -/* Adds everything associated with class to the lookup structure. - Returns 1 on error. */ - -static int -arg_assoc_class (k, type) - struct arg_lookup* k; - tree type; -{ - tree list, friends, context; - int i; - - if (purpose_member (type, k->classes)) - return 0; - k->classes = tree_cons (type, NULL_TREE, k->classes); - - context = decl_namespace (TYPE_MAIN_DECL (type)); - if (arg_assoc_namespace (k, context)) - return 1; - - /* Process baseclasses. */ - for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++) - if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i))) - return 1; - - /* Process friends. */ - for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list; - list = TREE_CHAIN (list)) - if (k->name == TREE_PURPOSE (list)) - for (friends = TREE_VALUE (list); friends; - friends = TREE_CHAIN (friends)) - /* Only interested in global functions with potentially hidden - (i.e. unqualified) declarations. */ - if (TREE_PURPOSE (list) == error_mark_node && TREE_VALUE (list) - && decl_namespace (TREE_VALUE (list)) == context) - if (add_function (k, TREE_VALUE (list))) - return 1; - - /* Process template arguments. */ - if (CLASSTYPE_TEMPLATE_INFO (type)) - { - list = innermost_args (CLASSTYPE_TI_ARGS (type)); - for (i = 0; i < TREE_VEC_LENGTH (list); ++i) - arg_assoc (k, TREE_VEC_ELT (list, i)); - } - - return 0; -} - -/* Adds everything associated with a given type. - Returns 1 on error. */ - -static int -arg_assoc_type (k, type) - struct arg_lookup *k; - tree type; -{ - switch (TREE_CODE (type)) - { - case VOID_TYPE: - case INTEGER_TYPE: - case REAL_TYPE: - case COMPLEX_TYPE: - case CHAR_TYPE: - case BOOLEAN_TYPE: - return 0; - case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (type)) - return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type)); - return arg_assoc_class (k, type); - case POINTER_TYPE: - case REFERENCE_TYPE: - case ARRAY_TYPE: - return arg_assoc_type (k, TREE_TYPE (type)); - case UNION_TYPE: - case ENUMERAL_TYPE: - return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type))); - case OFFSET_TYPE: - /* Pointer to member: associate class type and value type. */ - if (arg_assoc_type (k, TYPE_OFFSET_BASETYPE (type))) - return 1; - return arg_assoc_type (k, TREE_TYPE (type)); - case METHOD_TYPE: - /* The basetype is referenced in the first arg type, so just - fall through. */ - case FUNCTION_TYPE: - /* Associate the parameter types. */ - if (arg_assoc_args (k, TYPE_ARG_TYPES (type))) - return 1; - /* Associate the return type. */ - return arg_assoc_type (k, TREE_TYPE (type)); - case TEMPLATE_TYPE_PARM: - return 0; - case LANG_TYPE: - if (type == unknown_type_node) - return 0; - /* else fall through */ - default: - my_friendly_abort (390); - } - return 0; -} - -/* Adds everything associated with arguments. Returns 1 on error. */ - -static int -arg_assoc_args (k, args) - struct arg_lookup* k; - tree args; -{ - for (; args; args = TREE_CHAIN (args)) - if (arg_assoc (k, TREE_VALUE (args))) - return 1; - return 0; -} - -/* Adds everything associated with a given tree_node. Returns 1 on error. */ - -static int -arg_assoc (k, n) - struct arg_lookup* k; - tree n; -{ - if (n == error_mark_node) - return 0; - - if (TREE_CODE_CLASS (TREE_CODE (n)) == 't') - return arg_assoc_type (k, n); - - if (! type_unknown_p (n)) - return arg_assoc_type (k, TREE_TYPE (n)); - - if (TREE_CODE (n) == ADDR_EXPR) - n = TREE_OPERAND (n, 0); - if (TREE_CODE (n) == COMPONENT_REF) - n = TREE_OPERAND (n, 1); - while (TREE_CODE (n) == TREE_LIST) - n = TREE_VALUE (n); - - if (TREE_CODE (n) == FUNCTION_DECL) - return arg_assoc_type (k, TREE_TYPE (n)); - if (TREE_CODE (n) == TEMPLATE_ID_EXPR) - { - /* [basic.lookup.koenig] - - If T is a template-id, its associated namespaces and classes - are the namespace in which the template is defined; for - member templates, the member template's class; the namespaces - and classes associated with the types of the template - arguments provided for template type parameters (excluding - template template parameters); the namespaces in which any - template template arguments are defined; and the classes in - which any member templates used as template template - arguments are defined. [Note: non-type template arguments do - not contribute to the set of associated namespaces. ] */ - tree template = TREE_OPERAND (n, 0); - tree args = TREE_OPERAND (n, 1); - tree ctx; - tree arg; - - /* First, the template. There may actually be more than one if - this is an overloaded function template. But, in that case, - we only need the first; all the functions will be in the same - namespace. */ - template = OVL_CURRENT (template); - - ctx = CP_DECL_CONTEXT (template); - - if (TREE_CODE (ctx) == NAMESPACE_DECL) - { - if (arg_assoc_namespace (k, ctx) == 1) - return 1; - } - /* It must be a member template. */ - else if (arg_assoc_class (k, ctx) == 1) - return 1; - - /* Now the arguments. */ - for (arg = args; arg != NULL_TREE; arg = TREE_CHAIN (arg)) - { - tree t = TREE_VALUE (arg); - - if (TREE_CODE (t) == TEMPLATE_DECL) - { - ctx = CP_DECL_CONTEXT (t); - if (TREE_CODE (ctx) == NAMESPACE_DECL) - { - if (arg_assoc_namespace (k, ctx) == 1) - return 1; - } - else if (arg_assoc_class (k, ctx) == 1) - return 1; - } - else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't' - && arg_assoc_type (k, t) == 1) - return 1; - } - } - else - { - my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715); - - for (; n; n = OVL_CHAIN (n)) - if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n)))) - return 1; - } - - return 0; -} - -/* Performs Koenig lookup depending on arguments, where fns - are the functions found in normal lookup. */ - -tree -lookup_arg_dependent (name, fns, args) - tree name; - tree fns; - tree args; -{ - struct arg_lookup k; - k.name = name; - k.functions = fns; - k.namespaces = NULL_TREE; - k.classes = NULL_TREE; - - push_scratch_obstack (); - arg_assoc_args (&k, args); - pop_obstacks (); - return k.functions; -} - -/* Process a namespace-alias declaration. */ - -void -do_namespace_alias (alias, namespace) - tree alias, namespace; -{ - if (TREE_CODE (namespace) != NAMESPACE_DECL) - { - /* The parser did not find it, so it's not there. */ - cp_error ("unknown namespace `%D'", namespace); - return; - } - - namespace = ORIGINAL_NAMESPACE (namespace); - - /* Build the alias. */ - alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node); - DECL_NAMESPACE_ALIAS (alias) = namespace; - pushdecl (alias); -} - -/* Check a non-member using-declaration. Return the name and scope - being used, and the USING_DECL, or NULL_TREE on failure. */ - -static tree -validate_nonmember_using_decl (decl, scope, name) - tree decl; - tree *scope; - tree *name; -{ - if (TREE_CODE (decl) == SCOPE_REF - && TREE_OPERAND (decl, 0) == std_node) - { - if (namespace_bindings_p () - && current_namespace == global_namespace) - /* There's no need for a using declaration at all, here, - since `std' is the same as `::'. We can't just pass this - on because we'll complain later about declaring something - in the same scope as a using declaration with the same - name. We return NULL_TREE which indicates to the caller - that there's no need to do any further processing. */ - return NULL_TREE; - - *scope = global_namespace; - *name = TREE_OPERAND (decl, 1); - } - else if (TREE_CODE (decl) == SCOPE_REF) - { - *scope = TREE_OPERAND (decl, 0); - *name = TREE_OPERAND (decl, 1); - - /* [namespace.udecl] - - A using-declaration for a class member shall be a - member-declaration. */ - if (TREE_CODE (*scope) != NAMESPACE_DECL) - { - cp_error ("`%D' is not a namespace", *scope); - return NULL_TREE; - } - } - else if (TREE_CODE (decl) == IDENTIFIER_NODE - || TREE_CODE (decl) == TYPE_DECL - || TREE_CODE (decl) == TEMPLATE_DECL) - { - *scope = global_namespace; - *name = decl; - } - else - my_friendly_abort (382); - if (TREE_CODE_CLASS (TREE_CODE (*name)) == 'd') - *name = DECL_NAME (*name); - /* Make a USING_DECL. */ - return push_using_decl (*scope, *name); -} - -/* Process local and global using-declarations. */ - -static void -do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype) - tree scope, name; - tree oldval, oldtype; - tree *newval, *newtype; -{ - tree decls; - struct tree_binding _decls; - - *newval = *newtype = NULL_TREE; - decls = binding_init (&_decls); - if (!qualified_lookup_using_namespace (name, scope, decls, 0)) - /* Lookup error */ - return; - - if (!BINDING_VALUE (decls) && !BINDING_TYPE (decls)) - { - cp_error ("`%D' not declared", name); - return; - } - - /* Check for using functions. */ - if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls))) - { - tree tmp, tmp1; - - if (oldval && !is_overloaded_fn (oldval)) - { - duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval); - oldval = NULL_TREE; - } - - *newval = oldval; - for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp)) - { - tree new_fn = OVL_CURRENT (tmp); - - /* [namespace.udecl] - - If a function declaration in namespace scope or block - scope has the same name and the same parameter types as a - function introduced by a using declaration the program is - ill-formed. */ - for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1)) - { - tree old_fn = OVL_CURRENT (tmp1); - - if (!OVL_USED (tmp1) - && compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), - TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) - { - /* There was already a non-using declaration in - this scope with the same parameter types. */ - cp_error ("`%D' is already declared in this scope", - name); - break; - } - else if (duplicate_decls (new_fn, old_fn)) - /* We're re-using something we already used - before. We don't need to add it again. */ - break; - } - - /* If we broke out of the loop, there's no reason to add - this function to the using declarations for this - scope. */ - if (tmp1) - continue; - - *newval = build_overload (OVL_CURRENT (tmp), *newval); - if (TREE_CODE (*newval) != OVERLOAD) - *newval = ovl_cons (*newval, NULL_TREE); - OVL_USED (*newval) = 1; - } - } - else - { - *newval = BINDING_VALUE (decls); - if (oldval) - duplicate_decls (*newval, oldval); - } - - *newtype = BINDING_TYPE (decls); - if (oldtype && *newtype && oldtype != *newtype) - { - cp_error ("using directive `%D' introduced ambiguous type `%T'", - name, oldtype); - return; - } -} - -/* Process a using-declaration not appearing in class or local scope. */ - -void -do_toplevel_using_decl (decl) - tree decl; -{ - tree scope, name, binding; - tree oldval, oldtype, newval, newtype; - - decl = validate_nonmember_using_decl (decl, &scope, &name); - if (decl == NULL_TREE) - return; - - binding = binding_for_name (name, current_namespace); - - oldval = BINDING_VALUE (binding); - oldtype = BINDING_TYPE (binding); - - do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); - - /* Copy declarations found. */ - if (newval) - BINDING_VALUE (binding) = newval; - if (newtype) - BINDING_TYPE (binding) = newtype; - return; -} - -/* Process a using-declaration at function scope. */ - -void -do_local_using_decl (decl) - tree decl; -{ - tree scope, name; - tree oldval, oldtype, newval, newtype; - - decl = validate_nonmember_using_decl (decl, &scope, &name); - if (decl == NULL_TREE) - return; - - oldval = lookup_name_current_level (name); - oldtype = lookup_type_current_level (name); - - do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); - - if (newval) - { - if (is_overloaded_fn (newval)) - { - tree fn; - - /* We only need to push declarations for those functions - that were not already bound in the current level. */ - for (fn = newval; fn != oldval; fn = OVL_NEXT (fn)) - push_overloaded_decl (OVL_CURRENT (fn), - PUSH_LOCAL | PUSH_USING); - } - else - push_local_binding (name, newval, PUSH_USING); - } - if (newtype) - set_identifier_type_value (name, newtype); -} - -tree -do_class_using_decl (decl) - tree decl; -{ - tree name, value; - - if (TREE_CODE (decl) != SCOPE_REF - || TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (decl, 0))) != 't') - { - cp_error ("using-declaration for non-member at class scope"); - return NULL_TREE; - } - name = TREE_OPERAND (decl, 1); - if (TREE_CODE (name) == BIT_NOT_EXPR) - { - cp_error ("using-declaration for destructor"); - return NULL_TREE; - } - if (TREE_CODE (name) == TYPE_DECL) - name = DECL_NAME (name); - - my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716); - - value = build_lang_field_decl (USING_DECL, name, void_type_node); - DECL_INITIAL (value) = TREE_OPERAND (decl, 0); - return value; -} - -/* Process a using-directive. */ - -void -do_using_directive (namespace) - tree namespace; -{ - if (namespace == std_node) - return; - /* using namespace A::B::C; */ - if (TREE_CODE (namespace) == SCOPE_REF) - namespace = TREE_OPERAND (namespace, 1); - if (TREE_CODE (namespace) == IDENTIFIER_NODE) - { - /* Lookup in lexer did not find a namespace. */ - cp_error ("namespace `%T' undeclared", namespace); - return; - } - if (TREE_CODE (namespace) != NAMESPACE_DECL) - { - cp_error ("`%T' is not a namespace", namespace); - return; - } - namespace = ORIGINAL_NAMESPACE (namespace); - if (!toplevel_bindings_p ()) - push_using_directive (namespace); - else - /* direct usage */ - add_using_namespace (current_namespace, namespace, 0); -} - -void -check_default_args (x) - tree x; -{ - tree arg = TYPE_ARG_TYPES (TREE_TYPE (x)); - int saw_def = 0, i = 0 - (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE); - for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i) - { - if (TREE_PURPOSE (arg)) - saw_def = 1; - else if (saw_def) - { - cp_error_at ("default argument missing for parameter %P of `%+#D'", - i, x); - break; - } - } -} - -void -mark_used (decl) - tree decl; -{ - TREE_USED (decl) = 1; - if (processing_template_decl) - return; - assemble_external (decl); - - /* Is it a synthesized method that needs to be synthesized? */ - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl) - && DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) - /* Kludge: don't synthesize for default args. */ - && current_function_decl) - synthesize_method (decl); - - /* If this is a function or variable that is an instance of some - template, we now know that we will need to actually do the - instantiation. A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO, - if it's a partial instantiation, but there's no need to - instantiate such a thing. We check that DECL is not an explicit - instantiation because that is not checked in instantiate_decl. */ - if (TREE_CODE (decl) != TEMPLATE_DECL - && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) - && !DECL_EXPLICIT_INSTANTIATION (decl)) - instantiate_decl (decl); -} - -/* Helper function for named_class_head_sans_basetype nonterminal. */ - -tree -handle_class_head (aggr, scope, id) - tree aggr, scope, id; -{ - if (TREE_CODE (id) == TYPE_DECL) - return id; - if (DECL_CLASS_TEMPLATE_P (id)) - return DECL_TEMPLATE_RESULT (id); - - if (scope) - cp_error ("`%T' does not have a nested type named `%D'", scope, id); - else - cp_error ("no file-scope type named `%D'", id); - - id = xref_tag - (aggr, make_anon_name (), 1); - return TYPE_MAIN_DECL (id); -} |