summaryrefslogtreecommitdiff
path: root/gcc/cp/decl2.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl2.c')
-rwxr-xr-xgcc/cp/decl2.c5040
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);
-}