/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
#include "lex.h"
#include "output.h"
#include "except.h"
-#include "defaults.h"
#include "toplev.h"
#include "dwarf2out.h"
#include "dwarfout.h"
#include "ggc.h"
#include "timevar.h"
#include "cpplib.h"
+#include "target.h"
extern cpp_reader *parse_in;
/* This structure contains information about the initializations
static int compare_options PARAMS ((const PTR, const PTR));
static tree get_guard_bits PARAMS ((tree));
-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. */
/* The :: namespace. */
tree global_namespace;
-
-/* The stack for namespaces of current declarations. */
-
-static tree decl_namespace_list;
-
\f
/* 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;
/* 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;
+int flag_vtable_thunks = 1;
/* Nonzero means generate separate instantiation control files and juggle
them at link time. */
/* 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;
+int warn_nonvdtor;
/* 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. */
#endif
int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-/* Nonzero means that labels can be used as first-class objects */
-
-int flag_labels_ok;
-
/* Nonzero means allow Microsoft extensions without a pedwarn. */
int flag_ms_extensions;
/* 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;
/* Nonzero means we should attempt to elide constructors when possible. */
/* 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;
+int flag_rtti = 1;
/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
objects. */
int flag_weak = 1;
-/* Nonzero to enable experimental ABI changes. */
-
-int flag_new_abi;
-
/* Nonzero to use __cxa_atexit, rather than atexit, to register
destructors for local statics and global objects. */
/* Nonzero to not ignore namespace std. */
-int flag_honor_std = ENABLE_STD_NAMESPACE;
+int flag_honor_std = 1;
-/* Nonzero if we should expand functions calls inline at the tree
- level, rather than at the RTL level. */
+/* 0 if we should not perform inlining.
+ 1 if we should expand functions calls inline at the tree level.
+ 2 if we should consider *all* functions to be inline
+ candidates. */
int flag_inline_trees = 0;
-/* Maximum template instantiation depth. Must be at least 17 for ISO
- 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;
+/* Maximum template instantiation depth. This limit is rather
+ arbitrary, but it exists to limit the time it takes to notice
+ infinite template instantiations. */
-/* Nonzero if wchar_t should be `unsigned short' instead of whatever it
- would normally be, for use with WINE. */
-int flag_short_wchar;
-
-/* 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;
+int max_tinst_depth = 50;
/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
{"short-enums", &flag_short_enums, 1},
{"short-double", &flag_short_double, 1},
{"short-wchar", &flag_short_wchar, 1},
- {"cond-mismatch", &flag_cond_mismatch, 1},
{"asm", &flag_no_asm, 0},
{"builtin", &flag_no_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0},
{"handle-exceptions", &flag_exceptions, 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},
{"ms-extensions", &flag_ms_extensions, 1},
{"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"operator-names", &flag_operator_names, 1},
{"permissive", &flag_permissive, 1},
{"repo", &flag_use_repository, 1},
{"rtti", &flag_rtti, 1},
- {"squangle", &flag_do_squangling, 1},
{"stats", &flag_detailed_statistics, 1},
- {"use-cxa-atexit", &flag_use_cxa_atexit, 1},
{"vtable-gc", &flag_vtable_gc, 1},
- {"vtable-thunks", &flag_vtable_thunks, 1},
- {"weak", &flag_weak, 1},
- {"xref", &flag_gnu_xref, 1}
+ {"use-cxa-atexit", &flag_use_cxa_atexit, 1},
+ {"weak", &flag_weak, 1}
};
/* The list of `-f' options that we no longer support. The `-f'
listed here. This table must be kept in alphabetical order. */
static const char * const unsupported_options[] = {
"all-virtual",
+ "cond-mismatch",
"enum-int-equiv",
"guiding-decls",
+ "huge-objects",
+ "labels-ok",
+ "new-abi",
"nonnull-objects",
- "this-is-variable",
+ "squangle",
"strict-prototype",
+ "this-is-variable",
+ "vtable-thunks",
+ "xref"
};
/* Compare two option strings, pointed two by P1 and P2, for use with
recognise the option. */
int
-lang_decode_option (argc, argv)
+cxx_decode_option (argc, argv)
int argc;
char **argv;
{
flag_external_templates = 1;
cp_deprecated ("-fexternal-templates");
}
- else if (!strcmp (p, "new-abi"))
- {
- flag_new_abi = 1;
- flag_do_squangling = 1;
- flag_vtable_thunks = 1;
- }
- else if (!strcmp (p, "no-new-abi"))
- {
- flag_new_abi = 0;
- flag_do_squangling = 0;
- }
else if ((option_value
= skip_leading_substring (p, "template-depth-")))
max_tinst_depth
= read_integral_parameter (option_value, p - 2, max_tinst_depth);
else if ((option_value
= skip_leading_substring (p, "name-mangling-version-")))
- name_mangling_version
- = read_integral_parameter (option_value, p - 2, name_mangling_version);
- else if ((option_value
- = skip_leading_substring (p, "dump-translation-unit-")))
{
- if (p[22] == '\0')
- error ("no file specified with -fdump-translation-unit");
- else
- flag_dump_translation_unit = option_value;
+ warning ("-fname-mangling-version is no longer supported");
+ return 1;
}
+ else if (dump_switch_p (p))
+ ;
else
{
int found = 0;
warn_float_equal = setting;
else if (!strcmp (p, "format"))
set_Wformat (setting);
+ else if (!strcmp (p, "format=2"))
+ set_Wformat (2);
else if (!strcmp (p, "format-y2k"))
warn_format_y2k = setting;
else if (!strcmp (p, "format-extra-args"))
warn_format_extra_args = setting;
else if (!strcmp (p, "format-nonliteral"))
warn_format_nonliteral = setting;
+ else if (!strcmp (p, "format-security"))
+ warn_format_security = setting;
else if (!strcmp (p, "missing-format-attribute"))
warn_missing_format_attribute = setting;
else if (!strcmp (p, "conversion"))
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"))
parm = build_decl (PARM_DECL, name, type);
DECL_ARTIFICIAL (parm) = 1;
+ /* All our artificial parms are implicitly `const'; they cannot be
+ assigned to. */
+ TREE_READONLY (parm) = 1;
DECL_ARG_TYPE (parm) = type;
return parm;
}
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. */
+ FN must be either a constructor or destructor.
+
+ The in-charge flag follows the 'this' parameter, and is followed by the
+ VTT parm (if any), then the user-written parms. */
void
maybe_retrofit_in_chrg (fn)
&& !TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
return;
- /* First add it to DECL_ARGUMENTS... */
- parm = build_artificial_parm (in_charge_identifier, 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));
+ arg_types = TREE_CHAIN (arg_types);
+
+ parms = TREE_CHAIN (DECL_ARGUMENTS (fn));
+
+ /* If this is a subobject constructor or destructor, our caller will
+ pass us a pointer to our VTT. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ {
+ parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type);
+
+ /* First add it to DECL_ARGUMENTS between 'this' and the real args... */
+ TREE_CHAIN (parm) = parms;
+ parms = parm;
+
+ /* ...and then to TYPE_ARG_TYPES. */
+ arg_types = hash_tree_chain (vtt_parm_type, arg_types);
+
+ DECL_HAS_VTT_PARM_P (fn) = 1;
+ }
+
+ /* Then add the in-charge parm (before the VTT parm). */
+ parm = build_artificial_parm (in_charge_identifier, integer_type_node);
+ TREE_CHAIN (parm) = parms;
+ parms = parm;
+ arg_types = hash_tree_chain (integer_type_node, arg_types);
+
+ /* Insert our new parameter(s) into the list. */
+ TREE_CHAIN (DECL_ARGUMENTS (fn)) = parms;
+
+ /* And rebuild the function type. */
fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
arg_types);
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
/* Now we've got the in-charge parameter. */
DECL_HAS_IN_CHARGE_PARM_P (fn) = 1;
-
- /* If this is a subobject constructor or destructor, our caller will
- pass us a pointer to our VTT. */
- if (flag_new_abi && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
- {
- DECL_VTT_PARM (fn) = build_artificial_parm (vtt_parm_identifier,
- vtt_parm_type);
- DECL_CONTEXT (DECL_VTT_PARM (fn)) = fn;
- DECL_USE_VTT_PARM (fn) = build_artificial_parm (NULL_TREE,
- boolean_type_node);
- DECL_CONTEXT (DECL_USE_VTT_PARM (fn)) = fn;
- }
}
/* Classes overload their constituent function names automatically.
/* Even within an `extern "C"' block, members get C++ linkage. See
[dcl.link] for details. */
- DECL_LANGUAGE (function) = lang_cplusplus;
+ SET_DECL_LANGUAGE (function, lang_cplusplus);
if (fn_name == NULL_TREE)
{
DECL_ARGUMENTS (function) = last_function_parms;
DECL_CONTEXT (function) = ctype;
+ if (flags == DTOR_FLAG)
+ DECL_DESTRUCTOR_P (function) = 1;
+
if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))
maybe_retrofit_in_chrg (function);
if (flags == DTOR_FLAG)
{
DECL_DESTRUCTOR_P (function) = 1;
-
- if (flag_new_abi)
- set_mangled_name_for_decl (function);
- else
- 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). */
{
if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type))
return 1;
- if (TREE_CODE (type) == POINTER_TYPE)
+ if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
{
type = TREE_TYPE (type);
if (TREE_CODE (type) == RECORD_TYPE)
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 (!DECL_DESTRUCTOR_P (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
tree asmspec_tree;
int flags;
{
- const char *asmspec = 0;
-
- if (asmspec_tree)
- asmspec = TREE_STRING_POINTER (asmspec_tree);
-
my_friendly_assert (TREE_PUBLIC (decl), 0);
DECL_CONTEXT (decl) = current_class_type;
/* We cannot call pushdecl here, because that would fill in the
- decl of our TREE_CHAIN. Instead, we modify cp_finish_decl to do
+ TREE_CHAIN of our decl. 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 && current_class_type)
- {
- DECL_INITIAL (decl) = error_mark_node;
- if (flag_new_abi)
- DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl);
- else
- DECL_ASSEMBLER_NAME (decl)
- = build_static_name (current_class_type, DECL_NAME (decl));
- }
+ if (!asmspec_tree && current_class_type)
+ DECL_INITIAL (decl) = error_mark_node;
+
if (! processing_template_decl)
{
if (!pending_statics)
if (CLASS_TYPE_P (TREE_TYPE (value)))
CLASSTYPE_GOT_SEMICOLON (TREE_TYPE (value)) = 1;
- /* 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))
- {
- if (flag_new_abi)
- DECL_ASSEMBLER_NAME (value) = mangle_type (TREE_TYPE (value));
- else
- DECL_ASSEMBLER_NAME (value) =
- get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
- }
-
if (processing_template_decl)
value = push_template_decl (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);
- }
+ cp_error ("`asm' specifiers are not permitted on non-static data members");
if (DECL_INITIAL (value) == error_mark_node)
init = error_mark_node;
- cp_finish_decl (value, init, asmspec_tree, flags);
+ cp_finish_decl (value, init, NULL_TREE, flags);
DECL_INITIAL (value) = init;
DECL_IN_AGGR_P (value) = 1;
return value;
{
/* 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);
+ SET_DECL_RTL (value, NULL_RTX);
+ SET_DECL_ASSEMBLER_NAME (value, get_identifier (asmspec));
}
cp_finish_decl (value, init, asmspec_tree, flags);
tree declspecs, declarator;
{
tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
- if (flag_new_abi)
- return mangle_conv_op_name_for_type (t);
- else
- return build_typename_overload (t);
+ return mangle_conv_op_name_for_type (t);
}
/* When a function is declared with an initializer,
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 member function `%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 (!DECL_DESTRUCTOR_P (decl)))
- {
- /* Give this node rtl from `abort'. */
- DECL_RTL (decl) = DECL_RTL (abort_fndecl);
- }
-#endif
DECL_PURE_VIRTUAL_P (decl) = 1;
if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
{
if (TREE_CODE (decl) == TEMPLATE_DECL)
decl = DECL_TEMPLATE_RESULT (decl);
- decl_attributes (decl, attributes, prefix_attributes);
+ decl_attributes (decl, chainon (attributes, prefix_attributes));
if (TREE_CODE (decl) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (decl), TREE_TYPE (decl));
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. */
+/* Finish off the processing of a UNION_TYPE structure. If the union is an
+ anonymous union, then all members must be laid out together. PUBLIC_P
+ is nonzero if this union is not declared static. */
void
finish_anon_union (anon_union_decl)
int static_p = TREE_STATIC (anon_union_decl);
int external_p = DECL_EXTERNAL (anon_union_decl);
+ /* The VAR_DECL's context is the same as the TYPE's context. */
+ DECL_CONTEXT (anon_union_decl) = DECL_CONTEXT (TYPE_NAME (type));
+
if (TYPE_FIELDS (type) == NULL_TREE)
return;
if (static_p)
{
- make_decl_rtl (main_decl, 0, toplevel_bindings_p ());
- DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
+ make_decl_rtl (main_decl, 0);
+ COPY_DECL_RTL (main_decl, anon_union_decl);
expand_anon_union_decl (anon_union_decl,
NULL_TREE,
DECL_ANON_UNION_ELEMS (anon_union_decl));
if (TREE_CODE (fnaddr) != ADDR_EXPR)
/* This entry is an offset: a virtual base class offset, a
- virtual call offset, and RTTI offset, etc. */
+ virtual call offset, an RTTI offset, etc. */
continue;
fn = TREE_OPERAND (fnaddr, 0);
we know all the thunks we'll need when we emit a virtual
function, so we emit the thunks there instead. */
if (DECL_THUNK_P (fn))
- use_thunk (fn, THUNK_GENERATE_WITH_VTABLE_P (fn));
+ use_thunk (fn, /*emit_p=*/0);
mark_used (fn);
}
}
{
if (flag_weak)
make_decl_one_only (decl);
- else if (TREE_CODE (decl) == FUNCTION_DECL || DECL_VIRTUAL_P (decl))
- /* We can just emit functions and vtables statically; having
- multiple copies is (for the most part) only a waste of space.
- There is at least one correctness issue, however: the address
- of a template instantiation with external linkage should be the
+ else if (TREE_CODE (decl) == FUNCTION_DECL
+ || (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl)))
+ /* We can just emit function and compiler-generated variables
+ statically; having multiple copies is (for the most part) only
+ a waste of space.
+
+ There are two correctness issues, however: the address of a
+ template instantiation with external linkage should be the
same, independent of what translation unit asks for the
address, and this will not hold when we emit multiple copies of
- the function. However, there's little else we can do. */
+ the function. However, there's little else we can do.
+
+ Also, by default, the typeinfo implementation for the new ABI
+ assumes that there will be only one copy of the string used as
+ the name for each type. Therefore, if weak symbols are
+ unavailable, the run-time library should perform a more
+ conservative check; it should perform a string comparison,
+ rather than an address comparison. */
TREE_PUBLIC (decl) = 0;
else
{
after a weak one is an error. Also, not making explicit
instantiations one_only means that we can end up with two copies of
some template instantiations. */
- if (! supports_one_only ())
+ if (! flag_weak)
return;
/* We can't set DECL_COMDAT on functions, or finish_file will think
for (method = TYPE_METHODS (type); method != NULL_TREE;
method = TREE_CHAIN (method))
if (DECL_VINDEX (method) != NULL_TREE
- && ! DECL_THIS_INLINE (method)
- && ! DECL_PURE_VIRTUAL_P (method))
+ && ! DECL_DECLARED_INLINE_P (method)
+ && (! DECL_PURE_VIRTUAL_P (method)
+#if 0
+ /* This would be nice, but we didn't think of it in time. */
+ || DECL_DESTRUCTOR_P (method)
+#endif
+ ))
return method;
return NULL_TREE;
else if (CLASSTYPE_INTERFACE_KNOWN (type))
{
TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
+ DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (type);
DECL_INTERFACE_KNOWN (decl) = 1;
}
else
if (CLASSTYPE_INTERFACE_ONLY (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)))
+ if ((*targetm.valid_type_attribute) (ctype,
+ TYPE_ATTRIBUTES (ctype),
+ get_identifier ("dllimport"),
+ NULL_TREE)
+ && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
import_export = -1;
- else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
+ else if ((*targetm.valid_type_attribute) (ctype,
+ TYPE_ATTRIBUTES (ctype),
+ get_identifier ("dllexport"),
+ NULL_TREE)
+ && 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)
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
- CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = (import_export > 0);
CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0);
}
}
if (flag_weak)
comdat_linkage (vars);
- rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
+ rest_of_decl_compilation (vars, NULL, 1, 1);
if (flag_vtable_gc)
output_vtable_inherit (vars);
if ((DECL_IMPLICIT_INSTANTIATION (decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
&& (flag_implicit_templates
- || (flag_implicit_inline_templates && DECL_THIS_INLINE (decl))))
+ || (flag_implicit_inline_templates
+ && DECL_DECLARED_INLINE_P (decl))))
{
if (!TREE_PUBLIC (decl))
/* Templates are allowed to have internal linkage. See
}
else if (DECL_FUNCTION_MEMBER_P (decl))
{
- tree ctype = DECL_CONTEXT (decl);
- import_export_class (ctype);
- if (CLASSTYPE_INTERFACE_KNOWN (ctype)
- && (flag_new_abi
- ? (! DECL_THIS_INLINE (decl))
- : (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl))))
+ if (!DECL_DECLARED_INLINE_P (decl))
{
- DECL_NOT_REALLY_EXTERN (decl)
- = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
- || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines
- && !DECL_VINDEX (decl)));
-
- /* Always make artificials weak. */
- if (DECL_ARTIFICIAL (decl) && flag_weak)
- comdat_linkage (decl);
- else
- maybe_make_one_only (decl);
+ tree ctype = DECL_CONTEXT (decl);
+ import_export_class (ctype);
+ if (CLASSTYPE_INTERFACE_KNOWN (ctype))
+ {
+ DECL_NOT_REALLY_EXTERN (decl)
+ = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
+ || (DECL_DECLARED_INLINE_P (decl)
+ && ! flag_implement_inlines
+ && !DECL_VINDEX (decl)));
+
+ /* Always make artificials weak. */
+ if (DECL_ARTIFICIAL (decl) && flag_weak)
+ comdat_linkage (decl);
+ else
+ maybe_make_one_only (decl);
+ }
}
else
comdat_linkage (decl);
}
- else if (DECL_TINFO_FN_P (decl))
+ else if (tinfo_decl_p (decl, 0))
{
tree ctype = TREE_TYPE (DECL_NAME (decl));
{
DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype)
- || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines
+ || (DECL_DECLARED_INLINE_P (decl)
+ && ! flag_implement_inlines
&& !DECL_VINDEX (decl)));
/* Always make artificials weak. */
tree sname;
tree guard;
- /* For a local variable, under the old ABI, we do not try to get a
- unique mangled name for the DECL. */
- if (!flag_new_abi && DECL_FUNCTION_SCOPE_P (decl))
- {
- guard = get_temp_name (integer_type_node);
- cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
- return guard;
- }
-
- if (!flag_new_abi)
- /* For struct X foo __attribute__((weak)), there is a counter
- __snfoo. Since base is already an assembler name, sname should
- be globally unique */
- sname = get_id_2 ("__sn", DECL_ASSEMBLER_NAME (decl));
- else
- sname = mangle_guard_variable (decl);
-
+ sname = mangle_guard_variable (decl);
guard = IDENTIFIER_GLOBAL_VALUE (sname);
if (! guard)
{
/* Under the new ABI, we use a type that is big enough to
contain a mutex as well as an integer counter. */
- if (flag_new_abi)
- guard_type = long_long_integer_type_node;
- else
- guard_type = integer_type_node;
-
+ guard_type = long_long_integer_type_node;
guard = build_decl (VAR_DECL, sname, guard_type);
- TREE_PUBLIC (guard) = 1;
+
+ /* The guard should have the same linkage as what it guards. */
+ TREE_PUBLIC (guard) = TREE_PUBLIC (decl);
+ TREE_STATIC (guard) = TREE_STATIC (decl);
+ DECL_COMMON (guard) = DECL_COMMON (decl);
+ DECL_ONE_ONLY (guard) = DECL_ONE_ONLY (decl);
+ if (TREE_PUBLIC (decl))
+ DECL_WEAK (guard) = DECL_WEAK (decl);
+
DECL_ARTIFICIAL (guard) = 1;
- TREE_STATIC (guard) = 1;
TREE_USED (guard) = 1;
- DECL_COMMON (guard) = 1;
pushdecl_top_level (guard);
cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
}
get_guard_bits (guard)
tree guard;
{
- if (!flag_new_abi)
- return guard;
-
/* Under the new ABI, we only set the first byte of the guard,
in order to leave room for a mutex in the high-order bits. */
guard = build1 (ADDR_EXPR,
linker sorts in increasing order. */
MAX_INIT_PRIORITY - initp);
named_section (NULL_TREE, buf, 0);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, fnname),
+ assemble_integer (XEXP (DECL_RTL (fn), 0),
POINTER_SIZE / BITS_PER_UNIT, 1);
}
#endif
my_friendly_assert (initp, 20000629);
guard_cond = get_guard_cond (guard);
}
- /* Under the old ABI, e do initializations only if the GUARD is
- zero, i.e., if we are the first to initialize the variable.
- We do destructions only if the GUARD is one, i.e., if we are
- the last to destroy the variable. */
+ /* If we don't have __cxa_atexit, then we will be running
+ destructors from .fini sections, or their equivalents. So,
+ we need to know how many times we've tried to initialize this
+ object. We do initializations only if the GUARD is zero,
+ i.e., if we are the first to initialize the variable. We do
+ destructions only if the GUARD is one, i.e., if we are the
+ last to destroy the variable. */
else if (initp)
guard_cond
= cp_build_binary_op (EQ_EXPR,
finish_if_stmt_cond (cond, guard_if_stmt);
- /* Under the new ABI, we have not already set the GUARD, so we must
- do so now. */
- if (guard && initp && flag_new_abi)
+ /* If we're using __cxa_atexit, we have not already set the GUARD,
+ so we must do so now. */
+ if (guard && initp && flag_use_cxa_atexit)
finish_expr_stmt (set_guard (guard));
return guard_if_stmt;
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expr = build_aggr_init (decl, init, 0);
- else if (TREE_CODE (init) == TREE_VEC)
- expr = build_vec_init (decl, TREE_VEC_ELT (init, 0),
- TREE_VEC_ELT (init, 1),
- TREE_VEC_ELT (init, 2), 0);
else
{
expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
timevar_push (TV_VARCONST);
- if (new_abi_rtti_p ())
- emit_support_tinfos ();
+ emit_support_tinfos ();
do
{
/* Write out needed type info variables. Writing out one variable
might cause others to be needed. */
- if (new_abi_rtti_p ()
- && walk_globals (tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
+ if (walk_globals (tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
reconsider = 1;
/* The list of objects with static storage duration is built up
finish_function doesn't clean things up, and we end
up with CURRENT_FUNCTION_DECL set. */
push_to_top_level ();
- if (DECL_TINFO_FN_P (decl))
- synthesize_tinfo_fn (decl);
- else
- synthesize_method (decl);
+ synthesize_method (decl);
pop_from_top_level ();
reconsider = 1;
}
}
- /* Mark all functions that might deal with exception-handling as
- referenced. */
- mark_all_runtime_matches ();
-
/* We lie to the back-end, pretending that some functions are
not defined when they really are. This keeps these functions
from being put out unnecessarily. But, we must stop lying
/* The entire file is now complete. If requested, dump everything
to a file. */
- if (flag_dump_translation_unit)
- dump_node_to_file (global_namespace, flag_dump_translation_unit);
+ {
+ int flags;
+ FILE *stream = dump_begin (TDI_all, &flags);
+ if (stream)
+ {
+ dump_node (global_namespace, flags & ~TDF_SLIM, stream);
+ dump_end (TDI_all, stream);
+ }
+ }
+
/* If there's some tool that wants to examine the entire translation
unit, let it do so now. */
if (back_end_hook)
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 build_nt (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)));
finish_decl_parsing (decl)
tree decl;
{
- extern int current_class_depth;
-
switch (TREE_CODE (decl))
{
case IDENTIFIER_NODE:
if (!old)
/* No old declaration at all. */
goto complain;
+ /* A template can be explicitly specialized in any namespace. */
+ if (processing_explicit_instantiation)
+ return;
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
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)))
+ if (TREE_PURPOSE (friends) == error_mark_node && TREE_VALUE (friends)
+ && decl_namespace (TREE_VALUE (friends)) == context)
+ if (add_function (k, TREE_VALUE (friends)))
return 1;
/* Process template arguments. */
if (TREE_CODE (decl) == SCOPE_REF
&& TREE_OPERAND (decl, 0) == fake_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);
}
A using-declaration for a class member shall be a
member-declaration. */
- if (TREE_CODE (*scope) != NAMESPACE_DECL)
+ if (!processing_template_decl
+ && TREE_CODE (*scope) != NAMESPACE_DECL)
{
if (TYPE_P (*scope))
cp_error ("`%T' is not a namespace", *scope);
{
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))))
+ if (new_fn == old_fn)
+ /* The function already exists in the current namespace. */
+ break;
+ else if (OVL_USED (tmp1))
+ continue; /* this is a using decl */
+ else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
+ TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
{
- if (!(DECL_EXTERN_C_P (new_fn)
- && DECL_EXTERN_C_P (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);
+ /* There was already a non-using declaration in
+ this scope with the same parameter types. If both
+ are the same extern "C" functions, that's ok. */
+ if (!decls_match (new_fn, old_fn))
+ 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
if (decl == NULL_TREE)
return;
+ if (building_stmt_tree ()
+ && at_function_scope_p ())
+ add_decl_stmt (decl);
+
oldval = lookup_name_current_level (name);
oldtype = lookup_type_current_level (name);
{
if (namespace == fake_std_node)
return;
+ if (building_stmt_tree ())
+ add_stmt (build_stmt (USING_STMT, namespace));
+
/* 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);
+ if (!processing_template_decl)
+ cp_error ("namespace `%T' undeclared", namespace);
return;
}
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
- cp_error ("`%T' is not a namespace", namespace);
+ if (!processing_template_decl)
+ cp_error ("`%T' is not a namespace", namespace);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
void
init_decl2 ()
{
- ggc_add_tree_root (&decl_namespace_list, 1);
ggc_add_tree_varray_root (&deferred_fns, 1);
ggc_add_tree_varray_root (&pending_statics, 1);
ggc_add_tree_varray_root (&ssdf_decls, 1);
ggc_add_tree_root (&ssdf_decl, 1);
ggc_add_tree_root (&priority_decl, 1);
ggc_add_tree_root (&initialize_p_decl, 1);
- ggc_add_tree_root (&pending_vtables, 1);
}