/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
+extern tree builtin_return_address_fndecl;
+
extern struct obstack permanent_obstack;
extern int current_class_depth;
+extern tree cleanups_this_call;
+
+extern tree static_ctors, static_dtors;
+
/* Stack of places to restore the search obstack back to. */
/* Obstack used for remembering local class declarations (like
#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
+#ifndef BOOL_TYPE_SIZE
+#ifdef SLOW_BYTE_ACCESS
+#define BOOL_TYPE_SIZE BITS_PER_WORD
+#else
+#define BOOL_TYPE_SIZE BITS_PER_UNIT
+#endif
+#endif
+
/* We let tm.h override the types used here, to handle trivial differences
such as the choice of unsigned int or long unsigned int for size_t.
When machines start needing nontrivial differences in the size type,
#define WCHAR_TYPE "int"
#endif
-#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
- define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME)
-#define auto_function(NAME, TYPE, CODE) \
- do { \
- tree __name = NAME; \
- tree __type = TYPE; \
- define_function (IDENTIFIER_POINTER (__name), __type, CODE, \
- (void (*)())push_overloaded_decl_1, \
- IDENTIFIER_POINTER (build_decl_overload (__name, TYPE_ARG_TYPES (__type), 0)));\
- } while (0)
-
static tree grokparms PROTO((tree, int));
static tree lookup_nested_type PROTO((tree, tree));
static char *redeclaration_error_message PROTO((tree, tree));
static void grok_op_properties PROTO((tree, int, int));
-static void deactivate_exception_cleanups PROTO((void));
tree define_function
PROTO((char *, tree, enum built_in_function, void (*)(), char *));
tree signed_wchar_type_node;
tree unsigned_wchar_type_node;
+tree wchar_decl_node;
+
tree float_type_node;
tree double_type_node;
tree long_double_type_node;
tree wchar_array_type_node;
+/* The bool data type, and constants */
+tree boolean_type_node, boolean_true_node, boolean_false_node;
+
/* type `int ()' -- used for implicit declaration of functions. */
tree default_function_type;
/* C++ extensions */
tree vtable_entry_type;
tree delta_type_node;
-tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node;
+#if 0
+/* Old rtti stuff. */
+tree __baselist_desc_type_node;
+tree __i_desc_type_node, __m_desc_type_node;
tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type;
+#endif
+tree __t_desc_type_node, __tp_desc_type_node;
+tree __access_mode_type_node;
+tree __bltn_desc_type_node, __user_desc_type_node, __class_desc_type_node;
+tree __ptr_desc_type_node, __attr_desc_type_node, __func_desc_type_node;
+tree __ptmf_desc_type_node, __ptmd_desc_type_node;
+#if 0
+/* Not needed yet? May be needed one day? */
+tree __bltn_desc_array_type, __user_desc_array_type, __class_desc_array_type;
+tree __ptr_desc_array_type, __attr_dec_array_type, __func_desc_array_type;
+tree __ptmf_desc_array_type, __ptmd_desc_array_type;
+#endif
+
tree class_star_type_node;
tree class_type_node, record_type_node, union_type_node, enum_type_node;
-tree exception_type_node, unknown_type_node;
+tree unknown_type_node;
tree opaque_type_node, signature_type_node;
tree sigtable_entry_type;
tree maybe_gc_cleanup;
-/* Used for virtual function tables. */
-tree vtbl_mask;
-
/* Array type `vtable_entry_type[]' */
tree vtbl_type_node;
-/* Static decls which do not have static initializers have no
- initializers as far as GNU C is concerned. EMPTY_INIT_NODE
- is a static initializer which makes varasm code place the decl
- in data rather than in bss space. Such gymnastics are necessary
- to avoid the problem that the linker will not include a library
- file if all the library appears to contribute are bss variables. */
-
-tree empty_init_node;
-
/* In a destructor, the point at which all derived class destroying
has been done, just before any base class destroying will be done. */
tree ctor_label;
-/* A FUNCTION_DECL which can call `unhandled_exception'.
- Not necessarily the one that the user will declare,
- but sufficient to be called by routines that want to abort the program. */
-
-tree unhandled_exception_fndecl;
-
/* A FUNCTION_DECL which can call `abort'. Not necessarily the
one that the user will declare, but sufficient to be called
by routines that want to abort the program. */
in the TREE_PURPOSE slot. */
tree static_aggregates;
-/* A list of functions which were declared inline, but later had their
- address taken. Used only for non-virtual member functions, since we can
- find other functions easily enough. */
-tree pending_addressable_inlines;
-
-/* A list of overloaded functions which we should forget ever
- existed, such as functions declared in a function's scope,
- once we leave that function's scope. */
-static tree overloads_to_forget;
-
/* -- end of C++ */
/* Two expressions that are constants with value zero.
static tree enum_next_value;
+/* Nonzero means that there was overflow computing enum_next_value. */
+
+static int enum_overflow;
+
/* Parsing a function declarator leaves a list of parameter names
or a chain or parameter decls here. */
static int warn_about_return_type;
-/* Nonzero when starting a function declared `extern inline'. */
-
-static int current_extern_inline;
-
/* Nonzero means give `double' the same size as `float'. */
extern int flag_short_double;
extern int flag_no_builtin;
-/* Nonzero means do emit exported implementations of functions even if
- they can be inlined. */
+/* Nonzero means don't recognize the non-ANSI builtin functions.
+ -ansi sets this. */
-extern int flag_implement_inlines;
+extern int flag_no_nonansi_builtin;
-/* Nonzero means handle things in ANSI, instead of GNU fashion. This
- flag should be tested for language behavior that's different between
- ANSI and GNU, but not so horrible as to merit a PEDANTIC label. */
+/* Nonzero means enable obscure ANSI features and disable GNU extensions
+ that might cause ANSI-compliant code to be miscompiled. */
extern int flag_ansi;
/* 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 flaging multiple
+ .common instead of .data at the expense of not flagging multiple
definitions. */
extern int flag_conserve_space;
extern tree *current_lang_base, *current_lang_stack;
\f
-/* C and C++ flags are in cp-decl2.c. */
+/* C and C++ flags are in decl2.c. */
/* Set to 0 at beginning of a constructor, set to 1
if that function does an allocation before referencing its
int current_function_obstack_usage;
-/* Flag used when debugging cp-spew.c */
+/* Flag used when debugging spew.c */
extern int spew_debug;
/* Number of decls in `names' that have incomplete
structure or union types. */
- unsigned short n_incomplete;
+ unsigned int n_incomplete;
/* 1 for the level that holds the parameters of a function.
2 for the level that holds a class declaration.
unsigned more_cleanups_ok : 1;
unsigned have_cleanups : 1;
- /* Nonzero if this level can safely have additional
- exception-raising statements added to it. */
- unsigned more_exceptions_ok : 1;
- unsigned have_exceptions : 1;
-
/* Nonzero if we should accept any name as an identifier in
this scope. This happens in some template definitions. */
unsigned accept_any : 1;
current_binding_level = newlevel;
newlevel->tag_transparent = tag_transparent;
newlevel->more_cleanups_ok = 1;
- newlevel->more_exceptions_ok = 1;
newlevel->keep = keep;
#if defined(DEBUG_CP_BINDING_LEVELS)
newlevel->binding_depth = binding_depth;
current_binding_level->parm_flag = 1;
}
-/* Identify this binding level as a level of a default exception handler. */
-
-void
-declare_implicit_exception ()
-{
- current_binding_level->parm_flag = 3;
-}
-
-/* Nonzero if current binding contour contains expressions
- that might raise exceptions. */
-
-int
-have_exceptions_p ()
-{
- return current_binding_level->have_exceptions;
-}
-
void
declare_uninstantiated_type_level ()
{
if (TREE_CODE (decl) == FUNCTION_DECL
&& ! TREE_ASM_WRITTEN (decl)
&& DECL_INITIAL (decl) != NULL_TREE
- && TREE_ADDRESSABLE (decl))
+ && TREE_ADDRESSABLE (decl)
+ && decl_function_context (decl) == current_function_decl)
{
/* If this decl was copied from a file-scope decl
on account of a block-scope extern decl,
}
/* Take care of compiler's internal binding structures. */
- if (tmp == 2 && !implicit_try_block)
+ if (tmp == 2)
{
#if 0
/* We did not call push_momentary for this
while (current_binding_level->parm_flag == 2);
}
-/* ...and a poplevel for class declarations. */
+/* ...and a poplevel for class declarations. FORCE is used to force
+ clearing out of CLASS_VALUEs after a class definition. */
tree
-poplevel_class ()
+poplevel_class (force)
+ int force;
{
register struct binding_level *level = class_binding_level;
tree block = NULL_TREE;
for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed))
IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
/* If we're leaving a toplevel class, don't bother to do the setting
- of IDENTIFER_CLASS_VALUE to NULL_TREE, since first of all this slot
+ of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot
shouldn't even be used when current_class_type isn't set, and second,
- if we don't touch it here, we're able to use the caching effect if the
+ if we don't touch it here, we're able to use the cache effect if the
next time we're entering a class scope, it is the same class. */
- if (current_class_depth != 1)
+ if (current_class_depth != 1 || force)
for (shadowed = level->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
fprintf (stderr, " more-cleanups-ok");
if (lvl->have_cleanups)
fprintf (stderr, " have-cleanups");
- if (lvl->more_exceptions_ok)
- fprintf (stderr, " more-exceptions-ok");
- if (lvl->have_exceptions)
- fprintf (stderr, " have-exceptions");
fprintf (stderr, "\n");
if (lvl->names)
{
tree old_bindings;
struct saved_scope *prev;
tree class_name, class_type, class_decl, function_decl;
+ tree base_init_list, member_init_list;
struct binding_level *class_bindings;
tree previous_class_type;
+ tree *lang_base, *lang_stack, lang_name;
+ int lang_stacksize;
+ tree named_labels;
};
static struct saved_scope *current_saved_scope;
extern tree prev_class_type;
void
push_to_top_level ()
{
+ extern int current_lang_stacksize;
struct saved_scope *s =
(struct saved_scope *) xmalloc (sizeof (struct saved_scope));
struct binding_level *b = current_binding_level;
s->class_type = current_class_type;
s->class_decl = current_class_decl;
s->function_decl = current_function_decl;
+ s->base_init_list = current_base_init_list;
+ s->member_init_list = current_member_init_list;
s->class_bindings = class_binding_level;
s->previous_class_type = previous_class_type;
+ s->lang_stack = current_lang_stack;
+ s->lang_base = current_lang_base;
+ s->lang_stacksize = current_lang_stacksize;
+ s->lang_name = current_lang_name;
+ s->named_labels = named_labels;
current_class_name = current_class_type = current_class_decl = NULL_TREE;
current_function_decl = NULL_TREE;
class_binding_level = (struct binding_level *)0;
previous_class_type = NULL_TREE;
+ current_lang_stacksize = 10;
+ current_lang_stack = current_lang_base
+ = (tree *) xmalloc (current_lang_stacksize * sizeof (tree));
+ current_lang_name = lang_name_cplusplus;
+ strict_prototype = strict_prototypes_lang_cplusplus;
+ named_labels = NULL_TREE;
s->prev = current_saved_scope;
s->old_bindings = old_bindings;
void
pop_from_top_level ()
{
+ extern int current_lang_stacksize;
struct saved_scope *s = current_saved_scope;
tree t;
C_C_D = CLASSTYPE_INST_VAR (current_class_type);
else
C_C_D = NULL_TREE;
+ current_base_init_list = s->base_init_list;
+ current_member_init_list = s->member_init_list;
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
previous_class_type = s->previous_class_type;
+ free (current_lang_base);
+ current_lang_base = s->lang_base;
+ current_lang_stack = s->lang_stack;
+ current_lang_name = s->lang_name;
+ current_lang_stacksize = s->lang_stacksize;
+ if (current_lang_name == lang_name_cplusplus)
+ strict_prototype = strict_prototypes_lang_cplusplus;
+ else if (current_lang_name == lang_name_c)
+ strict_prototype = strict_prototypes_lang_c;
+ named_labels = s->named_labels;
+
free (s);
}
\f
set_nested_typename (decl, classname, name, type)
tree decl, classname, name, type;
{
+ char *buf;
my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136);
- if (classname != NULL_TREE)
- {
- char *buf;
- my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137);
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138);
- buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname)
- + IDENTIFIER_LENGTH (name));
- sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
- IDENTIFIER_POINTER (name));
- DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
-
- /* This is a special usage of IDENTIFIER_TYPE_VALUE which have no
- correspondence in any binding_level. This is ok since the
- DECL_NESTED_TYPENAME is just a convenience identifier whose
- IDENTIFIER_TYPE_VALUE will remain constant from now on. */
- SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type);
+
+ /* No need to do this for anonymous names, since they're unique. */
+ if (ANON_AGGRNAME_P (name))
+ {
+ DECL_NESTED_TYPENAME (decl) = name;
+ return;
}
- else
- DECL_NESTED_TYPENAME (decl) = name;
+
+ if (classname == NULL_TREE)
+ classname = get_identifier ("");
+
+ my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137);
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138);
+ buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname)
+ + IDENTIFIER_LENGTH (name));
+ sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
+ IDENTIFIER_POINTER (name));
+ DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
+ TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
+
+ /* Create an extra decl so that the nested name will have a type value
+ where appropriate. */
+ {
+ tree nested, type_decl;
+ nested = DECL_NESTED_TYPENAME (decl);
+ type_decl = build_decl (TYPE_DECL, nested, type);
+ DECL_NESTED_TYPENAME (type_decl) = nested;
+ SET_DECL_ARTIFICIAL (type_decl);
+ /* Mark the TYPE_DECL node created just above as a gratuitous one so that
+ dwarfout.c will know not to generate a TAG_typedef DIE for it, and
+ sdbout.c won't try to output a .def for "::foo". */
+ DECL_IGNORED_P (type_decl) = 1;
+
+ /* Remove this when local classes are fixed. */
+ SET_IDENTIFIER_TYPE_VALUE (nested, type);
+
+ pushdecl_nonclass_level (type_decl);
+ }
+}
+
+/* Pop off extraneous binding levels left over due to syntax errors. */
+void
+pop_everything ()
+{
+#ifdef DEBUG_CP_BINDING_LEVELS
+ fprintf (stderr, "XXX entering pop_everything ()\n");
+#endif
+ while (current_binding_level != global_binding_level
+ && ! current_binding_level->pseudo_global)
+ {
+ if (class_binding_level)
+ pop_nested_class (1);
+ else
+ poplevel (0, 0, 0);
+ }
+#ifdef DEBUG_CP_BINDING_LEVELS
+ fprintf (stderr, "XXX leaving pop_everything ()\n");
+#endif
}
#if 0 /* not yet, should get fixed properly later */
incorrect results with `-g' unless they duplicate this code.
This is currently needed mainly for dbxout.c, but we can make
- use of it in cp-method.c later as well. */
+ use of it in method.c later as well. */
tree
make_type_decl (name, type)
tree name, type;
#endif
/* Push a tag name NAME for struct/class/union/enum type TYPE.
- Normally put into into the inner-most non-tag-tranparent scope,
+ Normally put into into the inner-most non-tag-transparent scope,
but if GLOBALIZE is true, put it in the inner-most non-class scope.
The latter is needed for implicit declarations. */
int globalize;
{
register struct binding_level *b;
- tree t_context = 0;
+ tree context = 0;
+ tree c_decl = 0;
b = inner_binding_level;
while (b->tag_transparent
if (name)
{
- t_context = type ? TYPE_CONTEXT(type) : NULL_TREE;
- if (!t_context && !globalize)
- t_context = current_class_type;
+ context = type ? TYPE_CONTEXT (type) : NULL_TREE;
+ if (! context && ! globalize)
+ context = current_scope ();
+ if (context)
+ c_decl = TREE_CODE (context) == FUNCTION_DECL
+ ? context : TYPE_MAIN_DECL (context);
+#if 0
/* Record the identifier as the type's name if it has none. */
if (TYPE_NAME (type) == NULL_TREE)
TYPE_NAME (type) = name;
+#endif
/* Do C++ gratuitous typedefing. */
- if (IDENTIFIER_TYPE_VALUE (name) != type
- && (TREE_CODE (type) != RECORD_TYPE
- || b->parm_flag != 2
- || !CLASSTYPE_DECLARED_EXCEPTION (type)))
+ if (IDENTIFIER_TYPE_VALUE (name) != type)
{
register tree d;
int newdecl = 0;
if (b->parm_flag != 2
|| TYPE_SIZE (current_class_type) != NULL_TREE)
{
- if (current_lang_name == lang_name_cplusplus)
- d = lookup_nested_type (type,
- t_context ? TYPE_NAME (t_context) : NULL_TREE);
- else
- d = NULL_TREE;
+ d = lookup_nested_type (type, c_decl);
if (d == NULL_TREE)
{
#else
d = build_decl (TYPE_DECL, name, type);
#endif
+ SET_DECL_ARTIFICIAL (d);
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
{
else
d = TYPE_NAME (d);
+ TYPE_NAME (type) = d;
+
/* If it is anonymous, then we are called from pushdecl,
- and we don't want to infinitely recurse. Also, if the
- name is already in scope, we don't want to push it
- again--pushdecl is only for pushing new decls. */
- if (! ANON_AGGRNAME_P (name)
- && TYPE_NAME (type)
- && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL
- || lookup_name (name, 1) != TYPE_NAME (type)))
+ and we don't want to infinitely recurse. */
+ if (! ANON_AGGRNAME_P (name))
{
if (b->parm_flag == 2)
d = pushdecl_class_level (d);
{
/* Make nested declarations go into class-level scope. */
newdecl = 1;
- d = build_lang_field_decl (TYPE_DECL, name, type);
+ d = build_decl (TYPE_DECL, name, type);
+ SET_DECL_ARTIFICIAL (d);
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
{
DECL_IGNORED_P (d) = 1;
}
#endif /* DWARF_DEBUGGING_INFO */
+
+ TYPE_MAIN_DECL (type) = d;
+
/* Make sure we're in this type's scope when we push the
decl for a template, otherwise class_binding_level will
be NULL and we'll end up dying inside of
if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
popclass (0);
}
- if (write_symbols != DWARF_DEBUG)
- {
- if (ANON_AGGRNAME_P (name))
- DECL_IGNORED_P (d) = 1;
- }
- TYPE_NAME (type) = d;
-
- if ((t_context == NULL_TREE
- && current_function_decl == NULL_TREE)
- || current_lang_name != lang_name_cplusplus)
- /* Non-nested class. */
- DECL_NESTED_TYPENAME (d) = name;
- else if (current_function_decl != NULL_TREE)
- {
- /* Function-nested class. */
- set_nested_typename (d,
- DECL_ASSEMBLER_NAME (current_function_decl), name, type);
- /* This builds the links for classes nested in fn scope. */
- DECL_CONTEXT (d) = current_function_decl;
- }
-/* else if (TYPE_SIZE (current_class_type) == NULL_TREE)
-*/
- else if (t_context && TREE_CODE (t_context) == RECORD_TYPE)
+ if (newdecl)
{
- /* Class-nested class. */
- set_nested_typename (d,
- DECL_NESTED_TYPENAME (TYPE_NAME (t_context)), name, type);
- /* This builds the links for classes nested in type scope. */
- DECL_CONTEXT (d) = t_context;
- DECL_CLASS_CONTEXT (d) = t_context;
+ if (write_symbols != DWARF_DEBUG)
+ {
+ if (ANON_AGGRNAME_P (name))
+ DECL_IGNORED_P (d) = 1;
+ }
+
+ if (context == NULL_TREE)
+ /* Non-nested class. */
+ set_nested_typename (d, NULL_TREE, name, type);
+ else if (context && TREE_CODE (context) == FUNCTION_DECL)
+ /* Function-nested class. */
+ set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl),
+ name, type);
+ else /* if (context && IS_AGGR_TYPE (context)) */
+ /* Class-nested class. */
+ set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
+ name, type);
+
+ DECL_CONTEXT (d) = context;
+ TYPE_CONTEXT (type) = DECL_CONTEXT (d);
+ DECL_ASSEMBLER_NAME (d)
+ = get_identifier (build_overload_name (type, 1, 1));
}
- TYPE_CONTEXT (type) = DECL_CONTEXT (d);
- if (newdecl)
- DECL_ASSEMBLER_NAME (d)
- = get_identifier (build_overload_name (type, 1, 1));
}
if (b->parm_flag == 2)
{
For C++, we must compare the parameter list so that `int' can match
`int&' in a parameter position, but `int&' is not confused with
`const int&'. */
-static int
+int
decls_match (newdecl, olddecl)
tree newdecl, olddecl;
{
int types_match;
- if (TREE_CODE (newdecl) == FUNCTION_DECL && TREE_CODE (olddecl) == FUNCTION_DECL)
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && TREE_CODE (olddecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
tree f2 = TREE_TYPE (olddecl);
is METHOD_TYPE. Change that to FUNCTION_TYPE, and
proceed. */
if (TREE_CODE (f1) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (olddecl))
- revert_static_member_fn (&f1, &newdecl, &p1);
+ revert_static_member_fn (&newdecl, &f1, &p1);
else if (TREE_CODE (f2) == METHOD_TYPE
&& DECL_STATIC_FUNCTION_P (newdecl))
- revert_static_member_fn (&f2, &olddecl, &p2);
+ revert_static_member_fn (&olddecl, &f2, &p2);
/* Here we must take care of the case where new default
parameters are specified. Also, warn if an old
return 0;
}
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)),
- TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 2))
- types_match = compparms (p1, p2, 2);
+ if (comptypes (TREE_TYPE (f1), TREE_TYPE (f2), 1))
+ {
+ if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
+ && p2 == NULL_TREE)
+ {
+ types_match = self_promoting_args_p (p1);
+ if (p1 == void_list_node)
+ TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
+ }
+ else if (!strict_prototypes_lang_c && DECL_LANGUAGE (olddecl)==lang_c
+ && DECL_LANGUAGE (newdecl) == lang_c && p1 == NULL_TREE)
+ {
+ types_match = self_promoting_args_p (p2);
+ TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
+ }
+ else
+ types_match = compparms (p1, p2, 3);
+ }
else
types_match = 0;
}
+ else if (TREE_CODE (newdecl) == TEMPLATE_DECL
+ && TREE_CODE (olddecl) == TEMPLATE_DECL)
+ {
+ tree newargs = DECL_TEMPLATE_PARMS (newdecl);
+ tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
+ int i, len = TREE_VEC_LENGTH (newargs);
+
+ if (TREE_VEC_LENGTH (oldargs) != len)
+ return 0;
+
+ for (i = 0; i < len; i++)
+ {
+ tree newarg = TREE_VALUE (TREE_VEC_ELT (newargs, i));
+ tree oldarg = TREE_VALUE (TREE_VEC_ELT (oldargs, i));
+ if (TREE_CODE (newarg) != TREE_CODE (oldarg))
+ return 0;
+ else if (TREE_CODE (newarg) == TYPE_DECL)
+ /* continue */;
+ else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
+ return 0;
+ }
+
+ if (DECL_TEMPLATE_IS_CLASS (newdecl)
+ != DECL_TEMPLATE_IS_CLASS (olddecl))
+ types_match = 0;
+ else if (DECL_TEMPLATE_IS_CLASS (newdecl))
+ types_match = 1;
+ else
+ types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
+ DECL_TEMPLATE_RESULT (newdecl));
+ }
else
{
if (TREE_TYPE (newdecl) == error_mark_node)
types_match = TREE_TYPE (olddecl) == error_mark_node;
else if (TREE_TYPE (olddecl) == NULL_TREE)
types_match = TREE_TYPE (newdecl) == NULL_TREE;
+ else if (TREE_TYPE (newdecl) == NULL_TREE)
+ types_match = 0;
else
types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1);
}
= "`%D' was declared implicitly `extern' and later `static'";
if (flag_traditional
- || TREE_CODE (newdecl) == TYPE_DECL
- || (! warn_extern_inline
- && DECL_INLINE (newdecl)))
+ || TREE_CODE (newdecl) == TYPE_DECL)
return;
name = DECL_ASSEMBLER_NAME (newdecl);
- if (TREE_PUBLIC (name) && ! TREE_PUBLIC (newdecl))
+ if (TREE_PUBLIC (name) && DECL_THIS_STATIC (newdecl))
{
/* It's okay to redeclare an ANSI built-in function as static,
or to declare a non-ANSI built-in function as anything. */
If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
Otherwise, return 0. */
-static int
+int
duplicate_decls (newdecl, olddecl)
register tree newdecl, olddecl;
{
int new_defines_function;
tree previous_c_decl = NULL_TREE;
- if (TREE_CODE (newdecl) == FUNCTION_DECL
- && is_overloaded_fn (olddecl))
- {
- olddecl = get_first_fn (olddecl);
-
- while (olddecl)
- {
- if (DECL_LANGUAGE (olddecl) == lang_c)
- previous_c_decl = olddecl;
-
- /* Redeclaration. */
- if (decls_match (newdecl, olddecl))
- {
- types_match = 1;
- break;
- }
- /* Ambiguous overload. */
- else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
- TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2))
- break;
+ if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
+ DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl);
- /* Attempt to define multiple C-binding fns. */
- if (previous_c_decl)
- break;
-
- olddecl = DECL_CHAIN (olddecl);
- }
- if (!olddecl)
- {
- /* If we found no match, make this join the other
- overloaded decls. */
- DECL_OVERLOADED (newdecl) = 1;
- return 1;
- }
- }
- else
- types_match = decls_match (newdecl, olddecl);
+ types_match = decls_match (newdecl, olddecl);
if (TREE_CODE (olddecl) != TREE_LIST)
olddecl_friend = DECL_LANG_SPECIFIC (olddecl) && DECL_FRIEND_P (olddecl);
&& TREE_CODE (TREE_TYPE (olddecl)) == ERROR_MARK))
types_match = 1;
- if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
- {
- cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
- if (TREE_CODE (olddecl) == TREE_LIST)
- olddecl = TREE_VALUE (olddecl);
- cp_error_at ("previous declaration of `%#D'", olddecl);
-
- /* New decl is completely inconsistent with the old one =>
- tell caller to replace the old one. */
-
- return 0;
- }
-
if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
&& IDENTIFIER_IMPLICIT_DECL (DECL_ASSEMBLER_NAME (newdecl)) == olddecl)
/* If -traditional, avoid error for redeclaring fcn
after implicit decl. */
;
else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && (DECL_BUILT_IN (olddecl)
- || DECL_BUILT_IN_NONANSI (olddecl)))
+ && DECL_ARTIFICIAL (olddecl)
+ && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl)))
{
/* If you declare a built-in or predefined function name as static,
- the old definition is overridden,
- but optionally warn this was a bad choice of name. */
- if (! TREE_PUBLIC (newdecl))
+ the old definition is overridden, but optionally warn this was a
+ bad choice of name. Ditto for overloads. */
+ if (! DECL_PUBLIC (newdecl)
+ || (TREE_CODE (newdecl) == FUNCTION_DECL
+ && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl)))
{
if (warn_shadow)
cp_warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- newdecl);
+ olddecl);
/* Discard the old built-in function. */
return 0;
}
- /* Likewise, if the built-in is not ansi, then programs can
- override it even globally without an error. */
- else if (! DECL_BUILT_IN (olddecl))
- cp_warning ("library function `%#D' declared as non-function",
- newdecl);
-
- if (!types_match)
+ else if (! types_match)
{
+ if (TREE_CODE (newdecl) != FUNCTION_DECL)
+ {
+ /* If the built-in is not ansi, then programs can override
+ it even globally without an error. */
+ if (! DECL_BUILT_IN (olddecl))
+ cp_warning ("library function `%#D' redeclared as non-function `%#D'",
+ olddecl, newdecl);
+ else
+ {
+ cp_error ("declaration of `%#D'", newdecl);
+ cp_error ("conflicts with built-in declaration `%#D'",
+ olddecl);
+ }
+ return 0;
+ }
+
cp_warning ("declaration of `%#D'", newdecl);
cp_warning ("conflicts with built-in declaration `%#D'",
olddecl);
- return 0;
}
}
- else if (!types_match && previous_c_decl
- && DECL_LANGUAGE (newdecl) == lang_c)
+ else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
- cp_error ("declaration of C function `%#D' conflicts with", newdecl);
- cp_error_at ("previous declaration `%#D' here", previous_c_decl);
+ if ((TREE_CODE (newdecl) == FUNCTION_DECL
+ && TREE_CODE (olddecl) == TEMPLATE_DECL
+ && ! DECL_TEMPLATE_IS_CLASS (olddecl))
+ || (TREE_CODE (olddecl) == FUNCTION_DECL
+ && TREE_CODE (newdecl) == TEMPLATE_DECL
+ && ! DECL_TEMPLATE_IS_CLASS (newdecl)))
+ return 0;
+
+ cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
+ if (TREE_CODE (olddecl) == TREE_LIST)
+ olddecl = TREE_VALUE (olddecl);
+ cp_error_at ("previous declaration of `%#D'", olddecl);
+
+ /* New decl is completely inconsistent with the old one =>
+ tell caller to replace the old one. */
+
+ return 0;
}
else if (!types_match)
{
- tree oldtype = TREE_TYPE (olddecl);
- tree newtype = TREE_TYPE (newdecl);
- int give_error = 0;
-
- /* Already complained about this, so don't do so again. */
- if (current_class_type == NULL_TREE
- || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
+ if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
- give_error = 1;
-
- /* Since we're doing this before finish_struct can set the
- line number on NEWDECL, we just do a regular error here. */
- if (DECL_SOURCE_LINE (newdecl) == 0)
- cp_error ("conflicting types for `%#D'", newdecl);
- else
- cp_error_at ("conflicting types for `%#D'", newdecl);
+ /* The name of a class template may not be declared to refer to
+ any other template, class, function, object, namespace, value,
+ or type in the same scope. */
+ if (DECL_TEMPLATE_IS_CLASS (olddecl)
+ || DECL_TEMPLATE_IS_CLASS (newdecl))
+ {
+ cp_error ("declaration of template `%#D'", newdecl);
+ cp_error_at ("conflicts with previous declaration `%#D'",
+ olddecl);
+ }
+ return 0;
}
-
- /* Check for function type mismatch
- involving an empty arglist vs a nonempty one. */
- if (TREE_CODE (olddecl) == FUNCTION_DECL
- && comptypes (TREE_TYPE (oldtype),
- TREE_TYPE (newtype), 1)
- && ((TYPE_ARG_TYPES (oldtype) == NULL_TREE
- && DECL_INITIAL (olddecl) == NULL_TREE)
- || (TYPE_ARG_TYPES (newtype) == NULL_TREE
- && DECL_INITIAL (newdecl) == NULL_TREE)))
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
- /* Classify the problem further. */
- register tree t = TYPE_ARG_TYPES (oldtype);
-
- if (t == NULL_TREE)
- t = TYPE_ARG_TYPES (newtype);
- for (; t; t = TREE_CHAIN (t))
+ if (DECL_LANGUAGE (newdecl) == lang_c
+ && DECL_LANGUAGE (olddecl) == lang_c)
{
- register tree type = TREE_VALUE (t);
-
- if (TREE_CHAIN (t) == NULL_TREE && type != void_type_node)
- {
- give_error = 1;
- error ("A parameter list with an ellipsis can't match");
- error ("an empty parameter name list declaration.");
- break;
- }
-
- if (TYPE_MAIN_VARIANT (type) == float_type_node
- || C_PROMOTING_INTEGER_TYPE_P (type))
- {
- give_error = 1;
- error ("An argument type that has a default promotion");
- error ("can't match an empty parameter name list declaration.");
- break;
- }
+ cp_error ("declaration of C function `%#D' conflicts with",
+ newdecl);
+ cp_error_at ("previous declaration `%#D' here", olddecl);
}
+ else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
+ TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 3))
+ {
+ cp_error ("new declaration `%#D'", newdecl);
+ cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+ }
+ else
+ return 0;
}
- if (give_error)
- cp_error_at ("previous declaration as `%#D'", olddecl);
- /* There is one thing GNU C++ cannot tolerate: a constructor
- which takes the type of object being constructed.
- Farm that case out here. */
- if (TREE_CODE (newdecl) == FUNCTION_DECL
- && DECL_CONSTRUCTOR_P (newdecl))
+ /* Already complained about this, so don't do so again. */
+ else if (current_class_type == NULL_TREE
+ || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
{
- tree tmp = TREE_CHAIN (TYPE_ARG_TYPES (newtype));
-
- if (tmp != NULL_TREE
- && (TYPE_MAIN_VARIANT (TREE_VALUE (tmp))
- == TYPE_METHOD_BASETYPE (newtype)))
- {
- tree parm = TREE_CHAIN (DECL_ARGUMENTS (newdecl));
- tree argtypes
- = hash_tree_chain (build_reference_type (TREE_VALUE (tmp)),
- TREE_CHAIN (tmp));
-
- DECL_ARG_TYPE (parm)
- = TREE_TYPE (parm)
- = TYPE_REFERENCE_TO (TREE_VALUE (tmp));
-
- TREE_TYPE (newdecl) = newtype
- = build_cplus_method_type (TYPE_METHOD_BASETYPE (newtype),
- TREE_TYPE (newtype), argtypes);
- error ("constructor cannot take as argument the type being constructed");
- SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl), current_class_type);
- }
+ cp_error ("conflicting types for `%#D'", newdecl);
+ cp_error_at ("previous declaration as `%#D'", olddecl);
}
}
else
char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
- error_with_decl (newdecl, errmsg);
+ cp_error (errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
&& current_binding_level == global_binding_level)
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
- /* extern "C" int foo ();
- int foo () { bar (); }
- is OK. */
- if (current_lang_stack == current_lang_base)
- DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
- else
- {
- cp_error_at ("previous declaration of `%#D' with %L linkage",
- olddecl, DECL_LANGUAGE (olddecl));
- cp_error ("conflicts with new declaration with %L linkage",
- DECL_LANGUAGE (newdecl));
- }
+ {
+ /* extern "C" int foo ();
+ int foo () { bar (); }
+ is OK. */
+ if (current_lang_stack == current_lang_base)
+ DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
+ else
+ {
+ cp_error_at ("previous declaration of `%#D' with %L linkage",
+ olddecl, DECL_LANGUAGE (olddecl));
+ cp_error ("conflicts with new declaration with %L linkage",
+ DECL_LANGUAGE (newdecl));
+ }
+ }
+
+ if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ {
+ tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
+ tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
+ int i = 1;
+
+ if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
+ t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
+
+ for (; t1 && t1 != void_list_node;
+ t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
+ if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
+ {
+ if (simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
+ {
+ if (pedantic)
+ {
+ cp_pedwarn ("default argument given for parameter %d of `%#D'",
+ i, newdecl);
+ cp_pedwarn_at ("after previous specification in `%#D'",
+ olddecl);
+ }
+ }
+ else
+ {
+ cp_error ("default argument given for parameter %d of `%#D'",
+ i, newdecl);
+ cp_error_at ("conflicts with previous specification in `%#D'",
+ olddecl);
+ }
+ }
- /* These bits are logically part of the type. */
- if (pedantic
- && (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
- || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)))
- cp_error_at ("type qualifiers for `%D' conflict with previous decl", newdecl);
+ if (DECL_THIS_INLINE (newdecl) && ! DECL_THIS_INLINE (olddecl)
+ && TREE_ADDRESSABLE (olddecl))
+ cp_pedwarn ("`%#D' was used before it was declared inline",
+ newdecl);
+ }
+ /* These bits are logically part of the type for non-functions. */
+ else if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
+ || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
+ {
+ cp_pedwarn ("type qualifiers for `%#D'", newdecl);
+ cp_pedwarn_at ("conflict with previous decl `%#D'", olddecl);
+ }
}
/* If new decl is `static' and an `extern' was seen previously,
DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl);
if (DECL_CHAIN (newdecl) == NULL_TREE)
DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
+ if (DECL_NEXT_METHOD (newdecl) == NULL_TREE)
+ DECL_NEXT_METHOD (newdecl) = DECL_NEXT_METHOD (olddecl);
if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
+ DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
+ DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
+ DECL_ABSTRACT_VIRTUAL_P (newdecl) |= DECL_ABSTRACT_VIRTUAL_P (olddecl);
}
/* Deal with C++: must preserve virtual function table size. */
register tree newtype = TREE_TYPE (newdecl);
register tree oldtype = TREE_TYPE (olddecl);
+ DECL_NESTED_TYPENAME (newdecl) = DECL_NESTED_TYPENAME (olddecl);
+
if (newtype != error_mark_node && oldtype != error_mark_node
&& TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
{
CLASSTYPE_FRIEND_CLASSES (newtype)
= CLASSTYPE_FRIEND_CLASSES (oldtype);
}
+#if 0
/* why assert here? Just because debugging information is
messed up? (mrs) */
/* it happens on something like:
int x;
} Thing;
*/
-#if 0
- my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl), 139);
+ my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl),
+ 139);
#endif
}
/* Optionally warn about more than one declaration for the same name,
but don't warn about a function declaration followed by a definition. */
if (warn_redundant_decls
- && DECL_SOURCE_LINE (olddecl) != 0
+ && ! DECL_ARTIFICIAL (olddecl)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
/* Don't warn about extern decl followed by (tentative) definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl)))
{
cp_warning ("redundant redeclaration of `%D' in same scope", newdecl);
- cp_warning ("previous declaration of `%D'", olddecl);
+ cp_warning_at ("previous declaration of `%D'", olddecl);
}
/* Copy all the DECL_... slots specified in the new decl
{
/* Automatically handles default parameters. */
tree oldtype = TREE_TYPE (olddecl);
+ tree newtype;
+
+ /* Make sure we put the new type in the same obstack as the old one. */
+ if (oldtype)
+ push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
+ else
+ {
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ }
+
/* Merge the data types specified in the two decls. */
- tree newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
+ newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
if (TREE_CODE (newdecl) == VAR_DECL)
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
TREE_TYPE (olddecl) = build_exception_variant (ctype, newtype,
TYPE_RAISES_EXCEPTIONS (oldtype));
- if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE(olddecl), 0))
+ if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
{
- cp_error ("declaration of `%D' raises different exceptions...", newdecl);
+ cp_error ("declaration of `%D' throws different exceptions...",
+ newdecl);
cp_error_at ("...from previous declaration here", olddecl);
}
}
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
- if (oldtype != TREE_TYPE (newdecl))
- {
- if (TREE_TYPE (newdecl) != error_mark_node)
- layout_type (TREE_TYPE (newdecl));
- if (TREE_CODE (newdecl) != FUNCTION_DECL
- && TREE_CODE (newdecl) != TYPE_DECL
- && TREE_CODE (newdecl) != CONST_DECL)
- layout_decl (newdecl, 0);
- }
- else
- {
- /* Since the type is OLDDECL's, make OLDDECL's size go with. */
- DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
- }
+ if (oldtype != TREE_TYPE (newdecl)
+ && TREE_TYPE (newdecl) != error_mark_node)
+ layout_type (TREE_TYPE (newdecl));
+
+ if (TREE_CODE (newdecl) == VAR_DECL
+ || TREE_CODE (newdecl) == PARM_DECL
+ || TREE_CODE (newdecl) == RESULT_DECL
+ || TREE_CODE (newdecl) == FIELD_DECL
+ || TREE_CODE (newdecl) == TYPE_DECL)
+ layout_decl (newdecl, 0);
/* Merge the type qualifiers. */
if (TREE_READONLY (newdecl))
TREE_THIS_VOLATILE (olddecl) = 1;
/* Merge the initialization information. */
- if (DECL_INITIAL (newdecl) == NULL_TREE)
- DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+ if (DECL_INITIAL (newdecl) == NULL_TREE
+ && DECL_INITIAL (olddecl) != NULL_TREE)
+ {
+ DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+ DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
+ DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
+ }
+
+ /* Merge the section attribute.
+ We want to issue an error if the sections conflict but that must be
+ done later in decl_attributes since we are called before attributes
+ are assigned. */
+ if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
+ DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+
/* Keep the old rtl since we can safely use it, unless it's the
call to abort() used for abstract virtuals. */
if ((DECL_LANG_SPECIFIC (olddecl)
&& !DECL_ABSTRACT_VIRTUAL_P (olddecl))
|| DECL_RTL (olddecl) != DECL_RTL (abort_fndecl))
DECL_RTL (newdecl) = DECL_RTL (olddecl);
+
+ pop_obstacks ();
}
/* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */
}
/* Merge the storage class information. */
- if (DECL_EXTERNAL (newdecl))
+ if (DECL_EXTERNAL (newdecl) && ! DECL_INTERFACE_KNOWN (newdecl)
+ && ! (DECL_LANG_SPECIFIC (newdecl) && DECL_NOT_REALLY_EXTERN (newdecl)))
{
TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+ TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
- /* For functions, static overrides non-static. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
- TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
- /* This is since we don't automatically
- copy the attributes of NEWDECL into OLDDECL. */
- TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
- /* If this clears `static', clear it in the identifier too. */
- if (! TREE_PUBLIC (olddecl))
- TREE_PUBLIC (DECL_ASSEMBLER_NAME (olddecl)) = 0;
+ DECL_C_STATIC (newdecl) = DECL_C_STATIC (olddecl);
+ DECL_INTERFACE_KNOWN (newdecl) = DECL_INTERFACE_KNOWN (olddecl);
+ DECL_NOT_REALLY_EXTERN (newdecl) = DECL_NOT_REALLY_EXTERN (olddecl);
}
- else
- TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
}
else
{
TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
- /* A `const' which was not declared `extern' and is
- in static storage is invisible. */
+ /* A `const' which was not declared `extern' gets internal linkage. */
if (TREE_CODE (newdecl) == VAR_DECL
- && TREE_READONLY (newdecl) && TREE_STATIC (newdecl)
- && ! DECL_THIS_EXTERN (newdecl))
+ && TREE_READONLY (newdecl) && ! DECL_THIS_EXTERN (newdecl))
TREE_PUBLIC (newdecl) = 0;
- TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
- }
+ else
+ {
+ TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
- /* If either decl says `inline', this fn is inline,
- unless its definition was passed already. */
- if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
- DECL_INLINE (olddecl) = 1;
- DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+ /* If this clears PUBLIC, clear it in the identifier too. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL && ! TREE_PUBLIC (olddecl))
+ TREE_PUBLIC (DECL_ASSEMBLER_NAME (olddecl)) = 0;
+ }
+ }
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
+ DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl);
+
+ /* If either decl says `inline', this fn is inline, unless its
+ definition was passed already. */
+ if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
+ DECL_INLINE (olddecl) = 1;
+ DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+
+ if (! types_match)
+ {
+ DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
+ DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (newdecl);
+ DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
+ DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
+ DECL_RTL (olddecl) = DECL_RTL (newdecl);
+ }
if (new_defines_function)
/* If defining a function declared with other language
linkage, use the previously declared language linkage. */
if (DECL_BUILT_IN (olddecl))
{
DECL_BUILT_IN (newdecl) = 1;
- DECL_SET_FUNCTION_CODE (newdecl, DECL_FUNCTION_CODE (olddecl));
+ DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
/* If we're keeping the built-in definition, keep the rtl,
regardless of declaration matches. */
DECL_RTL (newdecl) = DECL_RTL (olddecl);
DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
- if (DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl))
+ if ((DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl)))
/* Previously saved insns go together with
the function's previous definition. */
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
if (DECL_ARGUMENTS (olddecl))
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
}
+ if (DECL_LANG_SPECIFIC (olddecl))
+ DECL_MAIN_VARIANT (newdecl) = DECL_MAIN_VARIANT (olddecl);
}
+ if (TREE_CODE (newdecl) == TEMPLATE_DECL)
+ {
+ if (DECL_TEMPLATE_INFO (olddecl)->length)
+ DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+ DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl);
+ DECL_TEMPLATE_INSTANTIATIONS (newdecl)
+ = DECL_TEMPLATE_INSTANTIATIONS (olddecl);
+ if (DECL_CHAIN (newdecl) == NULL_TREE)
+ DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
+ }
+
/* Now preserve various other info from the definition. */
TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
+ DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl);
/* Don't really know how much of the language-specific
values we should copy from old to new. */
{
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
+ DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
nglobals = len;
#endif
- /* Don't change DECL_CONTEXT of virtual methods. */
if (x != current_function_decl
- && (TREE_CODE (x) != FUNCTION_DECL
- || !DECL_VIRTUAL_P (x))
+ /* Don't change DECL_CONTEXT of virtual methods. */
+ && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
&& ! DECL_CONTEXT (x))
DECL_CONTEXT (x) = current_function_decl;
/* A local declaration for a function doesn't constitute nesting. */
#else
/* Type are looked up using the DECL_NAME, as that is what the rest of the
compiler wants to use. */
- if (TREE_CODE (x) == TYPE_DECL)
+ if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL)
name = DECL_NAME (x);
#endif
cp_error_at ("`%#D' used prior to declaration", x);
}
- if (t != NULL_TREE)
+ else if (t != NULL_TREE)
{
if (TREE_CODE (t) == PARM_DECL)
{
}
file = DECL_SOURCE_FILE (t);
line = DECL_SOURCE_LINE (t);
- }
- if (t != NULL_TREE
- && (TREE_CODE (t) != TREE_CODE (x) || is_overloaded_fn (t)))
- {
- if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL)
+ if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c)
+ || (TREE_CODE (x) == TEMPLATE_DECL
+ && ! DECL_TEMPLATE_IS_CLASS (x)))
+ && is_overloaded_fn (t))
+ /* don't do anything just yet */;
+ else if (t == wchar_decl_node)
{
- /* We do nothing special here, because C++ does such nasty
- things with TYPE_DECLs. Instead, just let the TYPE_DECL
- get shadowed, and know that if we need to find a TYPE_DECL
- for a given name, we can look in the IDENTIFIER_TYPE_VALUE
- slot of the identifier. */
- ;
+ if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
+ cp_pedwarn ("redeclaration of wchar_t as `%T'", TREE_TYPE (x));
+
+ /* Throw away the redeclaration. */
+ return t;
}
- else if (duplicate_decls (x, t))
- return t;
- }
- else if (t != NULL_TREE && duplicate_decls (x, t))
- {
-#if 0
- /* This is turned off until I have time to do it right (bpk). */
-
- /* Also warn if they did a prototype with `static' on it, but
- then later left the `static' off. */
- else if (! TREE_PUBLIC (name) && TREE_PUBLIC (x))
+ else if (TREE_CODE (t) != TREE_CODE (x))
{
- if (DECL_LANG_SPECIFIC (t) && DECL_FRIEND_P (t))
+ if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
+ || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+ {
+ /* We do nothing special here, because C++ does such nasty
+ things with TYPE_DECLs. Instead, just let the TYPE_DECL
+ get shadowed, and know that if we need to find a TYPE_DECL
+ for a given name, we can look in the IDENTIFIER_TYPE_VALUE
+ slot of the identifier. */
+ ;
+ }
+ else if (duplicate_decls (x, t))
return t;
+ }
+ else if (duplicate_decls (x, t))
+ {
+#if 0
+ /* This is turned off until I have time to do it right (bpk). */
- if (extra_warnings)
+ /* Also warn if they did a prototype with `static' on it, but
+ then later left the `static' off. */
+ if (! TREE_PUBLIC (name) && TREE_PUBLIC (x))
{
- cp_warning ("`static' missing from declaration of `%D'", t);
- warning_with_file_and_line (file, line,
- "previous declaration of `%s'",
- decl_as_string (t, 0));
- }
+ if (DECL_LANG_SPECIFIC (t) && DECL_FRIEND_P (t))
+ return t;
- /* Now fix things so it'll do what they expect. */
- if (current_function_decl)
- TREE_PUBLIC (current_function_decl) = 0;
- }
+ if (extra_warnings)
+ {
+ cp_warning ("`static' missing from declaration of `%D'",
+ t);
+ warning_with_file_and_line (file, line,
+ "previous declaration of `%s'",
+ decl_as_string (t, 0));
+ }
+
+ /* Now fix things so it'll do what they expect. */
+ if (current_function_decl)
+ TREE_PUBLIC (current_function_decl) = 0;
+ }
+ /* Due to interference in memory reclamation (X may be
+ obstack-deallocated at this point), we must guard against
+ one really special case. [jason: This should be handled
+ by start_function] */
+ if (current_function_decl == x)
+ current_function_decl = t;
#endif
+ if (TREE_CODE (t) == TYPE_DECL)
+ SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
- /* Due to interference in memory reclamation (X may be
- obstack-deallocated at this point), we must guard against
- one really special case. */
- if (current_function_decl == x)
- current_function_decl = t;
+ return t;
+ }
+ }
- return t;
+ if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
+ {
+ t = push_overloaded_decl (x, 1);
+ if (t != x || DECL_LANGUAGE (x) == lang_c)
+ return t;
}
+ else if (TREE_CODE (x) == TEMPLATE_DECL && ! DECL_TEMPLATE_IS_CLASS (x))
+ return push_overloaded_decl (x, 0);
/* If declaring a type as a typedef, and the type has no known
typedef name, install this TYPE_DECL as its typedef name. */
{
tree tname = DECL_NAME (name);
+ /* This is a disgusting kludge for dealing with UPTs. */
if (global_bindings_p () && ANON_AGGRNAME_P (tname))
{
/* do gratuitous C++ typedefing, and make sure that
}
my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140);
- if (DECL_NAME (name) && !DECL_NESTED_TYPENAME (name))
- set_nested_typename (x, current_class_name,
- DECL_NAME (name), type);
+ /* Don't set nested_typename on template type parms, for instance.
+ Any artificial decls that need DECL_NESTED_TYPENAME will have it
+ set in pushtag. */
+ if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
+ set_nested_typename (x, current_class_name, DECL_NAME (x), type);
if (type != error_mark_node
&& TYPE_NAME (type)
/* Multiple external decls of the same identifier ought to match.
We get warnings about inline functions where they are defined.
+ We get warnings about other functions from push_overloaded_decl.
+
Avoid duplicate warnings where they are used. */
- if (TREE_PUBLIC (x) && !DECL_INLINE (x))
+ if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
{
tree decl;
else
decl = NULL_TREE;
- if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl), 1)
+ if (decl
/* If different sort of thing, we already gave an error. */
&& TREE_CODE (decl) == TREE_CODE (x)
- /* If old decl is built-in, we already warned if we should. */
- && !DECL_BUILT_IN (decl))
+ && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl), 1))
{
cp_pedwarn ("type mismatch with previous external decl", x);
- cp_pedwarn_at ("previous external decl of `%D'", decl);
+ cp_pedwarn_at ("previous external decl of `%#D'", decl);
}
}
/* If the first global decl has external linkage,
warn if we later see static one. */
- if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
+ if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && DECL_PUBLIC (x))
TREE_PUBLIC (name) = 1;
- /* Don't install a TYPE_DECL if we already have another
- sort of _DECL with that name. */
+ /* Don't install an artificial TYPE_DECL if we already have
+ another _DECL with that name. */
if (TREE_CODE (x) != TYPE_DECL
|| t == NULL_TREE
- || TREE_CODE (t) == TYPE_DECL)
+ || ! DECL_ARTIFICIAL (x))
IDENTIFIER_GLOBAL_VALUE (name) = x;
/* Don't forget if the function was used via an implicit decl. */
/* If new decl is `static' and an `extern' was seen previously,
warn about it. */
- warn_extern_redeclared_static (x, t);
+ if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t))
+ warn_extern_redeclared_static (x, t);
}
else
{
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
- b->shadowed = tree_cons (name, oldlocal, b->shadowed);
- IDENTIFIER_LOCAL_VALUE (name) = x;
+ /* Don't install an artificial TYPE_DECL if we already have
+ another _DECL with that name. */
+ if (TREE_CODE (x) != TYPE_DECL
+ || t == NULL_TREE
+ || ! DECL_ARTIFICIAL (x))
+ {
+ b->shadowed = tree_cons (name, oldlocal, b->shadowed);
+ IDENTIFIER_LOCAL_VALUE (name) = x;
+ }
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
/* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */
if (oldlocal == NULL_TREE
- && DECL_EXTERNAL (x) && !DECL_INLINE (x)
+ && DECL_EXTERNAL (x)
&& oldglobal != NULL_TREE
&& TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL)
{
/* We have one. Their types must agree. */
- if (! comptypes (TREE_TYPE (x), TREE_TYPE (oldglobal), 1))
+ if (decls_match (x, oldglobal))
+ /* OK */;
+ else
{
cp_warning ("extern declaration of `%#D' doesn't match", x);
cp_warning_at ("global declaration `%#D'", oldglobal);
}
- else
- {
- /* Inner extern decl is inline if global one is.
- Copy enough to really inline it. */
- if (DECL_INLINE (oldglobal))
- {
- DECL_INLINE (x) = DECL_INLINE (oldglobal);
- DECL_INITIAL (x) = (current_function_decl == oldglobal
- ? NULL_TREE : DECL_INITIAL (oldglobal));
- DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal);
- DECL_FRAME_SIZE (x) = DECL_FRAME_SIZE (oldglobal);
- DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
- DECL_RESULT (x) = DECL_RESULT (oldglobal);
- TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
- DECL_ABSTRACT_ORIGIN (x) = oldglobal;
- }
- /* Inner extern decl is built-in if global one is. */
- if (DECL_BUILT_IN (oldglobal))
- {
- DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal);
- DECL_SET_FUNCTION_CODE (x, DECL_FUNCTION_CODE (oldglobal));
- }
- /* Keep the arg types from a file-scope fcn defn. */
- if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != NULL_TREE
- && DECL_INITIAL (oldglobal)
- && TYPE_ARG_TYPES (TREE_TYPE (x)) == NULL_TREE)
- TREE_TYPE (x) = TREE_TYPE (oldglobal);
- }
}
/* If we have a local external declaration,
and no file-scope declaration has yet been seen,
/* Maybe warn if shadowing something else. */
else if (warn_shadow && !DECL_EXTERNAL (x)
/* No shadow warnings for internally generated vars. */
- && DECL_SOURCE_LINE (x) != 0
+ && ! DECL_ARTIFICIAL (x)
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
if (warnstring)
warning (warnstring, IDENTIFIER_POINTER (name));
}
+ }
- /* If storing a local value, there may already be one (inherited).
- If so, record it for restoration when this binding level ends. */
- if (oldlocal != NULL_TREE)
- b->shadowed = tree_cons (name, oldlocal, b->shadowed);
+ if (TREE_CODE (x) == FUNCTION_DECL)
+ {
+ /* This is probably the wrong place to check this, but it has to
+ come after the call to duplicate_decls. */
+ tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
+ int saw_def = 0, i = 1;
+ for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
+ {
+ if (TREE_PURPOSE (arg))
+ saw_def = 1;
+ else if (saw_def)
+ {
+ cp_error ("default argument missing for parameter %d of `%#D'",
+ i, x);
+ break;
+ }
+ }
}
/* Keep count of variables in this level with incomplete type. */
if (TREE_CODE (x) != TEMPLATE_DECL
- && TREE_CODE (x) != CPLUS_CATCH_DECL
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
&& PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
{
if (++b->n_incomplete == 0)
error ("too many incomplete variables at this point");
}
- }
- if (TREE_CODE (x) == TYPE_DECL && name != NULL_TREE)
- {
- if (current_class_name)
+ /* Keep count of variables in this level with incomplete type. */
+ /* RTTI TD entries are created while defining the type_info. */
+ if (TREE_CODE (x) == VAR_DECL
+ && TREE_TYPE (x) != error_mark_node
+ && TYPE_LANG_SPECIFIC (TREE_TYPE (x))
+ && TYPE_BEING_DEFINED (TREE_TYPE (x)))
{
- if (!DECL_NESTED_TYPENAME (x))
- set_nested_typename (x, current_class_name, DECL_NAME (x),
- TREE_TYPE (x));
+ if (++b->n_incomplete == 0)
+ error ("too many incomplete variables at this point");
}
}
if (name)
{
+ if (TYPE_BEING_DEFINED (current_class_type))
+ {
+ /* Check for inconsistent use of this name in the class body.
+ Types, enums, and static vars are checked here; other
+ members are checked in finish_struct. */
+ tree icv = IDENTIFIER_CLASS_VALUE (name);
+
+ if (icv
+ /* Don't complain about inherited names. */
+ && id_in_current_class (name)
+ /* Or shadowed tags. */
+ && !(TREE_CODE (icv) == TYPE_DECL
+ && DECL_CONTEXT (icv) == current_class_type))
+ {
+ cp_error ("declaration of identifier `%D' as `%#D'", name, x);
+ cp_error_at ("conflicts with previous use in class as `%#D'",
+ icv);
+ }
+ }
+
push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
{
set_identifier_type_value (name, TREE_TYPE (x));
- if (!DECL_NESTED_TYPENAME (x))
+
+ /* Don't set nested_typename on template type parms, for instance.
+ Any artificial decls that need DECL_NESTED_TYPENAME will have it
+ set in pushtag. */
+ if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
set_nested_typename (x, current_class_name, name, TREE_TYPE (x));
}
}
return x;
}
+/* This function is used to push the mangled decls for nested types into
+ the appropriate scope. Previously pushdecl_top_level was used, but that
+ is incorrect for members of local classes. */
+tree
+pushdecl_nonclass_level (x)
+ tree x;
+{
+ struct binding_level *b = current_binding_level;
+
+#if 0
+ /* Get out of class scope -- this isn't necessary, because class scope
+ doesn't make it into current_binding_level. */
+ while (b->parm_flag == 2)
+ b = b->level_chain;
+#else
+ my_friendly_assert (b->parm_flag != 2, 180);
+#endif
+
+ /* Get out of template binding levels */
+ while (b->pseudo_global)
+ b = b->level_chain;
+
+ pushdecl_with_scope (x, b);
+}
+
/* Make the declaration(s) of X appear in CLASS scope
under the name NAME. */
void
tree name;
tree x;
{
+ if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+ && purpose_member (name, class_binding_level->class_shadowed))
+ return;
+
maybe_push_cache_obstack ();
class_binding_level->class_shadowed
= tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
return 0;
}
-/* DECL is a FUNCTION_DECL which may have other definitions already in place.
- We get around this by making IDENTIFIER_GLOBAL_VALUE (DECL_NAME (DECL))
- point to a list of all the things that want to be referenced by that name.
- It is then up to the users of that name to decide what to do with that
+/* DECL is a FUNCTION_DECL which may have other definitions already in
+ place. We get around this by making the value of the identifier point
+ to a list of all the things that want to be referenced by that name. It
+ is then up to the users of that name to decide what to do with that
list.
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
int forgettable;
{
tree orig_name = DECL_NAME (decl);
- tree glob = IDENTIFIER_GLOBAL_VALUE (orig_name);
+ tree old;
+ int doing_global = (global_bindings_p () || ! forgettable
+ || flag_traditional || pseudo_global_level_p ());
- DECL_OVERLOADED (decl) = 1;
-
- if (forgettable
- && ! flag_traditional
- && (glob == NULL_TREE || TREE_PERMANENT (glob) == 1)
- && !global_bindings_p ()
- && !pseudo_global_level_p ())
- overloads_to_forget = tree_cons (orig_name, glob, overloads_to_forget);
-
- if (glob)
+ if (doing_global)
{
- if (DECL_LANGUAGE (decl) == lang_c)
+ old = IDENTIFIER_GLOBAL_VALUE (orig_name);
+ if (old && TREE_CODE (old) == FUNCTION_DECL
+ && DECL_ARTIFICIAL (old)
+ && (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
{
- tree decls = get_first_fn (glob);
- while (decls && DECL_LANGUAGE (decls) == lang_cplusplus)
- decls = DECL_CHAIN (decls);
- if (decls)
- {
- cp_error_at ("C-language function `%#D'", decls);
- cp_error ("overloaded as `%#D'", decl);
- }
+ if (duplicate_decls (decl, old))
+ return old;
+ old = NULL_TREE;
}
+ }
+ else
+ {
+ old = IDENTIFIER_LOCAL_VALUE (orig_name);
+
+ if (! purpose_member (orig_name, current_binding_level->shadowed))
+ {
+ current_binding_level->shadowed
+ = tree_cons (orig_name, old, current_binding_level->shadowed);
+ old = NULL_TREE;
+ }
+ }
+ if (old)
+ {
+#if 0
/* We cache the value of builtin functions as ADDR_EXPRs
in the name space. Convert it to some kind of _DECL after
remembering what to forget. */
- if (TREE_CODE (glob) == ADDR_EXPR)
- glob = TREE_OPERAND (glob, 0);
-
- else if (TREE_CODE (decl) == TEMPLATE_DECL)
- {
- tree tmp;
-
- for (tmp = get_first_fn (glob); tmp; tmp = DECL_CHAIN (tmp))
- if (decl == tmp)
- return decl;
- }
- else if (TREE_CODE (glob) == VAR_DECL)
+ if (TREE_CODE (old) == ADDR_EXPR)
+ old = TREE_OPERAND (old, 0);
+ else
+#endif
+ if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
{
- cp_error_at ("previous non-function declaration `%#D'", glob);
- cp_error ("conflicts with function declaration `%#D'", decl);
- return error_mark_node;
+ tree t = TREE_TYPE (old);
+ if (IS_AGGR_TYPE (t) && warn_shadow)
+ cp_warning ("`%#D' hides constructor for `%#T'", decl, t);
+ old = NULL_TREE;
}
- else if (is_overloaded_fn (glob))
+ else if (is_overloaded_fn (old))
{
- tree name = DECL_ASSEMBLER_NAME (decl);
tree tmp;
- for (tmp = get_first_fn (glob); tmp; tmp = DECL_CHAIN (tmp))
- {
- if (TREE_CODE (tmp) == FUNCTION_DECL
- && comptypes (TREE_TYPE (tmp), TREE_TYPE (decl), 2))
- {
- if (DECL_LANGUAGE (tmp) != DECL_LANGUAGE (decl))
- {
- if (current_lang_stack == current_lang_base)
- {
- DECL_LANGUAGE (decl) = DECL_LANGUAGE (tmp);
- return tmp;
- }
- cp_error_at ("previous declaration of `%#D' with %L linkage",
- tmp, DECL_LANGUAGE (tmp));
- cp_error ("conflicts with new %L-language declaration",
- DECL_LANGUAGE (decl));
- }
- else if (TREE_CODE (tmp) != TEMPLATE_DECL
- && DECL_ASSEMBLER_NAME (tmp) != name)
- {
- cp_error ("new declaration `%#D'", decl);
- cp_error_at ("ambiguates old declaration `%#D'", tmp);
- }
- }
- /* If we really have seen this before, then if it ambiguates
- something, we've already given an error before. */
- if (TREE_CODE (tmp) != TEMPLATE_DECL
- && DECL_ASSEMBLER_NAME (tmp) == name)
- return decl;
- }
+ for (tmp = get_first_fn (old); tmp; tmp = DECL_CHAIN (tmp))
+ if (decl == tmp || duplicate_decls (decl, tmp))
+ return tmp;
+ }
+ else
+ {
+ cp_error_at ("previous non-function declaration `%#D'", old);
+ cp_error ("conflicts with function declaration `%#D'", decl);
+ return error_mark_node;
}
}
- if (glob || TREE_CODE (decl) == TEMPLATE_DECL)
+
+ if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{
- if (glob && is_overloaded_fn (glob))
- DECL_CHAIN (decl) = get_first_fn (glob);
+ if (old && is_overloaded_fn (old))
+ DECL_CHAIN (decl) = get_first_fn (old);
else
DECL_CHAIN (decl) = NULL_TREE;
- glob = tree_cons (orig_name, decl, NULL_TREE);
- TREE_TYPE (glob) = unknown_type_node;
+ old = tree_cons (orig_name, decl, NULL_TREE);
+ TREE_TYPE (old) = unknown_type_node;
}
else
/* orig_name is not ambiguous. */
- glob = decl;
-
- IDENTIFIER_GLOBAL_VALUE (orig_name) = glob;
+ old = decl;
+
+ if (doing_global)
+ IDENTIFIER_GLOBAL_VALUE (orig_name) = old;
+ else
+ IDENTIFIER_LOCAL_VALUE (orig_name) = old;
+
return decl;
}
\f
/* Because C++ can put things into name space for free,
constructs like "typedef struct foo { ... } foo"
would look like an erroneous redeclaration. */
- if (comptypes (newdecl, olddecl, 0))
+ if (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
return 0;
else
- return "redefinition of `%s'";
+ return "redefinition of `%#D'";
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_LANG_SPECIFIC (olddecl) && DECL_ABSTRACT_VIRTUAL_P (olddecl))
return 0;
- /* Declarations of functions can insist on internal linkage
- but they can't be inconsistent with internal linkage,
- so there can be no error on that account.
- However defining the same name twice is no good. */
+ /* We'll complain about linkage mismatches in
+ warn_extern_redeclared_static. */
+
+ /* defining the same name twice is no good. */
if (DECL_INITIAL (olddecl) != NULL_TREE
- && DECL_INITIAL (newdecl) != NULL_TREE
- /* However, defining once as extern inline and a second
- time in another way is ok. */
- && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
- && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
+ && DECL_INITIAL (newdecl) != NULL_TREE)
{
if (DECL_NAME (olddecl) == NULL_TREE)
- return "`%s' not declared in class";
+ return "`%#D' not declared in class";
else
- return "redefinition of `%s'";
+ return "redefinition of `%#D'";
}
return 0;
}
+ else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
+ {
+ if (DECL_INITIAL (olddecl) && DECL_INITIAL (newdecl))
+ return "redefinition of `%#D'";
+ return 0;
+ }
else if (current_binding_level == global_binding_level)
{
/* Objects declared at top level: */
+ /* Insist that the linkage match. */
+ if (! TREE_PUBLIC (newdecl) && TREE_PUBLIC (olddecl))
+ return "conflicting declarations of `%#D'";
/* If at least one is a reference, it's ok. */
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
/* Reject two definitions. */
- if (DECL_INITIAL (olddecl) != NULL_TREE
- && DECL_INITIAL (newdecl) != NULL_TREE)
- return "redefinition of `%s'";
- /* Now we have two tentative defs, or one tentative and one real def. */
- /* Insist that the linkage match. */
- if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
- return "conflicting declarations of `%s'";
- return 0;
+ return "redefinition of `%#D'";
}
else
{
/* Reject two definitions, and reject a definition
together with an external reference. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
- return "redeclaration of `%s'";
+ return "redeclaration of `%#D'";
return 0;
}
}
decl = lookup_label (name);
}
+ if (name == get_identifier ("wchar_t"))
+ cp_pedwarn ("label named wchar_t");
+
if (DECL_INITIAL (decl) != NULL_TREE)
{
cp_error ("duplicate label `%D'", decl);
else
{
tree uses, prev;
+ int identified = 0;
/* Mark label as having been defined. */
DECL_INITIAL (decl) = error_mark_node;
of internal entities. They can't be accessed,
and they should be cleaned up
by the time we get to the label. */
- && DECL_SOURCE_LINE (new_decls) != 0
+ && ! DECL_ARTIFICIAL (new_decls)
&& ((DECL_INITIAL (new_decls) != NULL_TREE
&& DECL_INITIAL (new_decls) != error_mark_node)
|| TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
{
- if (IDENTIFIER_ERROR_LOCUS (decl) == NULL_TREE)
- cp_error ("invalid jump to label `%D'", decl);
- SET_IDENTIFIER_ERROR_LOCUS (decl, current_function_decl);
- cp_error ("crosses initialization of `%D'", new_decls);
+ if (! identified)
+ cp_error ("jump to label `%D'", decl);
+ identified = 1;
+ cp_error_at (" crosses initialization of `%#D'",
+ new_decls);
}
new_decls = TREE_CHAIN (new_decls);
}
}
}
+struct cp_switch
+{
+ struct binding_level *level;
+ struct cp_switch *next;
+};
+
+static struct cp_switch *switch_stack;
+
+void
+push_switch ()
+{
+ struct cp_switch *p
+ = (struct cp_switch *) oballoc (sizeof (struct cp_switch));
+ p->level = current_binding_level;
+ p->next = switch_stack;
+ switch_stack = p;
+}
+
+void
+pop_switch ()
+{
+ switch_stack = switch_stack->next;
+}
+
/* Same, but for CASE labels. If DECL is NULL_TREE, it's the default. */
/* XXX Note decl is never actually used. (bpk) */
void
tree decl;
{
tree cleanup = last_cleanup_this_contour ();
+ struct binding_level *b = current_binding_level;
+ int identified = 0;
+
if (cleanup)
{
static int explained = 0;
- cp_error_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup));
- error ("where case label appears here");
+ cp_warning_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup));
+ warning ("where case label appears here");
if (!explained)
{
- error ("(enclose actions of previous case statements requiring");
- error ("destructors in their own binding contours.)");
+ warning ("(enclose actions of previous case statements requiring");
+ warning ("destructors in their own binding contours.)");
explained = 1;
}
}
+ for (; b && b != switch_stack->level; b = b->level_chain)
+ {
+ tree new_decls = b->names;
+ for (; new_decls; new_decls = TREE_CHAIN (new_decls))
+ {
+ if (TREE_CODE (new_decls) == VAR_DECL
+ /* Don't complain about crossing initialization
+ of internal entities. They can't be accessed,
+ and they should be cleaned up
+ by the time we get to the label. */
+ && ! DECL_ARTIFICIAL (new_decls)
+ && ((DECL_INITIAL (new_decls) != NULL_TREE
+ && DECL_INITIAL (new_decls) != error_mark_node)
+ || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
+ {
+ if (! identified)
+ error ("jump to case label");
+ identified = 1;
+ cp_error_at (" crosses initialization of `%#D'",
+ new_decls);
+ }
+ }
+ }
+
/* After labels, make any new cleanups go into their
own new (temporary) binding contour. */
}
break;
case FUNCTION_DECL:
- return TYPE_IDENTIFIER (type) ? lookup_name (TYPE_IDENTIFIER (type), 1) : NULL_TREE;
- break;
+ if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
+ return lookup_name (TYPE_IDENTIFIER (type), 1);
+ return NULL_TREE;
default:
my_friendly_abort (12);
}
definitions if there are many, or return 0 if it is undefined.
If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
- If PREFER_TYPE is = 0, we prefer non-TYPE_DECLs.
- If PREFER_TYPE is < 0, we arbitrate according to lexical context. */
+ If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
+ Otherwise we prefer non-TYPE_DECLs. */
tree
-lookup_name (name, prefer_type)
+lookup_name_real (name, prefer_type, nonclass)
tree name;
- int prefer_type;
+ int prefer_type, nonclass;
{
register tree val;
+ int yylex = 0;
+ tree from_obj = NULL_TREE;
+
+ if (prefer_type == -2)
+ {
+ extern int looking_for_typename;
+ tree type;
+
+ yylex = 1;
+ prefer_type = looking_for_typename;
+
+ if (got_scope)
+ type = got_scope;
+ else
+ type = got_object;
+
+ if (type)
+ {
+ if (type == error_mark_node)
+ return error_mark_node;
+ else if (type == void_type_node)
+ val = IDENTIFIER_GLOBAL_VALUE (name);
+ else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ /* TFIXME -- don't do this for UPTs in new model. */
+ || TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
+ {
+ if (prefer_type > 0)
+ val = create_nested_upt (type, name);
+ else
+ val = NULL_TREE;
+ }
+ else if (! IS_AGGR_TYPE (type))
+ /* Someone else will give an error about this if needed. */
+ val = NULL_TREE;
+ else if (TYPE_BEING_DEFINED (type))
+ {
+ val = IDENTIFIER_CLASS_VALUE (name);
+ if (val && DECL_CONTEXT (val) != type)
+ {
+ struct binding_level *b = class_binding_level;
+ for (val = NULL_TREE; b; b = b->level_chain)
+ {
+ tree t = purpose_member (name, b->class_shadowed);
+ if (t && TREE_VALUE (t)
+ && DECL_CONTEXT (TREE_VALUE (t)) == type)
+ {
+ val = TREE_VALUE (t);
+ break;
+ }
+ }
+ }
+ if (val == NULL_TREE
+ && CLASSTYPE_LOCAL_TYPEDECLS (type))
+ val = lookup_field (type, name, 0, 1);
+ }
+ else if (type == current_class_type)
+ val = IDENTIFIER_CLASS_VALUE (name);
+ else
+ val = lookup_field (type, name, 0, prefer_type);
+ }
+ else
+ val = NULL_TREE;
+ if (got_scope)
+ goto done;
+
+ /* This special lookup only applies to types. */
+ else if (got_object && val && TREE_CODE (val) == TYPE_DECL)
+ from_obj = val;
+ }
+
if (current_binding_level != global_binding_level
&& IDENTIFIER_LOCAL_VALUE (name))
val = IDENTIFIER_LOCAL_VALUE (name);
/* In C++ class fields are between local and global scope,
just before the global scope. */
- else if (current_class_type)
+ else if (current_class_type && ! nonclass)
{
val = IDENTIFIER_CLASS_VALUE (name);
if (val == NULL_TREE
- && TYPE_SIZE (current_class_type) == NULL_TREE
+ && TYPE_BEING_DEFINED (current_class_type)
&& CLASSTYPE_LOCAL_TYPEDECLS (current_class_type))
- {
- /* Try to find values from base classes
- if we are presently defining a type.
- We are presently only interested in TYPE_DECLs. */
- val = lookup_field (current_class_type, name, 0, prefer_type < 0);
- if (val == error_mark_node)
- return val;
- if (val && TREE_CODE (val) != TYPE_DECL)
- val = NULL_TREE;
- }
+ /* Try to find values from base classes if we are presently
+ defining a type. We are presently only interested in
+ TYPE_DECLs. */
+ val = lookup_field (current_class_type, name, 0, 1);
/* yylex() calls this with -2, since we should never start digging for
the nested name at the point where we haven't even, for example,
created the COMPONENT_REF or anything like that. */
if (val == NULL_TREE)
- val = lookup_nested_field (name, prefer_type != -2);
+ val = lookup_nested_field (name, ! yylex);
if (val == NULL_TREE)
val = IDENTIFIER_GLOBAL_VALUE (name);
else
val = IDENTIFIER_GLOBAL_VALUE (name);
+ done:
if (val)
{
- extern int looking_for_typename;
-
- /* Arbitrate between finding a TYPE_DECL and finding
- other kinds of _DECLs. */
- if (TREE_CODE (val) == TYPE_DECL || looking_for_typename < 0)
- return val;
-
- if (IDENTIFIER_HAS_TYPE_VALUE (name))
- {
- register tree val_as_type = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
+ if (from_obj && from_obj != val)
+ cp_error ("lookup in the scope of `%#T' does not match lookup in the current scope",
+ got_object);
- if (val == val_as_type || prefer_type > 0
- || looking_for_typename > 0)
- return val_as_type;
- if (prefer_type == 0)
- return val;
- return arbitrate_lookup (name, val, val_as_type);
- }
- if (TREE_TYPE (val) == error_mark_node)
- return error_mark_node;
+ if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
+ || TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
+ ;
+ else if (IDENTIFIER_HAS_TYPE_VALUE (name))
+ val = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
+ else if (TREE_TYPE (val) == error_mark_node)
+ val = error_mark_node;
}
+ else if (from_obj)
+ val = from_obj;
return val;
}
+tree
+lookup_name_nonclass (name)
+ tree name;
+{
+ return lookup_name_real (name, 0, 1);
+}
+
+tree
+lookup_name (name, prefer_type)
+ tree name;
+ int prefer_type;
+{
+ return lookup_name_real (name, prefer_type, 0);
+}
+
/* Similar to `lookup_name' but look only at current binding level. */
tree
}
else if (IDENTIFIER_LOCAL_VALUE (name) != NULL_TREE)
{
- for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
- if (DECL_NAME (t) == name)
- break;
+ struct binding_level *b = current_binding_level;
+ while (1)
+ {
+ for (t = b->names; t; t = TREE_CHAIN (t))
+ if (DECL_NAME (t) == name || DECL_ASSEMBLER_NAME (t) == name)
+ goto out;
+ if (b->keep == 2)
+ b = b->level_chain;
+ else
+ break;
+ }
+ out:
+ ;
}
return t;
}
}
- if (flag_dossier)
+ if (flag_rtti)
{
if (builtin_type_tdescs_len+5 >= builtin_type_tdescs_max)
{
builtin_type_tdescs_arr[builtin_type_tdescs_len++]
= build_pointer_type (type);
builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_type_variant (TYPE_POINTER_TO (type), 1, 0);
+ = build_pointer_type (build_type_variant (type, 1, 0));
}
if (TREE_CODE (type) != VOID_TYPE)
{
builtin_type_tdescs_arr[builtin_type_tdescs_len++]
= build_reference_type (type);
builtin_type_tdescs_arr[builtin_type_tdescs_len++]
- = build_type_variant (TYPE_REFERENCE_TO (type), 1, 0);
+ = build_reference_type (build_type_variant (type, 1, 0));
}
}
}
push_overloaded_decl (x, 0);
}
+#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
+ define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME)
+
+#ifdef __GNUC__
+__inline
+#endif
+tree auto_function (name, type, code)
+ tree name, type;
+ enum built_in_function code;
+{
+ return define_function
+ (IDENTIFIER_POINTER (name), type, code, (void (*)())push_overloaded_decl_1,
+ IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type),
+ 0)));
+}
+
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *)0).
Initialize the global binding level.
int wchar_type_size;
tree temp;
tree array_domain_type;
+ extern int flag_strict_prototype;
/* Have to make these distinct before we try using them. */
lang_name_cplusplus = get_identifier ("C++");
lang_name_c = get_identifier ("C");
+ if (flag_strict_prototype == 2)
+ {
+ if (pedantic)
+ strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
+ }
+ else
+ strict_prototypes_lang_c = flag_strict_prototype;
+
/* Initially, C. */
current_lang_name = lang_name_c;
#endif
gcc_obstack_init (&decl_obstack);
- if (flag_dossier)
+ if (flag_rtti)
{
builtin_type_tdescs_max = 100;
builtin_type_tdescs_arr = (tree *)xmalloc (100 * sizeof (tree));
error_mark_list = build_tree_list (error_mark_node, error_mark_node);
TREE_TYPE (error_mark_list) = error_mark_node;
- pushlevel (0); /* make the binding_level structure for global names. */
+ /* Make the binding_level structure for global names. */
+ pushlevel (0);
global_binding_level = current_binding_level;
this_identifier = get_identifier (THIS_NAME);
TREE_TYPE (integer_two_node) = integer_type_node;
integer_three_node = build_int_2 (3, 0);
TREE_TYPE (integer_three_node) = integer_type_node;
- empty_init_node = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);
+
+ boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
+ TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
+ record_builtin_type (RID_BOOL, "bool", boolean_type_node);
+ boolean_false_node = build_int_2 (0, 0);
+ TREE_TYPE (boolean_false_node) = boolean_type_node;
+ boolean_true_node = build_int_2 (1, 0);
+ TREE_TYPE (boolean_true_node) = boolean_type_node;
/* These are needed by stor-layout.c. */
size_zero_node = size_int (0);
TREE_TYPE (void_zero_node) = void_type_node;
string_type_node = build_pointer_type (char_type_node);
- const_string_type_node = build_pointer_type (build_type_variant (char_type_node, 1, 0));
+ const_string_type_node =
+ build_pointer_type (build_type_variant (char_type_node, 1, 0));
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
/* Make a type to be the domain of a few array types
build_pointer_type (default_function_type);
ptr_type_node = build_pointer_type (void_type_node);
- const_ptr_type_node = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+ const_ptr_type_node =
+ build_pointer_type (build_type_variant (void_type_node, 1, 0));
record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
endlink = void_list_node;
int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
double_ftype_double_double
= build_function_type (double_type_node,
- tree_cons (NULL_TREE, double_type_node, double_endlink));
+ tree_cons (NULL_TREE, double_type_node,
+ double_endlink));
int_ftype_int
= build_function_type (integer_type_node, int_endlink);
long_ftype_long
= build_function_type (long_integer_type_node,
- tree_cons (NULL_TREE, long_integer_type_node, endlink));
+ tree_cons (NULL_TREE, long_integer_type_node,
+ endlink));
void_ftype_ptr_ptr_int
= build_function_type (void_type_node,
builtin_function ("__builtin_constant_p", int_ftype_int,
BUILT_IN_CONSTANT_P, NULL_PTR);
- builtin_function ("__builtin_alloca",
- build_function_type (ptr_type_node,
+ builtin_return_address_fndecl =
+ builtin_function ("__builtin_return_address",
+ build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
- sizetype,
+ unsigned_type_node,
endlink)),
- BUILT_IN_ALLOCA, "alloca");
-#if 0
- builtin_function ("alloca",
+ BUILT_IN_RETURN_ADDRESS, NULL_PTR);
+
+ builtin_function ("__builtin_frame_address",
+ build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE,
+ unsigned_type_node,
+ endlink)),
+ BUILT_IN_FRAME_ADDRESS, NULL_PTR);
+
+
+ builtin_function ("__builtin_alloca",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
sizetype,
endlink)),
- BUILT_IN_ALLOCA, NULL_PTR);
-#endif
+ BUILT_IN_ALLOCA, "alloca");
+ /* Define alloca, ffs as builtins.
+ Declare _exit just to mark it as volatile. */
+ if (! flag_no_builtin && !flag_no_nonansi_builtin)
+ {
+ temp = builtin_function ("alloca",
+ build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE,
+ sizetype,
+ endlink)),
+ BUILT_IN_ALLOCA, NULL_PTR);
+ /* Suppress error if redefined as a non-function. */
+ DECL_BUILT_IN_NONANSI (temp) = 1;
+ temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
+ /* Suppress error if redefined as a non-function. */
+ DECL_BUILT_IN_NONANSI (temp) = 1;
+ temp = builtin_function ("_exit", build_function_type (void_type_node,
+ int_endlink),
+ NOT_BUILT_IN, NULL_PTR);
+ TREE_THIS_VOLATILE (temp) = 1;
+ TREE_SIDE_EFFECTS (temp) = 1;
+ /* Suppress error if redefined as a non-function. */
+ DECL_BUILT_IN_NONANSI (temp) = 1;
+ }
builtin_function ("__builtin_abs", int_ftype_int,
BUILT_IN_ABS, NULL_PTR);
builtin_function ("__builtin_classify_type", default_function_type,
BUILT_IN_CLASSIFY_TYPE, NULL_PTR);
builtin_function ("__builtin_next_arg",
- build_function_type (ptr_type_node, endlink),
+ build_function_type (ptr_type_node, NULL_TREE),
BUILT_IN_NEXT_ARG, NULL_PTR);
builtin_function ("__builtin_args_info",
build_function_type (integer_type_node,
builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP,
NULL_PTR);
builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, NULL_PTR);
- builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, NULL_PTR);
+ builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
+ NULL_PTR);
#if 0
/* Not yet. */
builtin_function ("strncpy", strncpy_ftype, BUILT_IN_STRNCPY, NULL_PTR);
builtin_function ("strlen", sizet_ftype_string, BUILT_IN_STRLEN, NULL_PTR);
builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR);
builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR);
+
+ /* Declare these functions volatile
+ to avoid spurious "control drops through" warnings. */
+ temp = builtin_function ("abort",
+ build_function_type (void_type_node, endlink),
+ NOT_BUILT_IN, NULL_PTR);
+ TREE_THIS_VOLATILE (temp) = 1;
+ TREE_SIDE_EFFECTS (temp) = 1;
+ /* Well, these are actually ANSI, but we can't set DECL_BUILT_IN on
+ them... */
+ DECL_BUILT_IN_NONANSI (temp) = 1;
+ temp = builtin_function ("exit", build_function_type (void_type_node,
+ int_endlink),
+ NOT_BUILT_IN, NULL_PTR);
+ TREE_THIS_VOLATILE (temp) = 1;
+ TREE_SIDE_EFFECTS (temp) = 1;
+ DECL_BUILT_IN_NONANSI (temp) = 1;
}
#if 0
or build_function_call. */
builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, 0);
builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, 0);
- builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, 0);
+ builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR,
+ 0);
builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, 0);
- builtin_function ("__builtin_fmod", double_ftype_double_double, BUILT_IN_FMOD, 0);
- builtin_function ("__builtin_frem", double_ftype_double_double, BUILT_IN_FREM, 0);
- builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET, 0);
- builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, 0);
- builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, 0);
+ builtin_function ("__builtin_fmod", double_ftype_double_double,
+ BUILT_IN_FMOD, 0);
+ builtin_function ("__builtin_frem", double_ftype_double_double,
+ BUILT_IN_FREM, 0);
+ builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET,
+ 0);
+ builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP,
+ 0);
+ builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN,
+ 0);
#endif
/* C++ extensions */
unknown_type_node));
/* Make sure the "unknown type" typedecl gets ignored for debug info. */
DECL_IGNORED_P (decl) = 1;
+ TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
#endif
TYPE_SIZE (unknown_type_node) = TYPE_SIZE (void_type_node);
TYPE_ALIGN (unknown_type_node) = 1;
TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node);
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TREE_TYPE (unknown_type_node) = unknown_type_node;
- /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same result. */
+ /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same result. */
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
: signed_wchar_type_node;
record_builtin_type (RID_WCHAR, "__wchar_t", wchar_type_node);
+ /* Artificial declaration of wchar_t -- can be bashed */
+ wchar_decl_node = build_decl (TYPE_DECL, get_identifier ("wchar_t"),
+ wchar_type_node);
+ pushdecl (wchar_decl_node);
+
/* This is for wide string constants. */
wchar_array_type_node
= build_array_type (wchar_type_node, array_domain_type);
pushdecl (lookup_name (get_identifier ("__gc_main"), 0));
}
- /* Simplify life by making a "vtable_entry_type". Give its
- fields names so that the debugger can use them. */
+ if (flag_vtable_thunks)
+ {
+ /* Make sure we get a unique function type, so we can give
+ its pointer type a name. (This wins for gdb.) */
+ tree vfunc_type = make_node (FUNCTION_TYPE);
+ TREE_TYPE (vfunc_type) = integer_type_node;
+ TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
+ layout_type (vfunc_type);
- vtable_entry_type = make_lang_type (RECORD_TYPE);
- fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier, ptr_type_node);
- finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2,
- double_type_node);
-
- /* Make this part of an invisible union. */
- fields[3] = copy_node (fields[2]);
- TREE_TYPE (fields[3]) = delta_type_node;
- DECL_NAME (fields[3]) = delta2_identifier;
- DECL_MODE (fields[3]) = TYPE_MODE (delta_type_node);
- DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
- TREE_UNSIGNED (fields[3]) = 0;
- TREE_CHAIN (fields[2]) = fields[3];
- vtable_entry_type = build_type_variant (vtable_entry_type, 1, 0);
- record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
+ vtable_entry_type = build_pointer_type (vfunc_type);
+ }
+ else
+ {
+ vtable_entry_type = make_lang_type (RECORD_TYPE);
+ fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
+ delta_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier,
+ delta_type_node);
+ fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier,
+ ptr_type_node);
+ finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2,
+ double_type_node);
-#ifdef VTABLE_USES_MASK
- /* This is primarily for virtual function definition. We
- declare an array of `void *', which can later be
- converted to the appropriate function pointer type.
- To do pointers to members, we need a mask which can
- distinguish an index value into a virtual function table
- from an address. */
- vtbl_mask = build_int_2 (~((HOST_WIDE_INT) VINDEX_MAX - 1), -1);
-#endif
+ /* Make this part of an invisible union. */
+ fields[3] = copy_node (fields[2]);
+ TREE_TYPE (fields[3]) = delta_type_node;
+ DECL_NAME (fields[3]) = delta2_identifier;
+ DECL_MODE (fields[3]) = TYPE_MODE (delta_type_node);
+ DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
+ TREE_UNSIGNED (fields[3]) = 0;
+ TREE_CHAIN (fields[2]) = fields[3];
+ vtable_entry_type = build_type_variant (vtable_entry_type, 1, 0);
+ }
+ record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
vtbl_type_node
= build_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node);
- vtbl_type_node = build_type_variant (vtbl_type_node, 1, 0);
+ vtbl_type_node = cp_build_type_variant (vtbl_type_node, 1, 0);
record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node);
/* Simplify life by making a "sigtable_entry_type". Give its
if (flag_handle_signatures)
{
sigtable_entry_type = make_lang_type (RECORD_TYPE);
- fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_CODE_NAME), short_integer_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_OFFSET_NAME), short_integer_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_PFN_NAME), ptr_type_node);
+ fields[0] = build_lang_field_decl (FIELD_DECL,
+ get_identifier (SIGTABLE_CODE_NAME),
+ short_integer_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL,
+ get_identifier (SIGTABLE_OFFSET_NAME),
+ short_integer_type_node);
+ fields[2] = build_lang_field_decl (FIELD_DECL,
+ get_identifier (SIGTABLE_PFN_NAME),
+ ptr_type_node);
finish_builtin_type (sigtable_entry_type, SIGTABLE_PTR_TYPE, fields, 2,
double_type_node);
sigtable_entry_type = build_type_variant (sigtable_entry_type, 1, 0);
record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type);
}
- if (flag_dossier)
+#if 0
+ if (flag_rtti)
{
/* Must build __t_desc type. Currently, type descriptors look like this:
__t_desc_type_node = make_lang_type (RECORD_TYPE);
__i_desc_type_node = make_lang_type (RECORD_TYPE);
__m_desc_type_node = make_lang_type (RECORD_TYPE);
- __t_desc_array_type = build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE);
- __i_desc_array_type = build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE);
- __m_desc_array_type = build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE);
+ __t_desc_array_type =
+ build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE);
+ __i_desc_array_type =
+ build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE);
+ __m_desc_array_type =
+ build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE);
fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
string_type_node);
unsigned_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("bits"),
unsigned_type_node);
- fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("points_to"),
+ fields[3] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("points_to"),
TYPE_POINTER_TO (__t_desc_type_node));
fields[4] = build_lang_field_decl (FIELD_DECL,
get_identifier ("ivars_count"),
integer_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
TYPE_POINTER_TO (__t_desc_type_node));
- finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2, integer_type_node);
+ finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2,
+ integer_type_node);
/* method descriptors look like this:
short_integer_type_node);
fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"),
build_pointer_type (build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE)));
- finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7, integer_type_node);
+ finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7,
+ integer_type_node);
}
- /* Now, C++. */
- current_lang_name = lang_name_cplusplus;
- if (flag_dossier)
+ if (flag_rtti)
{
int i = builtin_type_tdescs_len;
while (i > 0)
TREE_PUBLIC (TREE_OPERAND (tdesc, 0)) = 1;
}
}
+#endif /*flag_rtti*/
+
+ /* Now, C++. */
+ current_lang_name = lang_name_cplusplus;
auto_function (ansi_opname[(int) NEW_EXPR],
build_function_type (ptr_type_node,
tree_cons (NULL_TREE, sizetype,
void_list_node)),
NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) VEC_NEW_EXPR],
+ build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE, sizetype,
+ void_list_node)),
+ NOT_BUILT_IN);
auto_function (ansi_opname[(int) DELETE_EXPR],
build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node,
void_list_node)),
NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) VEC_DELETE_EXPR],
+ build_function_type (void_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ void_list_node)),
+ NOT_BUILT_IN);
- abort_fndecl
- = define_function ("abort",
- build_function_type (void_type_node, void_list_node),
- NOT_BUILT_IN, 0, 0);
-
- unhandled_exception_fndecl
- = define_function ("__unhandled_exception",
- build_function_type (void_type_node, NULL_TREE),
+ abort_fndecl
+ = define_function ("__pure_virtual",
+ build_function_type (void_type_node, void_list_node),
NOT_BUILT_IN, 0, 0);
/* Perform other language dependent initializations. */
init_search_processing ();
if (flag_handle_exceptions)
- {
- if (flag_handle_exceptions == 2)
- /* Too much trouble to inline all the trys needed for this. */
- flag_this_is_variable = 2;
- init_exception_processing ();
- }
+ init_exception_processing ();
if (flag_gc)
init_gc_processing ();
if (flag_no_inline)
{
flag_inline_functions = 0;
#if 0
- /* This causes uneccessary emission of inline functions. */
+ /* This causes unnecessary emission of inline functions. */
flag_default_inline = 0;
#endif
}
init_function_format_info ();
}
+/* initialize type descriptor type node of various rtti type. */
+
+int
+init_type_desc()
+{
+ tree tdecl;
+
+ tdecl = lookup_name (get_identifier ("type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __t_desc_type_node = TREE_TYPE(tdecl);
+ __tp_desc_type_node = build_pointer_type (__t_desc_type_node);
+
+#if 0
+ tdecl = lookup_name (get_identifier ("__baselist_type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __baselist_desc_type_node = TREE_TYPE (tdecl);
+#endif
+
+ tdecl = lookup_name (get_identifier ("__builtin_type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __bltn_desc_type_node = TREE_TYPE (tdecl);
+
+ tdecl = lookup_name (get_identifier ("__user_type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __user_desc_type_node = TREE_TYPE (tdecl);
+
+ tdecl = lookup_name (get_identifier ("__class_type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __class_desc_type_node = TREE_TYPE (tdecl);
+
+ tdecl = lookup_field (__class_desc_type_node,
+ get_identifier ("access_mode"), 0, 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __access_mode_type_node = TREE_TYPE (tdecl);
+
+ tdecl = lookup_name (get_identifier ("__attr_type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __attr_desc_type_node = TREE_TYPE (tdecl);
+
+ tdecl = lookup_name (get_identifier ("__pointer_type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __ptr_desc_type_node = TREE_TYPE (tdecl);
+
+ tdecl = lookup_name (get_identifier ("__func_type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __func_desc_type_node = TREE_TYPE (tdecl);
+
+ tdecl = lookup_name (get_identifier ("__ptmf_type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __ptmf_desc_type_node = TREE_TYPE (tdecl);
+
+ tdecl = lookup_name (get_identifier ("__ptmd_type_info"), 0);
+ if (tdecl == NULL_TREE)
+ return 0;
+ __ptmd_desc_type_node = TREE_TYPE (tdecl);
+
+ return 1;
+}
/* Make a definition for a builtin function named NAME and whose data type
is TYPE. TYPE should be a function type with argument types.
FUNCTION_CODE tells later passes how to compile calls to this function.
tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
+ DECL_INTERFACE_KNOWN (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
/* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
we cannot change DECL_ASSEMBLER_NAME until we have installed this
if (function_code != NOT_BUILT_IN)
{
DECL_BUILT_IN (decl) = 1;
- DECL_SET_FUNCTION_CODE (decl, function_code);
+ DECL_FUNCTION_CODE (decl) = function_code;
}
return decl;
}
tree declspecs;
{
int found_tag = 0;
- int warned = 0;
- int static_or_extern = 0;
+ tree ob_modifier = NULL_TREE;
register tree link;
register enum tree_code code, ok_code = ERROR_MARK;
register tree t = NULL_TREE;
code = TREE_CODE (value);
if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
- /* Used to test also that TYPE_SIZE (value) != 0.
- That caused warning for `struct foo;' at top level in the file. */
{
- register tree name = TYPE_NAME (value);
-
- if (name == NULL_TREE)
- name = lookup_tag_reverse (value, NULL_TREE);
-
- if (name && TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
-
- t = lookup_tag (code, name, inner_binding_level, 1);
+ my_friendly_assert (TYPE_NAME (value) != NULL_TREE, 261);
- if (t == NULL_TREE)
- {
- push_obstacks (&permanent_obstack, &permanent_obstack);
- if (IS_AGGR_TYPE_CODE (code))
- t = make_lang_type (code);
- else
- t = make_node (code);
- pushtag (name, t, 0);
- pop_obstacks ();
- ok_code = code;
- break;
- }
- else if (name != NULL_TREE || code == ENUMERAL_TYPE)
- ok_code = code;
+ if (code == ENUMERAL_TYPE && TYPE_SIZE (value) == 0)
+ cp_error ("forward declaration of `%#T'", value);
- if (ok_code != ERROR_MARK)
- found_tag++;
- else
- {
- if (!warned)
- pedwarn ("useless keyword or type name in declaration");
- warned = 1;
- }
+ t = value;
+ ok_code = code;
+ found_tag++;
}
else if (value == ridpointers[(int) RID_STATIC]
- || value == ridpointers[(int) RID_EXTERN])
- static_or_extern = 1;
+ || value == ridpointers[(int) RID_EXTERN]
+ || value == ridpointers[(int) RID_AUTO]
+ || value == ridpointers[(int) RID_REGISTER]
+ || value == ridpointers[(int) RID_INLINE]
+ || value == ridpointers[(int) RID_VIRTUAL]
+ || value == ridpointers[(int) RID_EXPLICIT])
+ ob_modifier = value;
}
/* This is where the variables in an anonymous union are
function members. */
if (TYPE_FIELDS (t))
{
- tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, NULL_TREE);
+ tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
+ NULL_TREE);
finish_anon_union (decl);
}
else
else
{
/* Anonymous unions are objects, that's why we only check for
- static/extern specifiers in this branch. */
- if (static_or_extern)
- error ("static/extern can only be specified for objects and functions");
+ inappropriate specifiers in this branch. */
- if (ok_code == RECORD_TYPE
- && found_tag == 1
- && TYPE_LANG_SPECIFIC (t)
- && CLASSTYPE_DECLARED_EXCEPTION (t))
+ if (ob_modifier)
{
- if (TYPE_SIZE (t))
- cp_error ("redeclaration of exception `%T'", t);
+ if (ob_modifier == ridpointers[(int) RID_INLINE]
+ || ob_modifier == ridpointers[(int) RID_VIRTUAL])
+ cp_error ("`%D' can only be specified for functions", ob_modifier);
+ else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
+ cp_error ("`%D' can only be specified for constructors",
+ ob_modifier);
else
- {
- tree ename, decl;
-
- push_obstacks (&permanent_obstack, &permanent_obstack);
-
- pushclass (t, 0);
- finish_exception (t, NULL_TREE);
-
- ename = TYPE_NAME (t);
- if (TREE_CODE (ename) == TYPE_DECL)
- ename = DECL_NAME (ename);
- decl = build_lang_field_decl (VAR_DECL, ename, t);
- finish_exception_decl (current_class_name, decl);
- end_exception_decls ();
-
- pop_obstacks ();
- }
+ cp_error ("`%D' can only be specified for objects and functions",
+ ob_modifier);
}
- else if (!warned && found_tag > 1)
- warning ("multiple types in one declaration");
+
+ if (found_tag == 0)
+ pedwarn ("abstract declarator used as declaration");
+ else if (found_tag > 1)
+ pedwarn ("multiple types in one declaration");
}
}
\f
/* This should only be done once on the top most decl. */
if (have_extern_spec && !used_extern_spec)
{
- declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
+ declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"),
+ declspecs);
used_extern_spec = 1;
}
pop_obstacks ();
}
- /* Interesting work for this is done in `finish_exception_decl'. */
- if (TREE_CODE (type) == RECORD_TYPE
- && CLASSTYPE_DECLARED_EXCEPTION (type))
- return decl;
-
/* Corresponding pop_obstacks is done in `finish_decl'. */
push_obstacks_nochange ();
DECL_ARGUMENTS (decl) = args;
}
d = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), TREE_TYPE (decl));
- if (interface_unknown && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
- warn_if_unknown_interface ();
- TREE_PUBLIC (d) = TREE_PUBLIC (decl) = flag_external_templates && !interface_unknown;
+ TREE_PUBLIC (d) = TREE_PUBLIC (decl);
TREE_STATIC (d) = TREE_STATIC (decl);
DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl)
&& !(context && !DECL_THIS_EXTERN (decl)));
DECL_TEMPLATE_RESULT (d) = decl;
- DECL_OVERLOADED (d) = 1;
decl = d;
}
- if (context && TYPE_SIZE (context) != NULL_TREE)
- {
- /* If it was not explicitly declared `extern',
- revoke any previous claims of DECL_EXTERNAL. */
- if (DECL_THIS_EXTERN (decl) == 0)
- DECL_EXTERNAL (decl) = 0;
- if (DECL_LANG_SPECIFIC (decl))
- DECL_IN_AGGR_P (decl) = 0;
- pushclass (context, 2);
- }
-
/* If this type of object needs a cleanup, and control may
jump past it, make a new binding level so that it is cleaned
up only when it is initialized first. */
default:
/* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */
- if (TYPE_SIZE (type) != NULL_TREE)
+ if (type == error_mark_node)
+ ; /* Don't complain again. */
+ else if (TYPE_SIZE (type) != NULL_TREE)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
DECL_INITIAL (decl) = error_mark_node;
}
+ if (context && TYPE_SIZE (context) != NULL_TREE)
+ {
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
+ if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
+ cp_error ("`%#D' is not a static member of `%#T'", decl, context);
+ else if (duplicate_decls (decl, field))
+ decl = field;
+ }
+
+ /* If it was not explicitly declared `extern',
+ revoke any previous claims of DECL_EXTERNAL. */
+ if (DECL_THIS_EXTERN (decl) == 0)
+ DECL_EXTERNAL (decl) = 0;
+ if (DECL_LANG_SPECIFIC (decl))
+ DECL_IN_AGGR_P (decl) = 0;
+ pushclass (context, 2);
+ }
+
/* Add this decl to the current binding level, but not if it
comes from another scope, e.g. a static member variable.
TEM may equal DECL or it may be a previous decl of the same name. */
+
if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE)
|| (TREE_CODE (decl) == TEMPLATE_DECL && !global_bindings_p ())
|| TREE_CODE (type) == LANG_TYPE)
tem = decl;
else
- {
- tem = pushdecl (decl);
- if (is_overloaded_fn (tem))
- {
- tree tem2;
- tem = get_first_fn (tem);
- tem2 = decl_value_member (decl, tem);
-
- if (tem2 != NULL_TREE)
- tem = tem2;
- else
- {
- while (tem && ! decls_match (decl, tem))
- tem = DECL_CHAIN (tem);
- if (tem == NULL_TREE)
- tem = decl;
- }
- }
- }
+ tem = pushdecl (decl);
- /* Tell the back-end to use or not use .common as appropriate. */
- DECL_COMMON (tem) = flag_conserve_space;
+ /* Tell the back-end to use or not use .common as appropriate. If we say
+ -fconserve-space, we want this to save space, at the expense of wrong
+ semantics. If we say -fno-conserve-space, we want this to produce
+ errors about redefs; to do this we force variables into the data
+ segment. Common storage is okay for non-public uninitialized data;
+ the linker can't match it with storage from other files, and we may
+ save some disk space. */
+ DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
#if 0
/* We don't do this yet for GNU C++. */
}
#endif
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_OVERLOADED (decl))
- /* @@ Also done in start_function. */
- tem = push_overloaded_decl (tem, 1);
- else if (TREE_CODE (decl) == TEMPLATE_DECL)
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
{
tree result = DECL_TEMPLATE_RESULT (decl);
if (DECL_CONTEXT (result) != NULL_TREE)
return NULL_TREE;
}
- if (/* TREE_CODE (result) == VAR_DECL */ 1)
- {
+ if (TREE_CODE (result) == FUNCTION_DECL)
+ return tem;
+ else if (TREE_CODE (result) == VAR_DECL)
+ {
#if 0
tree tmpl = UPT_TEMPLATE (type);
DECL_TEMPLATE_MEMBERS (tmpl)
= perm_tree_cons (DECL_NAME (tem), tem,
DECL_TEMPLATE_MEMBERS (tmpl));
-#endif
return tem;
+#else
+ sorry ("static data member templates");
+ return NULL_TREE;
+#endif
}
- my_friendly_abort (13);
+ else
+ my_friendly_abort (13);
}
else if (TREE_CODE (result) == FUNCTION_DECL)
- tem = push_overloaded_decl (tem, 0);
- else if (TREE_CODE (result) == VAR_DECL
- || TREE_CODE (result) == TYPE_DECL)
+ /*tem = push_overloaded_decl (tem, 0)*/;
+ else if (TREE_CODE (result) == VAR_DECL)
+ {
+ cp_error ("data template `%#D' must be member of a class template",
+ result);
+ return NULL_TREE;
+ }
+ else if (TREE_CODE (result) == TYPE_DECL)
{
cp_error ("invalid template `%#D'", result);
return NULL_TREE;
use temporary storage. Do this even if we will ignore the value. */
if (current_binding_level == global_binding_level && debug_temp_inits)
{
- if (TYPE_NEEDS_CONSTRUCTING (type) || TREE_CODE (type) == REFERENCE_TYPE)
+ if (TYPE_NEEDS_CONSTRUCTING (type)
+ || TREE_CODE (type) == REFERENCE_TYPE)
/* In this case, the initializer must lay down in permanent
storage, since it will be saved until `finish_file' is run. */
;
return tem;
}
+#if 0 /* unused */
static void
make_temporary_for_reference (decl, ctor_call, init, cleanupp)
tree decl, ctor_call, init;
{
DECL_INITIAL (tmp) = init;
TREE_STATIC (tmp) = current_binding_level == global_binding_level;
- finish_decl (tmp, init, 0, 0);
+ finish_decl (tmp, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
}
if (TREE_STATIC (tmp))
preserve_initializer ();
}
+#endif
/* Handle initialization of references.
These three arguments from from `finish_decl', and have the
tree decl, type, init;
tree *cleanupp;
{
- char *errstr = NULL;
- int is_reference;
tree tmp;
- tree this_ptr_type, actual_init = NULL_TREE;
if (init == NULL_TREE)
{
- if (DECL_LANG_SPECIFIC (decl) == 0
- || DECL_IN_AGGR_P (decl) == 0)
+ if ((DECL_LANG_SPECIFIC (decl) == 0
+ || DECL_IN_AGGR_P (decl) == 0)
+ && ! DECL_THIS_EXTERN (decl))
{
cp_error ("`%D' declared as reference but not initialized", decl);
if (TREE_CODE (decl) == VAR_DECL)
if (TREE_CODE (init) == TREE_LIST)
init = build_compound_expr (init);
- is_reference = TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE;
- tmp = is_reference ? convert_from_reference (init) : init;
+
+ if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
+ init = convert_from_reference (init);
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
{
- /* Note: default conversion is only called in very
- special cases. */
+ /* Note: default conversion is only called in very special cases. */
init = default_conversion (init);
}
- /* Can we just enreference this lvalue? */
- if ((is_reference || lvalue_p (init)
- || (actual_init = unary_complex_lvalue (ADDR_EXPR, init)))
- && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
- TYPE_MAIN_VARIANT (TREE_TYPE (tmp)), 0))
- {
- /* This section implements ANSI C++ June 5 1992 WP 8.4.3.5. */
-
- /* A reference to a volatile T cannot be initialized with
- a const T, and vice-versa. */
- if (TYPE_VOLATILE (TREE_TYPE (type)) && TREE_READONLY (init))
- errstr = "cannot initialize a reference to a volatile `%T' with a const `%T'";
- else if (TYPE_READONLY (TREE_TYPE (type)) && TREE_THIS_VOLATILE (init))
- errstr = "cannot initialize a reference to a const `%T' with a volatile `%T'";
- /* A reference to a plain T can be initialized only with a plain T. */
- else if (!TYPE_VOLATILE (TREE_TYPE (type))
- && !TYPE_READONLY (TREE_TYPE (type)))
- {
- if (TREE_READONLY (init))
- errstr = "cannot initialize a reference to `%T' with a const `%T'";
- else if (TREE_THIS_VOLATILE (init))
- errstr = "cannot initialize a reference to `%T' with a volatile `%T'";
- }
- if (errstr)
- {
- cp_error (errstr, TREE_TYPE (type), TREE_TYPE (tmp));
- goto fail;
- }
- }
- /* OK, can we generate a reference then? */
- else if ((actual_init = convert_to_reference
- (decl, type, init, 0, 0, "initialization", 0,
- LOOKUP_SPECULATIVELY|LOOKUP_NORMAL)))
- {
- if (actual_init == error_mark_node)
- goto fail;
+ tmp = convert_to_reference
+ (type, init, CONV_IMPLICIT, LOOKUP_SPECULATIVELY|LOOKUP_NORMAL, decl);
- init = actual_init;
- is_reference = 1;
- }
- /* OK, try going through a temporary. */
- else if ((actual_init = convert_to_reference
- (error_mark_node, type, init, 0, 0, "initialization",
- 0, LOOKUP_NORMAL)))
+ if (tmp == error_mark_node)
+ goto fail;
+ else if (tmp != NULL_TREE)
{
- if (actual_init == error_mark_node)
- goto fail;
-
- init = actual_init;
- is_reference = 1;
+ tree subtype = TREE_TYPE (type);
+ init = tmp;
- if (TREE_CODE (init) == WITH_CLEANUP_EXPR)
+ /* Associate the cleanup with the reference so that we
+ don't get burned by "aggressive" cleanup policy. */
+ if (TYPE_NEEDS_DESTRUCTOR (subtype))
{
- /* Associate the cleanup with the reference so that we
- don't get burned by "aggressive" cleanup policy. */
- *cleanupp = TREE_OPERAND (init, 2);
- TREE_OPERAND (init, 2) = error_mark_node;
+ if (TREE_CODE (init) == WITH_CLEANUP_EXPR)
+ {
+ *cleanupp = TREE_OPERAND (init, 2);
+ TREE_OPERAND (init, 2) = error_mark_node;
+ }
+ else
+ {
+ if (TREE_CODE (tmp) == ADDR_EXPR)
+ tmp = TREE_OPERAND (tmp, 0);
+ if (TREE_CODE (tmp) == TARGET_EXPR)
+ {
+ *cleanupp = build_delete
+ (TYPE_POINTER_TO (subtype),
+ build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0),
+ integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
+ TREE_OPERAND (tmp, 2) = error_mark_node;
+ }
+ }
}
+
+ DECL_INITIAL (decl) = save_expr (init);
}
else
{
goto fail;
}
- /* In the case of initialization, it is permissible
- to assign one reference to another. */
- this_ptr_type = build_pointer_type (TREE_TYPE (type));
-
- if (is_reference)
- {
- if (TREE_SIDE_EFFECTS (init))
- DECL_INITIAL (decl) = save_expr (init);
- else
- DECL_INITIAL (decl) = init;
- }
- else if (lvalue_p (init))
- {
- tmp = build_unary_op (ADDR_EXPR, init, 0);
- if (TREE_CODE (tmp) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (tmp, 0)) == WITH_CLEANUP_EXPR)
- {
- if (*cleanupp) my_friendly_abort (1);
- *cleanupp = TREE_OPERAND (TREE_OPERAND (tmp, 0), 2);
- TREE_OPERAND (TREE_OPERAND (tmp, 0), 2) = error_mark_node;
- }
- if (IS_AGGR_TYPE (TREE_TYPE (this_ptr_type)))
- DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), tmp);
- else
- DECL_INITIAL (decl) = convert (this_ptr_type, tmp);
-
- DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
- if (DECL_INITIAL (decl) == current_class_decl)
- DECL_INITIAL (decl) = copy_node (current_class_decl);
- TREE_TYPE (DECL_INITIAL (decl)) = type;
- }
- /* If actual_init is set here, it is set from the first check above. */
- else if (actual_init)
- {
- /* The initializer for this decl goes into its
- DECL_REFERENCE_SLOT. Make sure that we can handle
- multiple evaluations without ill effect. */
- if (TREE_CODE (actual_init) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (actual_init, 0)) == TARGET_EXPR)
- actual_init = save_expr (actual_init);
- DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), actual_init);
- DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
- TREE_TYPE (DECL_INITIAL (decl)) = type;
- }
- else
- my_friendly_abort (1);
-
- done:
/* ?? Can this be optimized in some cases to
hand back the DECL_INITIAL slot?? */
if (TYPE_SIZE (TREE_TYPE (type)))
return;
}
+/* Fill in DECL_INITIAL with some magical value to prevent expand_decl from
+ mucking with forces it does not comprehend (i.e. initialization with a
+ constructor). If we are at global scope and won't go into COMMON, fill
+ it in with a dummy CONSTRUCTOR to force the variable into .data;
+ otherwise we can use error_mark_node. */
+
+static tree
+obscure_complex_init (decl, init)
+ tree decl, init;
+{
+ if (! flag_no_inline && TREE_STATIC (decl))
+ {
+ if (extract_init (decl, init))
+ return NULL_TREE;
+ }
+
+ if (current_binding_level == global_binding_level
+ && ! DECL_COMMON (decl))
+ DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE,
+ NULL_TREE);
+ else
+ DECL_INITIAL (decl) = error_mark_node;
+
+ return init;
+}
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
INIT0 holds the value of an initializer that should be allowed to escape
the normal rules.
+ FLAGS is LOOKUP_ONLYCONVERTING is the = init syntax was used, else 0
+ if the (init) syntax was used.
+
For functions that take default parameters, DECL points to its
"maximal" instantiation. `finish_decl' must then also declared its
subsequently lower and lower forms of instantiation, checking for
ambiguity as it goes. This can be sped up later. */
void
-finish_decl (decl, init, asmspec_tree, need_pop)
+finish_decl (decl, init, asmspec_tree, need_pop, flags)
tree decl, init;
tree asmspec_tree;
int need_pop;
+ int flags;
{
register tree type;
tree cleanup = NULL_TREE, ttype;
return;
}
+ /* If a name was specified, get the string. */
if (asmspec_tree)
- {
asmspec = TREE_STRING_POINTER (asmspec_tree);
- /* Zero out old RTL, since we will rewrite it. */
- DECL_RTL (decl) = NULL_RTX;
- }
/* If the type of the thing we are declaring either has
a constructor, or has a virtual function table pointer,
type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ {
+ if (current_binding_level == global_binding_level && temporary)
+ end_temporary_allocation ();
+
+ return;
+ }
+
was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
/* Take care of TYPE_DECLs up front. */
TREE_TYPE (decl) = type = TREE_TYPE (init);
DECL_INITIAL (decl) = init = NULL_TREE;
}
- if (IS_AGGR_TYPE (type) && DECL_NAME (decl))
+ if (type != error_mark_node
+ && IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
cp_warning ("shadowing previous type declaration of `%#D'", decl);
DECL_CONTEXT (decl) == NULL_TREE, 0);
goto finish_end;
}
- if (type != error_mark_node && IS_AGGR_TYPE (type)
- && CLASSTYPE_DECLARED_EXCEPTION (type))
- {
- finish_exception_decl (NULL_TREE, decl);
- CLASSTYPE_GOT_SEMICOLON (type) = 1;
- goto finish_end;
- }
if (TREE_CODE (decl) != FUNCTION_DECL)
{
ttype = target_type (type);
if (asmspec)
{
/* This must override the asm specifier which was placed
- by grokclassfn. Lay this out fresh.
-
- @@ Should emit an error if this redefines an asm-specified
- @@ name, or if we have already used the function's name. */
+ by grokclassfn. Lay this out fresh. */
DECL_RTL (TREE_TYPE (decl)) = NULL_RTX;
DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
make_decl_rtl (decl, asmspec, 0);
else if (TREE_CODE (type) == REFERENCE_TYPE
|| (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE_REFERENCE (type)))
{
+ if (TREE_STATIC (decl))
+ make_decl_rtl (decl, NULL_PTR,
+ current_binding_level == global_binding_level
+ || pseudo_global_level_p ());
grok_reference_init (decl, type, init, &cleanup);
init = NULL_TREE;
}
GNU_xref_decl (current_function_decl, decl);
- if (TREE_CODE (decl) == FIELD_DECL || DECL_EXTERNAL (decl))
+ if (TREE_CODE (decl) == FIELD_DECL)
;
else if (TREE_CODE (decl) == CONST_DECL)
{
{
if (TREE_CODE (type) == ARRAY_TYPE)
init = digest_init (type, init, (tree *) 0);
- else if (TREE_CODE (init) == CONSTRUCTOR
- && CONSTRUCTOR_ELTS (init) != NULL_TREE)
+ else if (TREE_CODE (init) == CONSTRUCTOR)
{
if (TYPE_NEEDS_CONSTRUCTING (type))
{
- cp_error ("`%D' must be initialized by constructor, not by `{...}'", decl);
+ cp_error ("`%D' must be initialized by constructor, not by `{...}'",
+ decl);
init = error_mark_node;
}
else
}
}
#endif
-
- /* We must hide the initializer so that expand_decl
- won't try to do something it does not understand. */
- if (current_binding_level == global_binding_level)
- {
- tree value;
- if (flag_conserve_space)
- /* If we say -fconserve-space, we want this to save
- space, at the expense of wrong semantics. */
- /* Should this be a NULL_TREE? */
- value = error_mark_node;
- else
- /* If we say -fno-conserve-space, we want this to
- produce errors about redefs, to do this we make it
- go in the data space */
- value = digest_init (type, empty_init_node, (tree *) 0);
- DECL_INITIAL (decl) = value;
- }
- else
- DECL_INITIAL (decl) = error_mark_node;
}
else
{
dont_use_constructor:
if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init);
-
- if (init)
- /* Don't let anyone try to initialize this variable
- until we are ready to do so. */
- DECL_INITIAL (decl) = error_mark_node;
}
+
+ if (init)
+ /* We must hide the initializer so that expand_decl
+ won't try to do something it does not understand. */
+ init = obscure_complex_init (decl, init);
}
+ else if (DECL_EXTERNAL (decl))
+ ;
else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
&& (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
{
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype))
cp_error ("structure `%D' with uninitialized const members", decl);
if (CLASSTYPE_REF_FIELDS_NEED_INIT (ctype))
- cp_error ("structure `%D' with uninitialized reference members", decl);
+ cp_error ("structure `%D' with uninitialized reference members",
+ decl);
}
if (TREE_CODE (decl) == VAR_DECL
&& (TYPE_READONLY (type) || TREE_READONLY (decl)))
cp_error ("uninitialized const `%D'", decl);
- /* Initialize variables in need of static initialization
- with `empty_init_node' to keep assemble_variable from putting them
- in the wrong program space. (Common storage is okay for non-public
- uninitialized data; the linker can't match it with storage from other
- files, and we may save some disk space.) */
- if (flag_pic == 0
- && TREE_STATIC (decl)
- && TREE_PUBLIC (decl)
- && ! DECL_EXTERNAL (decl)
- && TREE_CODE (decl) == VAR_DECL
- && TYPE_NEEDS_CONSTRUCTING (type)
- && (DECL_INITIAL (decl) == NULL_TREE
- || DECL_INITIAL (decl) == error_mark_node)
- /* If we say -fconserve-space, we want this to save space,
- at the expense of wrong semantics. */
- && ! flag_conserve_space)
- {
- tree value = digest_init (type, empty_init_node, (tree *) 0);
- DECL_INITIAL (decl) = value;
- }
+ if (TYPE_SIZE (type) != NULL_TREE
+ && TYPE_NEEDS_CONSTRUCTING (type))
+ init = obscure_complex_init (decl, NULL_TREE);
}
else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
/* Let debugger know it should output info for this type. */
note_debug_info_needed (ttype);
+ if (TREE_STATIC (decl) && DECL_CONTEXT (decl)
+ && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
+ note_debug_info_needed (DECL_CONTEXT (decl));
+
if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
&& DECL_SIZE (decl) != NULL_TREE
&& ! TREE_CONSTANT (DECL_SIZE (decl)))
cleanup = TREE_OPERAND (init, 2);
init = TREE_OPERAND (init, 0);
current_binding_level->have_cleanups = 1;
- current_binding_level->more_exceptions_ok = 0;
}
else
cleanup = maybe_build_cleanup (decl);
if (was_temp)
end_temporary_allocation ();
- /* If we are in need of a cleanup, get out of any implicit
- handlers that have been established so far. */
- if (cleanup && current_binding_level->parm_flag == 3)
- {
- pop_implicit_try_blocks (decl);
- current_binding_level->more_exceptions_ok = 0;
- }
-
if (TREE_CODE (decl) == VAR_DECL
&& current_binding_level != global_binding_level
&& ! TREE_STATIC (decl)
&& TREE_READONLY (decl)
&& DECL_INITIAL (decl) != NULL_TREE
&& DECL_INITIAL (decl) != error_mark_node
- && DECL_INITIAL (decl) != empty_init_node)
+ && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
{
DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0);
TREE_ASM_WRITTEN (decl) = 1;
}
- else if (toplev)
+ else if (toplev && ! TREE_PUBLIC (decl))
{
- /* Keep GCC from complaining that this variable
- is defined but never used. */
- TREE_USED (decl) = 1;
/* If this is a static const, change its apparent linkage
- if it belongs to a #pragma interface. */
- if (TREE_STATIC (decl) && !interface_unknown)
+ if it belongs to a #pragma interface. */
+ if (!interface_unknown)
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = interface_only;
signature_error (decl, TREE_TYPE (type));
if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- /* C++: Handle overloaded functions with default parameters. */
- if (DECL_OVERLOADED (decl))
- {
- tree parmtypes = TYPE_ARG_TYPES (type);
- tree prev = NULL_TREE;
- tree original_name = DECL_NAME (decl);
- struct lang_decl *tmp_lang_decl = DECL_LANG_SPECIFIC (decl);
- /* All variants will share an uncollectible lang_decl. */
- copy_decl_lang_specific (decl);
-
- while (parmtypes && parmtypes != void_list_node)
- {
- /* The default value for the parameter in parmtypes is
- stored in the TREE_PURPOSE of the TREE_LIST. */
- if (TREE_PURPOSE (parmtypes))
- {
- tree fnname, fndecl;
- tree *argp;
-
- argp = prev ? & TREE_CHAIN (prev)
- : & TYPE_ARG_TYPES (type);
-
- *argp = NULL_TREE;
- fnname = build_decl_overload (original_name, TYPE_ARG_TYPES (type), 0);
- *argp = parmtypes;
- fndecl = build_decl (FUNCTION_DECL, fnname, type);
- DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl);
- TREE_PUBLIC (fndecl) = TREE_PUBLIC (decl);
- DECL_INLINE (fndecl) = DECL_INLINE (decl);
- /* Keep G++ from thinking this function is unused.
- It is only used to speed up search in name space. */
- TREE_USED (fndecl) = 1;
- TREE_ASM_WRITTEN (fndecl) = 1;
- DECL_INITIAL (fndecl) = NULL_TREE;
- DECL_LANG_SPECIFIC (fndecl) = DECL_LANG_SPECIFIC (decl);
- fndecl = pushdecl (fndecl);
- DECL_INITIAL (fndecl) = error_mark_node;
- DECL_RTL (fndecl) = DECL_RTL (decl);
- }
- prev = parmtypes;
- parmtypes = TREE_CHAIN (parmtypes);
- }
- DECL_LANG_SPECIFIC (decl) = tmp_lang_decl;
- }
- }
+ ;
else if (DECL_EXTERNAL (decl))
;
else if (TREE_STATIC (decl) && type != error_mark_node)
}
else if (! toplev)
{
+ tree old_cleanups = cleanups_this_call;
/* This is a declared decl which must live until the
end of the binding contour. It may need a cleanup. */
expand_decl (decl);
else if (cleanup)
{
- expand_decl_cleanup (NULL_TREE, cleanup);
+ /* XXX: Why don't we use decl here? */
+ /* Ans: Because it was already expanded? */
+ if (! expand_decl_cleanup (NULL_TREE, cleanup))
+ cp_error ("parser lost in parsing declaration of `%D'",
+ decl);
/* Cleanup used up here. */
cleanup = NULL_TREE;
}
if (init || TYPE_NEEDS_CONSTRUCTING (type))
{
- emit_line_note (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
- expand_aggr_init (decl, init, 0);
+ emit_line_note (DECL_SOURCE_FILE (decl),
+ DECL_SOURCE_LINE (decl));
+ expand_aggr_init (decl, init, 0, flags);
}
- /* Set this to 0 so we can tell whether an aggregate
- which was initialized was ever used. */
- if (TYPE_NEEDS_CONSTRUCTING (type))
+ /* Set this to 0 so we can tell whether an aggregate which
+ was initialized was ever used. Don't do this if it has a
+ destructor, so we don't complain about the 'resource
+ allocation is initialization' idiom. */
+ if (TYPE_NEEDS_CONSTRUCTING (type) && cleanup == NULL_TREE)
TREE_USED (decl) = 0;
/* Store the cleanup, if there was one. */
if (cleanup)
{
if (! expand_decl_cleanup (decl, cleanup))
- cp_error ("parser lost in parsing declaration of `%D'", decl);
+ cp_error ("parser lost in parsing declaration of `%D'",
+ decl);
}
}
+ /* Cleanup any temporaries needed for the initial value. */
+ expand_cleanups_to (old_cleanups);
}
finish_end0:
finish_end:
+ /* If requested, warn about definitions of large data objects. */
+
+ if (warn_larger_than
+ && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
+ && !DECL_EXTERNAL (decl))
+ {
+ register tree decl_size = DECL_SIZE (decl);
+
+ if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
+ {
+ unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
+
+ if (units > larger_than_size)
+ warning_with_decl (decl, "size of `%s' is %u bytes", units);
+ }
+ }
+
if (need_pop)
{
/* Resume permanent allocation, if not within a function. */
tree init;
{
tree oldstatic = value_member (decl, static_aggregates);
+ tree old_cleanups;
+
if (oldstatic)
{
if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
cp_error ("multiple initializations given for `%D'", decl);
}
- else if (current_binding_level != global_binding_level)
+ else if (current_binding_level != global_binding_level
+ && current_binding_level->pseudo_global == 0)
{
/* Emit code to perform this initialization but once. */
tree temp;
rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
expand_start_cond (build_binary_op (EQ_EXPR, temp,
integer_zero_node, 1), 0);
+ old_cleanups = cleanups_this_call;
expand_assignment (temp, integer_one_node, 0, 0);
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+ || TREE_CODE (init) == TREE_LIST)
{
- expand_aggr_init (decl, init, 0);
+ expand_aggr_init (decl, init, 0, 0);
do_pending_stack_adjust ();
}
else
expand_assignment (decl, init, 0, 0);
+ /* Cleanup any temporaries needed for the initial value. */
+ expand_cleanups_to (old_cleanups);
expand_end_cond ();
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
{
/* Note MAXINDEX is really the maximum index,
one less than the size. */
if (TREE_CODE (initial_value) == STRING_CST)
- maxindex = build_int_2 (TREE_STRING_LENGTH (initial_value) - 1, 0);
+ {
+ int eltsize
+ = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
+ maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
+ / eltsize) - 1, 0);
+ }
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
- register int nelts
- = list_length (CONSTRUCTOR_ELTS (initial_value));
- maxindex = build_int_2 (nelts - 1, - (nelts == 0));
+ tree elts = CONSTRUCTOR_ELTS (initial_value);
+ maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
+ for (; elts; elts = TREE_CHAIN (elts))
+ {
+ if (TREE_PURPOSE (elts))
+ maxindex = TREE_PURPOSE (elts);
+ else
+ maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node);
+ }
+ maxindex = copy_node (maxindex);
}
else
{
if (maxindex)
{
+ tree itype;
+
TYPE_DOMAIN (type) = build_index_type (maxindex);
if (!TREE_TYPE (maxindex))
TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+ if (initial_value)
+ itype = TREE_TYPE (initial_value);
+ else
+ itype = NULL;
+ if (itype && !TYPE_DOMAIN (itype))
+ TYPE_DOMAIN (itype) = TYPE_DOMAIN (type);
}
/* Lay out the type now that we can get the real answer. */
if (inlinep)
cp_error ("`%D' declared as an `inline' %s", object, type);
if (quals)
- cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration", object, type);
+ cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration",
+ object, type);
if (friendp)
cp_error_at ("invalid friend declaration", object);
if (raises)
- cp_error_at ("invalid raises declaration", object);
+ cp_error_at ("invalid exception specifications", object);
}
/* CTYPE is class type, or null if non-class.
CHECK is 1 if we must find this method in CTYPE, 0 if we should
not look, and -1 if we should not call `grokclassfn' at all. */
static tree
-grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publicp)
+grokfndecl (ctype, type, declarator, virtualp, flags, quals,
+ raises, check, publicp, inlinep)
tree ctype, type;
tree declarator;
int virtualp;
enum overload_flags flags;
tree quals, raises;
- int check, publicp;
+ int check, publicp, inlinep;
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
DECL_CLASS_CONTEXT (decl) = ctype;
}
- if (publicp)
- TREE_PUBLIC (decl) = 1;
+ /* All function decls start out public; we'll fix their linkage later (at
+ definition or EOF) if appropriate. */
+ TREE_PUBLIC (decl) = 1;
+
+ if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
+ {
+ if (inlinep)
+ error ("cannot declare `main' to be inline");
+ else if (! publicp)
+ error ("cannot declare `main' to be static");
+ inlinep = 0;
+ publicp = 1;
+ }
+
+ if (! publicp)
+ DECL_C_STATIC (decl) = 1;
+
+ if (inlinep)
+ DECL_THIS_INLINE (decl) = DECL_INLINE (decl) = 1;
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
grokclassfn (ctype, declarator, decl, flags, quals);
if (check)
check_classfn (ctype, declarator, decl);
- grok_ctor_properties (ctype, decl);
- if (check == 0)
+ if (! grok_ctor_properties (ctype, decl))
+ return NULL_TREE;
+
+ if (check == 0 && ! current_function_decl)
{
- /* FIXME: this should only need to look at IDENTIFIER_GLOBAL_VALUE. */
+ /* FIXME: this should only need to look at
+ IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
if (tmp == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
if (ctype == NULL_TREE || check)
return decl;
- /* Now install the declaration of this function so that
- others may find it (esp. its DECL_FRIENDLIST).
- Pretend we are at top level, we will get true
- reference later, perhaps.
-
- FIXME: This should only need to look at IDENTIFIER_GLOBAL_VALUE. */
- tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
- if (tmp == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
- else if (TREE_CODE (tmp) != TREE_CODE (decl))
- cp_error ("inconsistent declarations for `%D'", decl);
- else
+ /* Now install the declaration of this function so that others may
+ find it (esp. its DECL_FRIENDLIST). Don't do this for local class
+ methods, though. */
+ if (! current_function_decl)
{
- duplicate_decls (decl, tmp);
- decl = tmp;
- /* avoid creating circularities. */
- DECL_CHAIN (decl) = NULL_TREE;
+ /* FIXME: this should only need to look at
+ IDENTIFIER_GLOBAL_VALUE. */
+ tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
+ if (tmp == NULL_TREE)
+ IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
+ else if (TREE_CODE (tmp) != TREE_CODE (decl))
+ cp_error ("inconsistent declarations for `%D'", decl);
+ else
+ {
+ duplicate_decls (decl, tmp);
+ decl = tmp;
+ /* avoid creating circularities. */
+ DECL_CHAIN (decl) = NULL_TREE;
+ }
+ make_decl_rtl (decl, NULL_PTR, 1);
}
- make_decl_rtl (decl, NULL_PTR, 1);
/* If this declaration supersedes the declaration of
a method declared virtual in the base class, then
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)) || flag_all_virtual == 1)
+ if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))
+ || flag_all_virtual == 1)
{
- tmp = get_first_matching_virtual (base_binfo, decl,
- flags == DTOR_FLAG);
+ tmp = get_matching_virtual (base_binfo, decl,
+ flags == DTOR_FLAG);
if (tmp)
{
/* If this function overrides some virtual in some base
path to its virtual baseclass. */
if (staticp)
{
- cp_error ("method `%D' may not be declared static", decl);
- cp_error_at ("(since `%D' declared virtual in base class.)", tmp);
+ cp_error ("method `%D' may not be declared static",
+ decl);
+ cp_error_at ("(since `%D' declared virtual in base class.)",
+ tmp);
break;
}
virtualp = 1;
-#if 0
- /* Disable this as we want the most recent fndecl, not the most
- base fndecl. */
- if ((TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (base_binfo))
- || TYPE_USES_MULTIPLE_INHERITANCE (ctype))
- && BINFO_TYPE (base_binfo) != DECL_CONTEXT (tmp))
- tmp = get_first_matching_virtual (TYPE_BINFO (DECL_CONTEXT (tmp)),
- decl, flags == DTOR_FLAG);
-#endif
- if (value_member (tmp, DECL_VINDEX (decl)) == NULL_TREE)
- {
- /* The argument types may have changed... */
- tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
- tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
-
- argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
- TREE_CHAIN (argtypes));
- /* But the return type has not. */
- type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
- if (raises)
- {
- type = build_exception_variant (ctype, type, raises);
- raises = TYPE_RAISES_EXCEPTIONS (type);
- }
- TREE_TYPE (decl) = type;
- DECL_VINDEX (decl)
- = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
- }
+ {
+ /* The argument types may have changed... */
+ tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
+
+ argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
+ TREE_CHAIN (argtypes));
+ /* But the return type has not. */
+ type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
+ if (raises)
+ {
+ type = build_exception_variant (ctype, type, raises);
+ raises = TYPE_RAISES_EXCEPTIONS (type);
+ }
+ TREE_TYPE (decl) = type;
+ DECL_VINDEX (decl)
+ = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
+ }
+ break;
}
}
}
{
/* If you declare a static member so that it
can be initialized, the code will reach here. */
- tree field = lookup_field (TYPE_OFFSET_BASETYPE (type),
- declarator, 0, 0);
- if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
- {
- tree basetype = TYPE_OFFSET_BASETYPE (type);
- error ("`%s' is not a static member of class `%s'",
- IDENTIFIER_POINTER (declarator),
- TYPE_NAME_STRING (basetype));
- type = TREE_TYPE (type);
- decl = build_lang_field_decl (VAR_DECL, declarator, type);
- DECL_CONTEXT (decl) = basetype;
- DECL_CLASS_CONTEXT (decl) = basetype;
- }
- else
- {
- tree f_type = TREE_TYPE (field);
- tree o_type = TREE_TYPE (type);
-
- if (TYPE_SIZE (f_type) == NULL_TREE)
- {
- if (TREE_CODE (f_type) != TREE_CODE (o_type)
- || (TREE_CODE (f_type) == ARRAY_TYPE
- && TREE_TYPE (f_type) != TREE_TYPE (o_type)))
- error ("redeclaration of type for `%s'",
- IDENTIFIER_POINTER (declarator));
- else if (TYPE_SIZE (o_type) != NULL_TREE)
- TREE_TYPE (field) = type;
- }
- else if (f_type != o_type)
- error ("redeclaration of type for `%s'",
- IDENTIFIER_POINTER (declarator));
- decl = field;
- if (initialized && DECL_INITIAL (decl)
- /* Complain about multiply-initialized
- member variables, but don't be faked
- out if initializer is faked up from `empty_init_node'. */
- && (TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
- || CONSTRUCTOR_ELTS (DECL_INITIAL (decl)) != NULL_TREE))
- error_with_aggr_type (DECL_CONTEXT (decl),
- "multiple initializations of static member `%s::%s'",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- }
+ tree basetype = TYPE_OFFSET_BASETYPE (type);
+ type = TREE_TYPE (type);
+ decl = build_lang_field_decl (VAR_DECL, declarator, type);
+ DECL_CONTEXT (decl) = basetype;
+ DECL_CLASS_CONTEXT (decl) = basetype;
+ DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
}
else
decl = build_decl (VAR_DECL, declarator, type);
+ DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl));
+
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
DECL_THIS_EXTERN (decl) = 1;
{
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
- DECL_EXTERNAL (decl) = !initialized;
+ DECL_EXTERNAL (decl) = 0;
}
/* At top level, either `static' or no s.c. makes a definition
(perhaps tentative), and absence of `static' makes it public. */
u = make_lang_type (UNION_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type);
- fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier, delta_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier,
+ delta_type_node);
finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node);
TYPE_NAME (u) = NULL_TREE;
t = make_lang_type (RECORD_TYPE);
/* Let the front-end know this is a pointer to member function. */
- TYPE_PTRMEMFUNC_FLAG(t) = 1;
-
- fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node);
+ TYPE_PTRMEMFUNC_FLAG (t) = 1;
+ /* and not really an aggregate. */
+ IS_AGGR_TYPE (t) = 0;
+
+ fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
+ delta_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier,
+ delta_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
try to parse.
PARM for a parameter declaration (either within a function prototype
or before a function body). Make a PARM_DECL, or return void_type_node.
+ CATCHPARM for a parameter declaration before a catch clause.
TYPENAME if for a typename (in a cast or sizeof).
Don't make a DECL node; just return the ..._TYPE node.
FIELD for a struct or union field; make a FIELD_DECL.
int longlong = 0;
int constp;
int volatilep;
- int virtualp, friendp, inlinep, staticp;
+ int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
int opaque_typedef = 0;
enum tree_code innermost_code = ERROR_MARK;
int bitfield = 0;
int size_varies = 0;
+ tree decl_machine_attr = NULL_TREE;
/* Set this to error_mark_node for FIELD_DECLs we could not handle properly.
All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */
tree init = NULL_TREE;
tree ctype = current_class_type;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
- int seen_scope_ref = 0;
tree quals = NULL_TREE;
RIDBIT_RESET_ALL (specbits);
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
{
- tree type, last = NULL_TREE;
+ tree last = NULL_TREE;
register tree decl = declarator;
name = NULL;
init = TREE_OPERAND (decl, 1);
decl = start_decl (declarator, declspecs, 1, NULL_TREE);
- finish_decl (decl, init, NULL_TREE, 1);
+ finish_decl (decl, init, NULL_TREE, 1, 0);
return 0;
}
innermost_code = TREE_CODE (decl);
- decl = TREE_OPERAND (decl, 0);
if (decl_context == FIELD && ctype == NULL_TREE)
ctype = current_class_type;
+ if (ctype
+ && TREE_OPERAND (decl, 0) == constructor_name_full (ctype))
+ TREE_OPERAND (decl, 0) = constructor_name (ctype);
+ decl = TREE_OPERAND (decl, 0);
if (ctype != NULL_TREE
&& decl != NULL_TREE && flags != DTOR_FLAG
&& decl == constructor_name (ctype))
case IDENTIFIER_NODE:
dname = decl;
- name = IDENTIFIER_POINTER (decl);
decl = NULL_TREE;
+
+ if (! IDENTIFIER_OPNAME_P (dname)
+ /* Linux headers use '__op'. Arrgh. */
+ || IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname))
+ name = IDENTIFIER_POINTER (dname);
+ else
+ {
+ if (IDENTIFIER_TYPENAME_P (dname))
+ {
+ my_friendly_assert (flags == NO_SPECIAL, 154);
+ flags = TYPENAME_FLAG;
+ ctor_return_type = TREE_TYPE (dname);
+ return_type = return_conversion;
+ }
+ name = operator_name_string (dname);
+ }
break;
case RECORD_TYPE:
decl = NULL_TREE;
break;
- case TYPE_EXPR:
- my_friendly_assert (flags == NO_SPECIAL, 154);
- flags = TYPENAME_FLAG;
- name = "operator <typename>"; /* We don't know the type yet. */
- /* Go to the absdcl. */
- decl = TREE_OPERAND (decl, 0);
- return_type = return_conversion;
- break;
-
/* C++ extension */
case SCOPE_REF:
-/*
- if (seen_scope_ref == 1)
- error ("multiple `::' terms in declarator invalid");
-*/
- seen_scope_ref += 1;
{
/* Perform error checking, and convert class names to types.
We may call grokdeclarator multiple times for the same
}
}
+ if (ctype
+ && TREE_OPERAND (decl, 1) == constructor_name_full (ctype))
+ TREE_OPERAND (decl, 1) = constructor_name (ctype);
decl = TREE_OPERAND (decl, 1);
if (ctype)
{
}
else if (TREE_CODE (decl) == BIT_NOT_EXPR
&& TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
- && constructor_name (ctype) == TREE_OPERAND (decl, 0))
+ && (constructor_name (ctype) == TREE_OPERAND (decl, 0)
+ || constructor_name_full (ctype) == TREE_OPERAND (decl, 0)))
{
return_type = return_dtor;
ctor_return_type = ctype;
flags = DTOR_FLAG;
- decl = TREE_OPERAND (decl, 0);
+ decl = TREE_OPERAND (decl, 0) = constructor_name (ctype);
}
}
}
if (funcdef_flag && innermost_code != CALL_EXPR)
return 0;
+ if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
+ && innermost_code != CALL_EXPR
+ && ! (ctype && declspecs == NULL_TREE))
+ {
+ cp_error ("declaration of `%D' as non-function", dname);
+ return void_type_node;
+ }
+
/* Anything declared one level down from the top level
must be one of the parameters of a function
(because the body is at least two levels down). */
if (TREE_CODE (id) == IDENTIFIER_NODE)
{
- if (id == ridpointers[(int) RID_INT])
- {
- if (type)
- error ("extraneous `int' ignored");
- else
- {
- explicit_int = 1;
- type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
- }
- goto found;
- }
- if (id == ridpointers[(int) RID_CHAR])
+ if (id == ridpointers[(int) RID_INT]
+ || id == ridpointers[(int) RID_CHAR]
+ || id == ridpointers[(int) RID_BOOL]
+ || id == ridpointers[(int) RID_WCHAR])
{
if (type)
- error ("extraneous `char' ignored");
- else
{
- explicit_char = 1;
- type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
+ if (id == ridpointers[(int) RID_BOOL])
+ error ("`bool' is now a keyword");
+ else
+ cp_error ("extraneous `%T' ignored", id);
}
- goto found;
- }
- if (id == ridpointers[(int) RID_WCHAR])
- {
- if (type)
- error ("extraneous `__wchar_t' ignored");
else
{
+ if (id == ridpointers[(int) RID_INT])
+ explicit_int = 1;
+ else if (id == ridpointers[(int) RID_CHAR])
+ explicit_char = 1;
type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
}
goto found;
goto found;
}
- for (i = (int) RID_FIRST_MODIFIER; i < (int) RID_MAX; i++)
+ for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++)
{
if (ridpointers[i] == id)
{
if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
{
-#if 0
- if (pedantic)
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
- else
-#endif
- if (longlong)
- error ("`long long long' is too long for GCC");
+ if (pedantic && ! in_system_header)
+ pedwarn ("ANSI C++ does not support `long long'");
+ else if (longlong)
+ error ("`long long long' is too long for GCC");
else
longlong = 1;
}
else if (RIDBIT_SETP (i, specbits))
- warning ("duplicate `%s'", IDENTIFIER_POINTER (id));
+ pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
RIDBIT_SET (i, specbits);
goto found;
}
else
{
type = TREE_TYPE (t);
+ decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
typedef_decl = t;
}
}
which case the type defaults to `unknown type' and is
instantiated when assigning to a signature pointer or ref. */
+ if (type == NULL_TREE
+ && (RIDBIT_SETP (RID_SIGNED, specbits)
+ || RIDBIT_SETP (RID_UNSIGNED, specbits)
+ || RIDBIT_SETP (RID_LONG, specbits)
+ || RIDBIT_SETP (RID_SHORT, specbits)))
+ {
+ /* These imply 'int'. */
+ type = integer_type_node;
+ explicit_int = 1;
+ }
+
if (type == NULL_TREE)
{
explicit_int = -1;
type = void_type_node;
else if (return_type == return_ctor)
type = TYPE_POINTER_TO (ctor_return_type);
+ else if (return_type == return_conversion)
+ type = ctor_return_type;
else if (current_class_type
&& IS_SIGNATURE (current_class_type)
&& (RIDBIT_SETP (RID_TYPEDEF, specbits)
opaque_typedef = 1;
type = copy_node (opaque_type_node);
}
+ /* access declaration */
+ else if (decl_context == FIELD && declarator
+ && TREE_CODE (declarator) == SCOPE_REF)
+ type = void_type_node;
else
{
- if (funcdef_flag && warn_return_type
- && return_type == return_normal
- && ! (RIDBIT_SETP (RID_SIGNED, specbits)
- || RIDBIT_SETP (RID_UNSIGNED, specbits)
- || RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits)))
- warn_about_return_type = 1;
- /* Save warning until we know what is really going on. */
+ if (funcdef_flag)
+ {
+ if (warn_return_type
+ && return_type == return_normal)
+ /* Save warning until we know what is really going on. */
+ warn_about_return_type = 1;
+ }
+ else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
+ pedwarn ("ANSI C++ forbids typedef which does not specify a type");
+ else if (declspecs == NULL_TREE &&
+ (innermost_code != CALL_EXPR || pedantic))
+ cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type or storage class",
+ dname);
type = integer_type_node;
}
}
error ("return type specification for constructor invalid");
type = TYPE_POINTER_TO (ctor_return_type);
}
+ else if (return_type == return_conversion)
+ {
+ if (comptypes (type, ctor_return_type, 1) == 0)
+ cp_error ("operator `%T' declared to return `%T'",
+ ctor_return_type, type);
+ else
+ cp_pedwarn ("return type specified for `operator %T'",
+ ctor_return_type);
+
+ type = ctor_return_type;
+ }
+ /* Catch typedefs that only specify a type, like 'typedef int;'. */
+ else if (RIDBIT_SETP (RID_TYPEDEF, specbits) && declarator == NULL_TREE)
+ {
+ /* Template "this is a type" syntax; just ignore for now. */
+ if (processing_template_defn)
+ return void_type_node;
+ }
ctype = NULL_TREE;
if (TREE_CODE (type) == REAL_TYPE)
error ("short, signed or unsigned invalid for `%s'", name);
- else if (TREE_CODE (type) != INTEGER_TYPE || type == wchar_type_node)
+ else if (TREE_CODE (type) != INTEGER_TYPE)
error ("long, short, signed or unsigned invalid for `%s'", name);
else if (RIDBIT_SETP (RID_LONG, specbits)
&& RIDBIT_SETP (RID_SHORT, specbits))
volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
+#if 0
+ /* This sort of redundancy is blessed in a footnote to the Sep 94 WP. */
if (constp > 1)
warning ("duplicate `const'");
if (volatilep > 1)
warning ("duplicate `volatile'");
+#endif
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
+ RIDBIT_RESET (RID_VIRTUAL, specbits);
+ explicitp = RIDBIT_SETP (RID_EXPLICIT, specbits) != 0;
+ RIDBIT_RESET (RID_EXPLICIT, specbits);
- /* operators new and delete are implicitly static. */
if (RIDBIT_SETP (RID_STATIC, specbits))
staticp = 1 + (decl_context == FIELD);
staticp = 0;
}
friendp = RIDBIT_SETP (RID_FRIEND, specbits);
- RIDBIT_RESET (RID_VIRTUAL, specbits);
RIDBIT_RESET (RID_FRIEND, specbits);
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
if (decl_context == PARM)
{
- error ("non-member `%s' cannot be declared mutable", name);
+ error ("non-member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (friendp || decl_context == TYPENAME)
{
- error ("non-object member `%s' cannot be declared mutable", name);
+ error ("non-object member `%s' cannot be declared `mutable'", name);
+ RIDBIT_RESET (RID_MUTABLE, specbits);
+ }
+ else if (constp)
+ {
+ error ("const `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (staticp)
{
- error ("static `%s' cannot be declared mutable", name);
+ error ("static `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
#if 0
if (RIDBIT_SETP (RID_TYPEDEF, specbits))
{
- error ("non-object member `%s' cannot be declared mutable", name);
+ error ("non-object member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
/* Because local typedefs are parsed twice, we don't want this
message here. */
else if (decl_context != FIELD)
{
- error ("non-member `%s' cannot be declared mutable", name);
+ error ("non-member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
#endif
}
/* Give error if `virtual' is used outside of class declaration. */
- if (virtualp && current_class_name == NULL_TREE)
+ if (virtualp
+ && (current_class_name == NULL_TREE || decl_context != FIELD))
{
error ("virtual outside class declaration");
virtualp = 0;
}
if (volatilep)
{
- error ("`volatile' specified for signature member function `%s'", name);
+ error ("`volatile' specified for signature member function `%s'",
+ name);
volatilep = 0;
}
if (inlinep)
}
if (virtualp)
{
- error ("`virtual' specified for signature member function `%s'", name);
+ error ("`virtual' specified for signature member function `%s'",
+ name);
/* Later, we'll make signature member functions virtual. */
virtualp = 0;
}
error ("multiple storage classes in declaration of `%s'", name);
else if (decl_context != NORMAL && nclasses > 0)
{
- if (decl_context == PARM
+ if ((decl_context == PARM || decl_context == CATCHPARM)
&& (RIDBIT_SETP (RID_REGISTER, specbits)
|| RIDBIT_SETP (RID_AUTO, specbits)))
;
error ("typedef declaration includes an initializer");
/* To process a class-local typedef declaration, we descend down
- the chain of declspecs looking for the `typedef' spec. When we
- find it, we splice it out of the chain of declspecs, and then
- recursively call `grokdeclarator' with the original declarator
- and with the newly adjusted declspecs. This call should return
- a FIELD_DECL node with the TREE_TYPE (and other parts) set
+ the chain of declspecs looking for the `typedef' spec. When
+ we find it, we replace it with `static', and then recursively
+ call `grokdeclarator' with the original declarator and with
+ the newly adjusted declspecs. This call should return a
+ FIELD_DECL node with the TREE_TYPE (and other parts) set
appropriately. We can then just change the TREE_CODE on that
from FIELD_DECL to TYPE_DECL and we're done. */
if (TREE_VALUE (scanner) == ridpointers[(int) RID_TYPEDEF])
break;
}
+
if (previous_declspec)
TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner);
else
declspecs = TREE_CHAIN (scanner);
-
+
+ declspecs = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
+ declspecs);
+
/* In the recursive call to grokdeclarator we need to know
whether we are working on a signature-local typedef. */
if (IS_SIGNATURE (current_class_type))
loc_typedecl =
grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE);
+
+ if (previous_declspec)
+ TREE_CHAIN (previous_declspec) = scanner;
if (loc_typedecl != error_mark_node)
{
register int *pi;
TREE_SET_CODE (loc_typedecl, TYPE_DECL);
+ /* This is the same field as DECL_ARGUMENTS, which is set for
+ function typedefs by the above grokdeclarator. */
+ DECL_NESTED_TYPENAME (loc_typedecl) = 0;
pi = (int *) permalloc (sizeof (struct lang_decl_flags));
while (i > 0)
return loc_typedecl;
}
else if (decl_context == FIELD
- && (! IS_SIGNATURE (current_class_type))
+ && (! IS_SIGNATURE (current_class_type)
+ || SIGNATURE_GROKKING_TYPEDEF (current_class_type))
/* C++ allows static class elements */
&& RIDBIT_SETP (RID_STATIC, specbits))
/* C++ also allows inlines and signed and unsigned elements,
{
if (decl_context == FIELD)
{
- tree tmp = TREE_OPERAND (declarator, 0);
- register int op = IDENTIFIER_OPNAME_P (tmp);
+ tree tmp = NULL_TREE;
+ register int op = 0;
+
+ if (declarator)
+ {
+ tmp = TREE_OPERAND (declarator, 0);
+ op = IDENTIFIER_OPNAME_P (tmp);
+ }
error ("storage class specified for %s `%s'",
IS_SIGNATURE (current_class_type)
? (op
? "signature member operator"
: "signature member function")
- : (op ? "member operator" : "structure field"),
+ : (op ? "member operator" : "field"),
op ? operator_name_string (tmp) : name);
}
else
- error ((decl_context == PARM
+ error (((decl_context == PARM || decl_context == CATCHPARM)
? "storage class specified for parameter `%s'"
: "storage class specified for typename"), name);
RIDBIT_RESET (RID_REGISTER, specbits);
{
if (current_binding_level == global_binding_level)
{
- /* It's common practice (and completely legal) to have a const
+ /* It's common practice (and completely valid) to have a const
be initialized and declared extern. */
if (! constp)
warning ("`%s' initialized and declared `extern'", name);
qualify the member name.
an ADDR_EXPR (for &...),
a BIT_NOT_EXPR (for destructors)
- a TYPE_EXPR (for operator typenames)
At this point, TYPE is the type of elements of an array,
or for a function to return, or for a pointer to point to.
{
register tree itype = NULL_TREE;
register tree size = TREE_OPERAND (declarator, 1);
+ /* The index is a signed object `sizetype' bits wide. */
+ tree index_type = signed_type (sizetype);
declarator = TREE_OPERAND (declarator, 0);
/* ARM $8.4.3: Since you can't have a pointer to a reference,
you can't have arrays of references. If we allowed them,
- then we'd be saying x[i] is legal for an array x, but
+ then we'd be saying x[i] is valid for an array x, but
then you'd have to ask: what does `*(x + i)' mean? */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
cp_error ("size of array `%D' is negative", dname);
size = integer_one_node;
}
- itype = build_index_type (size_binop (MINUS_EXPR, size,
- integer_one_node));
}
else
{
if (pedantic)
- cp_pedwarn ("ANSI C++ forbids variable-size array `%D'", dname);
- dont_grok_size:
- itype =
- build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
+ {
+ if (dname)
+ cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
+ dname);
+ else
+ cp_pedwarn ("ANSI C++ forbids variable-size array");
+ }
/* Make sure the array size remains visibly nonconstant
- even if it is (eg) a const variable with known value. */
+ even if it is (eg) a const variable with known value. */
size_varies = 1;
- itype = variable_size (itype);
- itype = build_index_type (itype);
}
+
+ dont_grok_size:
+ itype =
+ fold (build_binary_op (MINUS_EXPR,
+ convert (index_type, size),
+ convert (index_type,
+ integer_one_node), 1));
+ if (! TREE_CONSTANT (itype))
+ itype = variable_size (itype);
+ itype = build_index_type (itype);
resume_momentary (yes);
}
type = build_cplus_array_type (type, itype);
if (constp || volatilep)
- /* Should this be c_build_type_variant? -jason */
- type = build_type_variant (type, constp, volatilep);
+ type = cp_build_type_variant (type, constp, volatilep);
ctype = NULL_TREE;
}
case CALL_EXPR:
{
tree arg_types;
+ int funcdecl_p;
+ tree inner_parms = TREE_OPERAND (declarator, 1);
+ tree inner_decl = TREE_OPERAND (declarator, 0);
/* Declaring a function type.
Make sure we have a valid type for the function to return. */
if (pedantic && (constp || volatilep))
pedwarn ("function declared to return const or volatile result");
#else
- /* Merge any constancy or volatility into the target type
- for the pointer. */
+ /* Merge any constancy or volatility into the function return
+ type. */
if (constp || volatilep)
{
- type = build_type_variant (type, constp, volatilep);
+ type = cp_build_type_variant (type, constp, volatilep);
if (IS_AGGR_TYPE (type))
build_pointer_type (type);
constp = 0;
type = integer_type_node;
}
+ if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
+ inner_decl = TREE_OPERAND (inner_decl, 1);
+
+ /* Pick up type qualifiers which should be applied to `this'. */
+ quals = TREE_OPERAND (declarator, 2);
+
+ /* Say it's a definition only for the CALL_EXPR
+ closest to the identifier. */
+ funcdecl_p =
+ inner_decl && (TREE_CODE (inner_decl) == IDENTIFIER_NODE
+ || TREE_CODE (inner_decl) == BIT_NOT_EXPR);
+
if (ctype == NULL_TREE
&& decl_context == FIELD
+ && funcdecl_p
&& (friendp == 0 || dname == current_class_name))
ctype = current_class_type;
- if (ctype && flags == TYPENAME_FLAG)
+ if (ctype && return_type == return_conversion)
TYPE_HAS_CONVERSION (ctype) = 1;
if (ctype && constructor_name (ctype) == dname)
{
may not be static. */
if (staticp == 2)
error ("destructor cannot be static member function");
- if (TYPE_READONLY (type))
- {
- error ("destructors cannot be declared `const'");
- return void_type_node;
- }
- if (TYPE_VOLATILE (type))
+ if (quals)
{
- error ("destructors cannot be declared `volatile'");
+ error ("destructors cannot be declared `const' or `volatile'");
return void_type_node;
}
if (decl_context == FIELD)
}
else /* it's a constructor. */
{
+ if (explicitp == 1)
+ explicitp = 2;
/* ANSI C++ June 5 1992 WP 12.1.2. A constructor may
not be declared const or volatile. A constructor may
not be virtual. A constructor may not be static. */
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
- if (TYPE_READONLY (type))
+ if (quals)
{
- error ("constructors cannot be declared `const'");
+ error ("constructors cannot be declared `const' or `volatile'");
return void_type_node;
}
- if (TYPE_VOLATILE (type))
- {
- error ("constructors cannot be declared `volatile'");
- return void_type_node;
- }
{
- int inlinep, staticp;
- inlinep = RIDBIT_SETP (RID_INLINE, specbits);
- staticp = RIDBIT_SETP (RID_STATIC, specbits);
- RIDBIT_RESET (RID_INLINE, specbits);
- RIDBIT_RESET (RID_STATIC, specbits);
- if (RIDBIT_ANY_SET (specbits))
+ RID_BIT_TYPE tmp_bits;
+ bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE));
+ RIDBIT_RESET (RID_INLINE, tmp_bits);
+ RIDBIT_RESET (RID_STATIC, tmp_bits);
+ if (RIDBIT_ANY_SET (tmp_bits))
error ("return value type specifier for constructor ignored");
- if (inlinep)
- RIDBIT_SET (RID_INLINE, specbits);
- if (staticp)
- RIDBIT_SET (RID_STATIC, specbits);
}
type = TYPE_POINTER_TO (ctype);
if (decl_context == FIELD &&
if (decl_context == FIELD)
staticp = 0;
}
- else if (friendp && virtualp)
+ else if (friendp)
{
- /* Cannot be both friend and virtual. */
- error ("virtual functions cannot be friends");
- RIDBIT_RESET (RID_FRIEND, specbits);
- friendp = 0;
+ if (initialized)
+ error ("can't initialize friend function `%s'", name);
+ if (virtualp)
+ {
+ /* Cannot be both friend and virtual. */
+ error ("virtual functions cannot be friends");
+ RIDBIT_RESET (RID_FRIEND, specbits);
+ friendp = 0;
+ }
+ if (decl_context == NORMAL)
+ error ("friend declaration not in class definition");
+ if (current_function_decl && funcdef_flag)
+ cp_error ("can't define friend function `%s' in a local class definition",
+ name);
}
- if (decl_context == NORMAL && friendp)
- error ("friend declaration not in class definition");
-
- /* Pick up type qualifiers which should be applied to `this'. */
- quals = TREE_OPERAND (declarator, 2);
-
/* Traditionally, declaring return type float means double. */
if (flag_traditional
/* Construct the function type and go to the next
inner layer of declarator. */
- {
- int funcdef_p;
- tree inner_parms = TREE_OPERAND (declarator, 1);
- tree inner_decl = TREE_OPERAND (declarator, 0);
-
- declarator = TREE_OPERAND (declarator, 0);
-
- if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
- inner_decl = TREE_OPERAND (inner_decl, 1);
-
- /* Say it's a definition only for the CALL_EXPR
- closest to the identifier. */
- funcdef_p =
- (inner_decl &&
- (TREE_CODE (inner_decl) == IDENTIFIER_NODE
- || TREE_CODE (inner_decl) == TYPE_EXPR)) ? funcdef_flag : 0;
+ declarator = TREE_OPERAND (declarator, 0);
- /* FIXME: This is where default args should be fully
- processed. */
+ /* FIXME: This is where default args should be fully
+ processed. */
- arg_types = grokparms (inner_parms, funcdef_p);
- }
+ arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0);
if (declarator)
{
continue;
}
+ if (TREE_CODE (type) == OFFSET_TYPE
+ && (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE
+ || TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE))
+ {
+ cp_error ("cannot declare pointer to `%#T' member",
+ TREE_TYPE (type));
+ type = TREE_TYPE (type);
+ }
+
/* Merge any constancy or volatility into the target type
for the pointer. */
signature pointer/reference itself. */
if (! IS_SIGNATURE (type))
{
- type = build_type_variant (type, constp, volatilep);
+ type = cp_build_type_variant (type, constp, volatilep);
if (IS_AGGR_TYPE (type))
build_pointer_type (type);
constp = 0;
{
if (TREE_CODE (declarator) == ADDR_EXPR)
{
- if (CLASSTYPE_METHOD_VEC (type) == NULL_TREE)
- warning ("empty signature `%s' used in signature reference declaration",
- TYPE_NAME_STRING(type));
+ if (CLASSTYPE_METHOD_VEC (type) == NULL_TREE
+ && TYPE_SIZE (type))
+ cp_warning ("empty signature `%T' used in signature reference declaration",
+ type);
#if 0
type = build_signature_reference_type (type,
constp, volatilep);
}
else
{
- if (CLASSTYPE_METHOD_VEC (type) == NULL_TREE)
- warning ("empty signature `%s' used in signature pointer declaration",
- TYPE_NAME_STRING(type));
+ if (CLASSTYPE_METHOD_VEC (type) == NULL_TREE
+ && TYPE_SIZE (type))
+ cp_warning ("empty signature `%T' used in signature pointer declaration",
+ type);
type = build_signature_pointer_type (type,
constp, volatilep);
}
}
}
if (constp > 1)
- warning ("duplicate `const'");
+ pedwarn ("duplicate `const'");
if (volatilep > 1)
- warning ("duplicate `volatile'");
+ pedwarn ("duplicate `volatile'");
+ if (TREE_CODE (declarator) == ADDR_EXPR
+ && (constp || volatilep))
+ {
+ if (constp)
+ pedwarn ("discarding `const' applied to a reference");
+ if (volatilep)
+ pedwarn ("discarding `volatile' applied to a reference");
+ constp = volatilep = 0;
+ }
}
declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
/* don't fall out into global scope. Hides real bug? --eichin */ ;
else if (TREE_COMPLEXITY (declarator) == current_class_depth)
{
- /* I'm not really sure what pushclass calls this popclass
- corresponds to. One is in build_push_scope and that has
- been changed to a push_nested_class call, that's why I
- try to use pop_nested_class here instead.
- -niklas@appli.se */
+ /* This pop_nested_class corresponds to the
+ push_nested_class used to push into class scope for
+ parsing the argument list of a function decl, in
+ qualified_id. */
pop_nested_class (1);
TREE_COMPLEXITY (declarator) = current_class_depth;
}
/* This is the `standard' use of the scoping operator:
basetype :: member . */
- if (TREE_CODE (type) == FUNCTION_TYPE)
+ if (ctype == current_class_type)
+ {
+ /* class A {
+ void A::f ();
+ };
+
+ Is this ill-formed? */
+
+ if (pedantic)
+ cp_pedwarn ("extra qualification `%T::' on member `%s' ignored",
+ ctype, name);
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
{
if (current_class_type == NULL_TREE
- || TYPE_MAIN_VARIANT (ctype) == current_class_type
|| friendp)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
TREE_TYPE (type), TYPE_ARG_TYPES (type));
else
{
- error ("cannot declare member function `%s::%s' within this class",
- TYPE_NAME_STRING (ctype), name);
+ cp_error ("cannot declare member function `%T::%s' within `%T'",
+ ctype, name, current_class_type);
return void_type_node;
}
}
- else if (TYPE_MAIN_VARIANT (ctype) == current_class_type)
- {
- if (extra_warnings)
- warning ("extra qualification `%s' on member `%s' ignored",
- TYPE_NAME_STRING (ctype), name);
- type = build_offset_type (ctype, type);
- }
else if (TYPE_SIZE (ctype) != NULL_TREE
|| (RIDBIT_SETP (RID_TYPEDEF, specbits)))
{
tree t;
/* have to move this code elsewhere in this function.
- this code is used for i.e., typedef int A::M; M *pm; */
+ this code is used for i.e., typedef int A::M; M *pm;
+
+ It is? How? jason 10/2/94 */
if (explicit_int == -1 && decl_context == FIELD
&& funcdef_flag == 0)
/* Don't include destructor with constructors. */
t = DECL_CHAIN (TREE_VALUE (t));
if (t == NULL_TREE)
- error ("class `%s' does not have any constructors", IDENTIFIER_POINTER (sname));
+ cp_error ("`%T' does not have any constructors",
+ ctype);
t = build_tree_list (NULL_TREE, t);
}
t = build_lang_field_decl (FIELD_DECL, build_nt (SCOPE_REF, ctype, t), type);
return t;
}
- if (flags == TYPENAME_FLAG)
- cp_error ("type conversion is not a member of structure `%T'", ctype);
- else
- cp_error
- ("field `%D' is not a member of structure `%T'",
- sname, ctype);
+ cp_error
+ ("field `%D' is not a member of structure `%T'",
+ sname, ctype);
}
if (current_class_type)
{
- if (TYPE_MAIN_VARIANT (ctype) != current_class_type)
- {
- cp_error ("cannot declare member `%T::%s' within `%T'",
- ctype, name, current_class_type);
- return void_type_node;
- }
- else if (extra_warnings)
- cp_warning ("extra qualification `%T' on member `%s' ignored",
- ctype, name);
+ cp_error ("cannot declare member `%T::%s' within `%T'",
+ ctype, name, current_class_type);
+ return void_type_node;
}
type = build_offset_type (ctype, type);
}
declarator = sname;
}
- else if (TREE_CODE (sname) == TYPE_EXPR)
- {
- /* A TYPE_EXPR will change types out from under us.
- So do the TYPE_EXPR now, and make this SCOPE_REF
- inner to the TYPE_EXPR's CALL_EXPR.
-
- This does not work if we don't get a CALL_EXPR back.
- I did not think about error recovery, hence the
- my_friendly_abort. */
-
- /* Get the CALL_EXPR. */
- sname = grokoptypename (sname, 0);
- my_friendly_assert (TREE_CODE (sname) == CALL_EXPR, 157);
- type = TREE_TYPE (TREE_OPERAND (sname, 0));
- /* Scope the CALL_EXPR's name. */
- TREE_OPERAND (declarator, 1) = TREE_OPERAND (sname, 0);
- /* Put the SCOPE_EXPR in the CALL_EXPR's innermost position. */
- TREE_OPERAND (sname, 0) = declarator;
- /* Now work from the CALL_EXPR. */
- declarator = sname;
- continue;
- }
else if (TREE_CODE (sname) == SCOPE_REF)
my_friendly_abort (17);
else
declarator = TREE_OPERAND (declarator, 0);
break;
- case TYPE_EXPR:
- declarator = grokoptypename (declarator, 0);
- if (explicit_int != -1)
- {
- tree stype = TREE_TYPE (TREE_OPERAND (declarator, 0));
- if (comp_target_types (type, stype, 1) == 0)
- cp_error ("`operator %T' declared to return `%T'", stype,
- type);
- else
- cp_pedwarn ("return type specified for `operator %T'", type);
- }
- dname = declarator;
- type = TREE_TYPE (TREE_OPERAND (declarator, 0));
- break;
-
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
}
}
+ if (explicitp == 1)
+ {
+ error ("only constructors can be declared `explicit'");
+ explicitp = 0;
+ }
+
/* Now TYPE has the actual type. */
/* If this is declaring a typedef name, return a TYPE_DECL. */
/* Note that the grammar rejects storage classes
in typenames, fields or parameters. */
if (constp || volatilep)
- type = build_type_variant (type, constp, volatilep);
+ type = cp_build_type_variant (type, constp, volatilep);
/* If the user declares "struct {...} foo" then `foo' will have
an anonymous name. Fill that name in now. Nothing can
declarator, type);
else
set_nested_typename (d, TYPE_NESTED_NAME (c), declarator, type);
+
+ DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
+ DECL_ASSEMBLER_NAME (d)
+ = get_identifier (build_overload_name (type, 1, 1));
}
}
if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
cp_error_at ("typedef name may not be class-qualified", decl);
- TREE_TYPE (decl) = error_mark_node;
+ return NULL_TREE;
}
else if (quals)
{
if (IS_SIGNATURE (type))
error ("`const' or `volatile' specified with signature type");
else
- type = build_type_variant (type, constp, volatilep);
+ type = cp_build_type_variant (type, constp, volatilep);
/* Special case: "friend class foo" looks like a TYPENAME context. */
if (friendp)
{
- /* A friendly class? */
- if (current_class_type)
- make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
- else
- error("trying to make class `%s' a friend of global scope",
- TYPE_NAME_STRING (type));
- type = void_type_node;
+ if (volatilep)
+ {
+ cp_error ("`volatile' specified for friend class declaration");
+ volatilep = 0;
+ }
+ if (inlinep)
+ {
+ cp_error ("`inline' specified for friend class declaration");
+ inlinep = 0;
+ }
+
+ /* Only try to do this stuff if we didn't already give up. */
+ if (type != integer_type_node)
+ {
+ /* A friendly class? */
+ if (current_class_type)
+ make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
+ else
+ error ("trying to make class `%s' a friend of global scope",
+ TYPE_NAME_STRING (type));
+ type = void_type_node;
+ }
}
else if (quals)
{
return type;
}
else if (declarator == NULL_TREE && decl_context != PARM
+ && decl_context != CATCHPARM
&& TREE_CODE (type) != UNION_TYPE
&& ! bitfield)
{
if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM)
{
- if (TREE_CODE (declarator) == IDENTIFIER_NODE)
+ if (! declarator)
+ error ("unnamed variable or field declared void");
+ else if (TREE_CODE (declarator) == IDENTIFIER_NODE)
{
if (IDENTIFIER_OPNAME_P (declarator))
#if 0 /* How could this happen? */
if (decl_context == PARM)
{
- tree parmtype = type;
-
if (ctype)
error ("cannot use `::' in parameter declaration");
/* A parameter declared as an array of T is really a pointer to T.
One declared as a function is really a pointer to a function.
- One declared as a member is really a pointer to member.
-
- Don't be misled by references. */
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
+ One declared as a member is really a pointer to member. */
if (TREE_CODE (type) == ARRAY_TYPE)
{
- if (parmtype == type)
- {
- /* Transfer const-ness of array into that of type
- pointed to. */
- type = build_pointer_type
- (build_type_variant (TREE_TYPE (type), constp, volatilep));
- volatilep = constp = 0;
- }
- else
- type = build_pointer_type (TREE_TYPE (type));
+ /* Transfer const-ness of array into that of type pointed to. */
+ type = build_pointer_type
+ (cp_build_type_variant (TREE_TYPE (type), constp, volatilep));
+ volatilep = constp = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
type = build_pointer_type (type);
else if (TREE_CODE (type) == OFFSET_TYPE)
type = build_pointer_type (type);
-
- if (TREE_CODE (parmtype) == REFERENCE_TYPE)
+ else if (type == void_type_node && declarator)
{
- /* Transfer const-ness of reference into that of type pointed to. */
- type = build_type_variant (build_reference_type (type), constp, volatilep);
- constp = volatilep = 0;
+ error ("declaration of `%s' as void", name);
+ return NULL_TREE;
}
decl = build_decl (PARM_DECL, declarator, type);
(For example, shorts and chars are passed as ints.)
When there is a prototype, this is overridden later. */
- DECL_ARG_TYPE (decl) = type;
- if (TYPE_MAIN_VARIANT (type) == float_type_node)
- DECL_ARG_TYPE (decl) = build_type_variant (double_type_node,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- else if (C_PROMOTING_INTEGER_TYPE_P (type))
- {
- tree argtype;
-
- /* Retain unsignedness if traditional or if not really
- getting wider. */
- if (TREE_UNSIGNED (type)
- && (flag_traditional
- || TYPE_PRECISION (type)
- == TYPE_PRECISION (integer_type_node)))
- argtype = unsigned_type_node;
- else
- argtype = integer_type_node;
- DECL_ARG_TYPE (decl) = build_type_variant (argtype,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- }
+ DECL_ARG_TYPE (decl) = type_promotes_to (type);
}
else if (decl_context == FIELD)
{
}
if (declarator == ansi_opname[(int) NEW_EXPR]
- || declarator == ansi_opname[(int) DELETE_EXPR])
+ || declarator == ansi_opname[(int) VEC_NEW_EXPR]
+ || declarator == ansi_opname[(int) DELETE_EXPR]
+ || declarator == ansi_opname[(int) VEC_DELETE_EXPR])
{
if (virtualp)
{
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
- publicp = (RIDBIT_SETP (RID_EXTERN, specbits)
- || (ctype != NULL_TREE && funcdef_flag >= 0)
- || (friendp
- && ! funcdef_flag
- && RIDBIT_NOTSETP (RID_STATIC, specbits)
- && RIDBIT_NOTSETP (RID_INLINE, specbits)));
+ publicp = (! friendp
+ || RIDBIT_SETP (RID_EXTERN, specbits)
+ || ! (funcdef_flag < 0 || inlinep));
decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals,
- raises, friendp ? -1 : 0, publicp);
- DECL_INLINE (decl) = inlinep;
+ raises, friendp ? -1 : 0, publicp, inlinep);
+ if (decl == NULL_TREE)
+ return NULL_TREE;
+ decl = build_decl_attribute_variant (decl, decl_machine_attr);
+
+ if (explicitp == 2)
+ DECL_NONCONVERTING_P (decl) = 1;
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
+ /* We only get here for friend declarations of
+ members of other classes. */
/* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals,
- raises, friendp ? -1 : 0, 1);
- DECL_INLINE (decl) = inlinep;
- }
- else if (TREE_CODE (type) == RECORD_TYPE
- && CLASSTYPE_DECLARED_EXCEPTION (type))
- {
- /* Handle a class-local exception declaration. */
- decl = build_lang_field_decl (VAR_DECL, declarator, type);
- if (ctype == NULL_TREE)
- ctype = current_class_type;
- finish_exception_decl (TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL
- ? TYPE_IDENTIFIER (ctype) : TYPE_NAME (ctype), decl);
- return void_type_node;
+ raises, friendp ? -1 : 0, 1, 0);
+ if (decl == NULL_TREE)
+ return NULL_TREE;
}
else if (TYPE_SIZE (type) == NULL_TREE && !staticp
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
- error ("field `%s' has incomplete type",
- IDENTIFIER_POINTER (declarator));
+ if (declarator)
+ cp_error ("field `%D' has incomplete type", declarator);
+ else
+ cp_error ("name `%T' has incomplete type", type);
/* If we're instantiating a template, tell them which
instantiation made the field's type be incomplete. */
&& IDENTIFIER_TEMPLATE (DECL_NAME (TYPE_NAME (current_class_type)))
&& declspecs && TREE_VALUE (declspecs)
&& TREE_TYPE (TREE_VALUE (declspecs)) == type)
- error (" in instantiation of template `%s'",
- TYPE_NAME_STRING (current_class_type));
-
+ cp_error (" in instantiation of template `%T'",
+ current_class_type);
+
type = error_mark_node;
decl = NULL_TREE;
}
if (decl == NULL_TREE)
{
- /* ANSI C++ June 5 1992 WP 9.2.2 and 9.4.2. A member-declarator
- cannot have an initializer, and a static member declaration must
- be defined elsewhere. */
if (initialized)
{
+ /* Motion 10 at San Diego: If a static const integral data
+ member is initialized with an integral constant
+ expression, the initializer may appear either in the
+ declaration (within the class), or in the definition,
+ but not both. If it appears in the class, the member is
+ a member constant. The file-scope definition is always
+ required. */
if (staticp)
- error ("static member `%s' must be defined separately from its declaration",
- IDENTIFIER_POINTER (declarator));
+ {
+ if (pedantic)
+ {
+ if (! constp)
+ cp_pedwarn ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
+ declarator);
+
+ else if (! INTEGRAL_TYPE_P (type))
+ cp_pedwarn ("ANSI C++ forbids member constant `%D' of non-integral type `%T'", declarator, type);
+ }
+ }
+
/* Note that initialization of const members is prohibited
by the draft ANSI standard, though it appears to be in
common practice. 12.6.2: The argument list is used to
initialize the named nonstatic member.... This (or an
- aggregate) is the only way to initialize nonstatic const
- and reference members. */
- else
- pedwarn ("ANSI C++ forbids initialization of %s `%s'",
- constp ? "const member" : "member",
- IDENTIFIER_POINTER (declarator));
+ initializer list) is the only way to initialize
+ nonstatic const and reference members. */
+ else if (pedantic || ! constp)
+ cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
+ constp ? "const member" : "member", declarator);
}
if (staticp || (constp && initialized))
This VAR_DECL is built by build_lang_field_decl.
All other VAR_DECLs are built by build_decl. */
decl = build_lang_field_decl (VAR_DECL, declarator, type);
- if (staticp || TREE_CODE (type) == ARRAY_TYPE)
- TREE_STATIC (decl) = 1;
- /* In class context, static means public access. */
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = !initialized;
+ TREE_STATIC (decl) = 1;
+ /* In class context, 'static' means public access. */
+ TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = !!staticp;
}
else
{
}
else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
- int was_overloaded = 0;
tree original_name = declarator;
int publicp = 0;
if (! declarator)
return NULL_TREE;
- if (RIDBIT_SETP (RID_AUTO, specbits)
- || RIDBIT_SETP (RID_REGISTER, specbits))
- error ("invalid storage class for function `%s'", name);
+ if (RIDBIT_SETP (RID_AUTO, specbits))
+ error ("storage class `auto' invalid for function `%s'", name);
+ else if (RIDBIT_SETP (RID_REGISTER, specbits))
+ error ("storage class `register' invalid for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
if (current_binding_level != global_binding_level
- && (RIDBIT_SETP (RID_STATIC, specbits) || RIDBIT_SETP (RID_INLINE, specbits))
+ && ! processing_template_decl
+ && (RIDBIT_SETP (RID_STATIC, specbits)
+ || RIDBIT_SETP (RID_INLINE, specbits))
&& pedantic)
- pedwarn ("invalid storage class for function `%s'", name);
-
+ {
+ if (RIDBIT_SETP (RID_STATIC, specbits))
+ pedwarn ("storage class `static' invalid for function `%s' declared out of global scope", name);
+ else
+ pedwarn ("storage class `inline' invalid for function `%s' declared out of global scope", name);
+ }
+
if (ctype == NULL_TREE)
{
if (virtualp)
&& IDENTIFIER_POINTER (original_name)[0] == '_'
&& IDENTIFIER_POINTER (original_name)[1] == '_'
&& strncmp (IDENTIFIER_POINTER (original_name)+2, "builtin_", 8) == 0))
- {
- /* Plain overloading: will not be grok'd by grokclassfn. */
- declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
- was_overloaded = 1;
- }
+ /* Plain overloading: will not be grok'd by grokclassfn. */
+ declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
TREE_TYPE (type), TYPE_ARG_TYPES (type));
- /* Record presence of `static'. In C++, `inline' is like `static'.
- Methods of classes should be public, unless we're dropping them
- into some other file, so we don't clear TREE_PUBLIC for them. */
- publicp
- = ((ctype
- && CLASSTYPE_INTERFACE_KNOWN (ctype)
- && ! CLASSTYPE_INTERFACE_ONLY (ctype))
- || !(RIDBIT_SETP (RID_STATIC, specbits)
- || RIDBIT_SETP (RID_INLINE, specbits)));
+ /* Record presence of `static'. In C++, `inline' implies `static'. */
+ publicp = (ctype != NULL_TREE
+ || (!RIDBIT_SETP (RID_STATIC, specbits)
+ && !RIDBIT_SETP (RID_INLINE, specbits)));
decl = grokfndecl (ctype, type, original_name,
virtualp, flags, quals,
raises,
processing_template_decl ? 0 : friendp ? 2 : 1,
- publicp);
+ publicp, inlinep);
+ if (decl == NULL_TREE)
+ return NULL_TREE;
if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c)
- DECL_ASSEMBLER_NAME (decl) = declarator;
+ DECL_ASSEMBLER_NAME (decl) = current_namespace_id (declarator);
if (staticp == 1)
{
declaring main to be static. */
if (TREE_CODE (type) == METHOD_TYPE)
{
- cp_error_at ("cannot declare member function `%D' to have static linkage", decl);
- illegal_static = 1;
- }
- else if (! was_overloaded
- && ! ctype
- && IDENTIFIER_LENGTH (original_name) == 4
- && IDENTIFIER_POINTER (original_name)[0] == 'm'
- && ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
- {
- error ("cannot declare function `main' to have static linkage");
+ cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl);
illegal_static = 1;
}
else if (current_function_decl)
RIDBIT_RESET (RID_STATIC, specbits);
}
}
+ }
+ else
+ {
+ /* It's a variable. */
- /* Record presence of `inline', if it is reasonable. */
- if (inlinep)
+ if (decl_context == CATCHPARM)
{
- tree last = tree_last (TYPE_ARG_TYPES (type));
-
- if (! was_overloaded
- && ! ctype
- && ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
- error ("cannot inline function `main'");
- else if (last && last != void_list_node)
- cp_warning ("cannot inline function `%D' which takes `...'", original_name);
- else
- /* Assume that otherwise the function can be inlined. */
- DECL_INLINE (decl) = 1;
+ if (ctype)
+ {
+ ctype = NULL_TREE;
+ error ("cannot use `::' in parameter declaration");
+ }
- if (RIDBIT_SETP (RID_EXTERN, specbits))
+ /* A parameter declared as an array of T is really a pointer to T.
+ One declared as a function is really a pointer to a function.
+ One declared as a member is really a pointer to member. */
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
{
- current_extern_inline = 1;
- if (flag_ansi || pedantic || flag_pedantic_errors)
- pedwarn ("ANSI C++ does not permit `extern inline'");
+ /* Transfer const-ness of array into that of type pointed to. */
+ type = build_pointer_type
+ (cp_build_type_variant (TREE_TYPE (type), constp, volatilep));
+ volatilep = constp = 0;
}
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ type = build_pointer_type (type);
+ else if (TREE_CODE (type) == OFFSET_TYPE)
+ type = build_pointer_type (type);
}
- if (was_overloaded)
- DECL_OVERLOADED (decl) = 1;
- }
- else
- {
- /* It's a variable. */
/* An uninitialized decl with `extern' is a reference. */
decl = grokvardecl (type, declarator, specbits, initialized);
if (ctype)
{
+ DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
cp_error ("static member `%D' re-declared as static",
staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits);
}
+ if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl))
+ {
+ cp_error ("static member `%D' declared `register'", decl);
+ RIDBIT_RESET (RID_REGISTER, specbits);
+ }
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
cp_error ("cannot explicitly declare member `%#D' to have extern linkage",
if (RIDBIT_SETP (RID_REGISTER, specbits))
DECL_REGISTER (decl) = 1;
+ if (RIDBIT_SETP (RID_EXTERN, specbits))
+ DECL_THIS_EXTERN (decl) = 1;
+
+ if (RIDBIT_SETP (RID_STATIC, specbits))
+ DECL_THIS_STATIC (decl) = 1;
+
/* Record constancy and volatility. */
if (constp)
any_init++;
if (TREE_CODE (init) == SAVE_EXPR)
PARM_DECL_EXPR (init) = 1;
- else if (TREE_CODE (init) == VAR_DECL)
+ else if (TREE_CODE (init) == VAR_DECL
+ || TREE_CODE (init) == PARM_DECL)
{
if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init)))
{
}
else
init = require_instantiated_type (type, init, integer_zero_node);
- }
+ }
+#if 0 /* This is too early to check; trailing parms might be merged in by
+ duplicate_decls. */
else if (any_init)
{
error ("all trailing parameters must have default arguments");
any_error = 1;
}
+#endif
}
else
init = NULL_TREE;
`grok_op_properties' takes notice of the various forms of
operator= which are defined, as well as what sorts of type conversion
may apply. Both functions take a FUNCTION_DECL as an argument. */
-void
+int
grok_ctor_properties (ctype, decl)
tree ctype, decl;
{
{
if (TREE_CHAIN (parmtypes) != NULL_TREE
&& TREE_CHAIN (parmtypes) == void_list_node)
- cp_error ("invalid constructor; you probably meant `%T (%T&)'",
- ctype, ctype);
- SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
- TYPE_GETS_INIT_AGGR (ctype) = 1;
+ {
+ cp_error ("invalid constructor; you probably meant `%T (%T&)'",
+ ctype, ctype);
+ SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
+
+ return 0;
+ }
+ else
+ TYPE_GETS_INIT_AGGR (ctype) = 1;
}
else if (TREE_CODE (parmtype) == VOID_TYPE
|| TREE_PURPOSE (parmtypes) != NULL_TREE)
TYPE_HAS_DEFAULT_CONSTRUCTOR (ctype) = 1;
+
+ return 1;
}
/* An operator with this name can be either unary or binary. */
-int ambi_op_p (name)
+static int
+ambi_op_p (name)
tree name;
{
return (name == ansi_opname [(int) INDIRECT_REF]
}
/* An operator with this name can only be unary. */
-int unary_op_p (name)
+static int
+unary_op_p (name)
tree name;
{
return (name == ansi_opname [(int) TRUTH_NOT_EXPR]
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
tree name = DECL_NAME (decl);
- tree t;
- if (! friendp)
- for (t = current_class_type; t; t = TYPE_NEXT_VARIANT (t))
- {
- if (name == ansi_opname[(int) MODIFY_EXPR])
- TYPE_HAS_ASSIGNMENT (t) = 1;
- else if (name == ansi_opname[(int) CALL_EXPR])
- TYPE_OVERLOADS_CALL_EXPR (t) = 1;
- else if (name == ansi_opname[(int) ARRAY_REF])
- TYPE_OVERLOADS_ARRAY_REF (t) = 1;
- else if (name == ansi_opname[(int) COMPONENT_REF]
- || name == ansi_opname[(int) MEMBER_REF])
- TYPE_OVERLOADS_ARROW (t) = 1;
- else if (name == ansi_opname[(int) NEW_EXPR])
- {
- if (TREE_CHAIN (argtypes) == void_list_node)
- TREE_GETS_NEW (t) = 1;
- else
- TREE_GETS_PLACED_NEW (t) = 1;
- }
- else if (name == ansi_opname[(int) DELETE_EXPR])
- TREE_GETS_DELETE (t) = 1;
-#if 0
- else if (name == ansi_opname[(int) VEC_NEW_EXPR])
- TREE_GETS_NEW (t) = 1;
- else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
- TREE_GETS_DELETE (t) = 1;
-#endif
- }
+ if (current_class_type == NULL_TREE)
+ friendp = 1;
- if (name == ansi_opname[(int) NEW_EXPR])
+ if (! friendp)
+ {
+ if (name == ansi_opname[(int) MODIFY_EXPR])
+ TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
+ else if (name == ansi_opname[(int) CALL_EXPR])
+ TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
+ else if (name == ansi_opname[(int) ARRAY_REF])
+ TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
+ else if (name == ansi_opname[(int) COMPONENT_REF]
+ || name == ansi_opname[(int) MEMBER_REF])
+ TYPE_OVERLOADS_ARROW (current_class_type) = 1;
+ else if (name == ansi_opname[(int) NEW_EXPR])
+ TYPE_GETS_NEW (current_class_type) |= 1;
+ else if (name == ansi_opname[(int) DELETE_EXPR])
+ TYPE_GETS_DELETE (current_class_type) |= 1;
+ else if (name == ansi_opname[(int) VEC_NEW_EXPR])
+ TYPE_GETS_NEW (current_class_type) |= 2;
+ else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
+ TYPE_GETS_DELETE (current_class_type) |= 2;
+ }
+
+ if (name == ansi_opname[(int) NEW_EXPR]
+ || name == ansi_opname[(int) VEC_NEW_EXPR])
{
-#if 0
/* When the compiler encounters the definition of A::operator new, it
doesn't look at the class declaration to find out if it's static. */
- my_friendly_assert (!methodp, 355);
-#endif
+ if (methodp)
+ revert_static_member_fn (&decl, NULL, NULL);
/* Take care of function decl if we had syntax errors. */
if (argtypes == NULL_TREE)
hash_tree_chain (integer_type_node,
void_list_node));
else
- decl = coerce_new_type (TREE_TYPE (decl));
- }
-#if 0
- else if (name == ansi_opname[(int) VEC_NEW_EXPR])
- {
+ TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
}
-#endif
- else if (name == ansi_opname[(int) DELETE_EXPR])
+ else if (name == ansi_opname[(int) DELETE_EXPR]
+ || name == ansi_opname[(int) VEC_DELETE_EXPR])
{
-#if 0
- my_friendly_assert (!methodp, 355);
-#endif
+ if (methodp)
+ revert_static_member_fn (&decl, NULL, NULL);
if (argtypes == NULL_TREE)
TREE_TYPE (decl) =
hash_tree_chain (ptr_type_node,
void_list_node));
else
- decl = coerce_delete_type (TREE_TYPE (decl));
- }
-#if 0
- else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
- {
+ {
+ TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
+
+ if (! friendp && name == ansi_opname[(int) VEC_DELETE_EXPR]
+ && (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
+ != void_list_node))
+ TYPE_VEC_DELETE_TAKES_SIZE (current_class_type) = 1;
+ }
}
-#endif
else
{
/* An operator function must either be a non-static member function
or have at least one parameter of a class, a reference to a class,
an enumeration, or a reference to an enumeration. 13.4.0.6 */
- if (! methodp)
+ if (! methodp || DECL_STATIC_FUNCTION_P (decl))
{
if (OPERATOR_TYPENAME_P (name)
|| name == ansi_opname[(int) CALL_EXPR]
{
tree p = argtypes;
+ if (DECL_STATIC_FUNCTION_P (decl))
+ cp_error ("`%D' must be either a non-static member function or a non-member function", decl);
+
if (p)
for (; TREE_VALUE (p) != void_type_node ; p = TREE_CHAIN (p))
{
|| name == ansi_opname[(int) METHOD_CALL_EXPR])
return; /* no restrictions on args */
+ if (IDENTIFIER_TYPENAME_P (name))
+ {
+ tree t = TREE_TYPE (name);
+ if (TREE_CODE (t) == VOID_TYPE)
+ pedwarn ("void is not a valid type conversion operator");
+ else if (! friendp)
+ {
+ int ref = (TREE_CODE (t) == REFERENCE_TYPE);
+ char *what = 0;
+ if (ref)
+ t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
+
+ if (t == current_class_type)
+ what = "the same type";
+ else if (IS_AGGR_TYPE (t)
+ && DERIVED_FROM_P (t, current_class_type))
+ what = "a base class";
+
+ if (what)
+ warning ("conversion to %s%s will never use a type conversion operator",
+ ref ? "a reference to " : "", what);
+ }
+ }
+
if (name == ansi_opname[(int) MODIFY_EXPR])
{
tree parmtype;
}
parmtype = TREE_VALUE (TREE_CHAIN (argtypes));
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype))
- == current_class_type)
+ if (copy_assignment_arg_p (parmtype, virtualp)
+ && ! friendp)
{
TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
- if (TYPE_READONLY (TREE_TYPE (parmtype)))
+ if (TREE_CODE (parmtype) != REFERENCE_TYPE
+ || TYPE_READONLY (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
+#if 0 /* Too soon; done in grok_function_init */
+ if (DECL_ABSTRACT_VIRTUAL_P (decl))
+ TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1;
+#endif
}
}
else if (name == ansi_opname[(int) COND_EXPR])
the current frame for the name (since C++ allows new names in any
scope.) */
-/* avoid rewriting all callers of xref_tag */
-static int xref_next_defn = 0;
-
-tree
-xref_defn_tag (code_type_node, name, binfo)
- tree code_type_node;
- tree name, binfo;
-{
- tree rv, ncp;
- xref_next_defn = 1;
-
- if (class_binding_level)
- {
- tree n1;
- char *buf;
- /* we need to build a new IDENTIFIER_NODE for name which nukes
- * the pieces... */
-/*
- n1 = IDENTIFIER_LOCAL_VALUE (current_class_name);
- if (n1)
- n1 = DECL_NAME (n1);
- else
- n1 = current_class_name;
-*/
- n1 = TYPE_NAME(current_class_type);
- if (n1)
- n1 = DECL_NESTED_TYPENAME(n1);
- else
- n1 = current_class_name;
-
- buf = (char *) alloca (4 + IDENTIFIER_LENGTH (n1)
- + IDENTIFIER_LENGTH (name));
-
- sprintf (buf, "%s::%s", IDENTIFIER_POINTER (n1),
- IDENTIFIER_POINTER (name));
- ncp = get_identifier (buf);
-#ifdef SPEW_DEBUG
- if (spew_debug)
- printf("*** %s ***\n", IDENTIFIER_POINTER (ncp));
-#endif
-#if 0
- IDENTIFIER_LOCAL_VALUE (name) =
- build_lang_decl (TYPE_DECL, ncp, NULL_TREE);
-#endif
- rv = xref_tag (code_type_node, name, binfo, 0);
- if (! ANON_AGGRNAME_P (name))
- {
- register tree type_decl = build_lang_decl (TYPE_DECL, ncp, rv);
-#ifdef DWARF_DEBUGGING_INFO
- /* Mark the TYPE_DECL node created just above as a gratuitous one
- so that dwarfout.c will know not to generate a TAG_typedef DIE
- for it. */
- if (write_symbols == DWARF_DEBUG)
- DECL_IGNORED_P (type_decl) = 1;
-#endif /* DWARF_DEBUGGING_INFO */
- pushdecl_top_level (type_decl);
- }
- }
- else
- {
- rv = xref_tag (code_type_node, name, binfo, 0);
- }
- xref_next_defn = 0;
- return rv;
-}
-
tree
xref_tag (code_type_node, name, binfo, globalize)
tree code_type_node;
enum tag_types tag_code;
enum tree_code code;
int temp = 0;
- int i, len;
+ int i;
register tree ref, t;
struct binding_level *b = inner_binding_level;
{
case record_type:
case class_type:
- case exception_type:
case signature_type:
code = RECORD_TYPE;
- len = list_length (binfo);
break;
case union_type:
code = UNION_TYPE;
- if (binfo)
- {
- cp_error ("derived union `%T' invalid", name);
- binfo = NULL_TREE;
- }
- len = 0;
break;
case enum_type:
code = ENUMERAL_TYPE;
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
- if (t = IDENTIFIER_TYPE_VALUE(name))
- {
- if (TREE_CODE(t) != code) t = NULL_TREE;
- }
- if (xref_next_defn)
+ t = IDENTIFIER_TYPE_VALUE (name);
+ if (t && TREE_CODE (t) != code)
+ t = NULL_TREE;
+
+ if (! globalize)
{
/* If we know we are defining this tag, only look it up in this scope
* and don't try to find it as a type. */
- xref_next_defn = 0;
- if (t && TYPE_CONTEXT(t) && strstr(IDENTIFIER_POINTER(name), "::"))
+ if (t && TYPE_CONTEXT(t) && TREE_MANGLED (name))
ref = t;
else
ref = lookup_tag (code, name, b, 1);
if (flag_cadillac)
cadillac_start_enum (ref);
}
- else if (tag_code == exception_type)
- {
- ref = make_lang_type (code);
- /* Enable us to recognize when an exception type is created in
- class context. To do nested classes correctly, this should
- probably be cleared out when we leave this class's scope. */
- CLASSTYPE_DECLARED_EXCEPTION (ref) = 1;
- pushtag (name, ref, globalize);
- if (flag_cadillac)
- cadillac_start_struct (ref);
- }
else
{
- extern tree pending_vtables;
struct binding_level *old_b = class_binding_level;
- int needs_writing;
ref = make_lang_type (code);
- /* A signature type will contain the fields of the signature
- table. Therefore, it's not only an interface. */
if (tag_code == signature_type)
{
SET_SIGNATURE (ref);
+ /* Since a signature type will be turned into the type
+ of signature tables, it's not only an interface. */
CLASSTYPE_INTERFACE_ONLY (ref) = 0;
- CLASSTYPE_INTERFACE_UNKNOWN (ref) = 0;
- }
-
- /* Record how to set the access of this class's
- virtual functions. If write_virtuals == 2 or 3, then
- inline virtuals are ``extern inline''. */
- switch (write_virtuals)
- {
- case 0:
- case 1:
- needs_writing = 1;
- break;
- case 2:
- needs_writing = !! value_member (name, pending_vtables);
- break;
- case 3:
- needs_writing = ! CLASSTYPE_INTERFACE_ONLY (ref)
- && CLASSTYPE_INTERFACE_KNOWN (ref);
- break;
- default:
- needs_writing = 0;
+ SET_CLASSTYPE_INTERFACE_KNOWN (ref);
+ /* A signature doesn't have a vtable. */
+ CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = 0;
}
- /* Signatures don't have a vtable. As long as we don't have default
- implementations, they behave as if `write_virtuals' were 3. */
- if (tag_code == signature_type)
- CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = 0;
- else
- CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = needs_writing;
-
#ifdef NONNESTED_CLASSES
/* Class types don't nest the way enums do. */
class_binding_level = (struct binding_level *)0;
}
else
{
- if (IS_AGGR_TYPE_CODE (code))
- {
- if (IS_AGGR_TYPE (ref)
- && ((tag_code == exception_type)
- != (CLASSTYPE_DECLARED_EXCEPTION (ref) == 1)))
- {
- cp_error ("type `%T' is both exception and aggregate type", ref);
- CLASSTYPE_DECLARED_EXCEPTION (ref) = (tag_code == exception_type);
- }
- }
-
/* If it no longer looks like a nested type, make sure it's
in global scope. */
if (b == global_binding_level && !class_binding_level
&& IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref);
+#if 0
if (binfo)
{
tree tt1 = binfo;
build them on the permanent obstack. */
end_temporary_allocation ();
}
+#endif
}
if (binfo)
+ xref_basetypes (code_type_node, name, ref, binfo);
+
+ just_return:
+
+ /* Until the type is defined, tentatively accept whatever
+ structure tag the user hands us. */
+ if (TYPE_SIZE (ref) == NULL_TREE
+ && ref != current_class_type
+ /* Have to check this, in case we have contradictory tag info. */
+ && IS_AGGR_TYPE_CODE (TREE_CODE (ref)))
{
- /* In the declaration `A : X, Y, ... Z' we mark all the types
- (A, X, Y, ..., Z) so we can check for duplicates. */
- tree binfos;
-
- SET_CLASSTYPE_MARKED (ref);
- BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
-
- for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
- {
- /* The base of a derived struct is public by default. */
- int via_public
- = (TREE_PURPOSE (binfo) == (tree)access_public
- || TREE_PURPOSE (binfo) == (tree)access_public_virtual
- || (tag_code != class_type
- && (TREE_PURPOSE (binfo) == (tree)access_default
- || TREE_PURPOSE (binfo) == (tree)access_default_virtual)));
- int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected;
- int via_virtual
- = (TREE_PURPOSE (binfo) == (tree)access_private_virtual
- || TREE_PURPOSE (binfo) == (tree)access_public_virtual
- || TREE_PURPOSE (binfo) == (tree)access_default_virtual);
- tree basetype = TREE_TYPE (TREE_VALUE (binfo));
- tree base_binfo;
-
- GNU_xref_hier (IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TREE_VALUE (binfo)),
- via_public, via_virtual, 0);
-
- if (basetype && TREE_CODE (basetype) == TYPE_DECL)
- basetype = TREE_TYPE (basetype);
- if (!basetype || TREE_CODE (basetype) != RECORD_TYPE)
- {
- error ("base type `%s' fails to be a struct or class type",
- IDENTIFIER_POINTER (TREE_VALUE (binfo)));
- continue;
- }
+ if (tag_code == class_type)
+ CLASSTYPE_DECLARED_CLASS (ref) = 1;
+ else if (tag_code == record_type || tag_code == signature_type)
+ CLASSTYPE_DECLARED_CLASS (ref) = 0;
+ }
+
+ pop_obstacks ();
+
+ return ref;
+}
+
+void
+xref_basetypes (code_type_node, name, ref, binfo)
+ tree code_type_node;
+ tree name, ref;
+ tree binfo;
+{
+ /* In the declaration `A : X, Y, ... Z' we mark all the types
+ (A, X, Y, ..., Z) so we can check for duplicates. */
+ tree binfos;
+ int i, len;
+ enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
+
+ if (tag_code == union_type)
+ {
+ cp_error ("derived union `%T' invalid", ref);
+ return;
+ }
+
+ len = list_length (binfo);
+ push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
+
+ SET_CLASSTYPE_MARKED (ref);
+ BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
+
+ for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
+ {
+ /* The base of a derived struct is public by default. */
+ int via_public
+ = (TREE_PURPOSE (binfo) == (tree)access_public
+ || TREE_PURPOSE (binfo) == (tree)access_public_virtual
+ || (tag_code != class_type
+ && (TREE_PURPOSE (binfo) == (tree)access_default
+ || TREE_PURPOSE (binfo) == (tree)access_default_virtual)));
+ int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected;
+ int via_virtual
+ = (TREE_PURPOSE (binfo) == (tree)access_private_virtual
+ || TREE_PURPOSE (binfo) == (tree)access_public_virtual
+ || TREE_PURPOSE (binfo) == (tree)access_default_virtual);
+ tree basetype = TREE_TYPE (TREE_VALUE (binfo));
+ tree base_binfo;
+
+ GNU_xref_hier (IDENTIFIER_POINTER (name),
+ IDENTIFIER_POINTER (TREE_VALUE (binfo)),
+ via_public, via_virtual, 0);
+
+ if (basetype && TREE_CODE (basetype) == TYPE_DECL)
+ basetype = TREE_TYPE (basetype);
+ if (!basetype || TREE_CODE (basetype) != RECORD_TYPE)
+ {
+ cp_error ("base type `%T' fails to be a struct or class type",
+ TREE_VALUE (binfo));
+ continue;
+ }
#if 1
- /* This code replaces similar code in layout_basetypes. */
- else if (TYPE_SIZE (basetype) == NULL_TREE)
+ /* This code replaces similar code in layout_basetypes. */
+ else if (TYPE_INCOMPLETE (basetype))
+ {
+ cp_error ("base class `%T' has incomplete type", basetype);
+ continue;
+ }
+#endif
+ else
+ {
+ if (CLASSTYPE_MARKED (basetype))
{
- cp_error ("base class `%T' has incomplete type", basetype);
+ if (basetype == ref)
+ cp_error ("recursive type `%T' undefined", basetype);
+ else
+ cp_error ("duplicate base type `%T' invalid", basetype);
continue;
}
-#endif
- else
- {
- if (CLASSTYPE_MARKED (basetype))
- {
- if (basetype == ref)
- cp_error ("recursive type `%T' undefined", basetype);
- else
- cp_error ("duplicate base type `%T' invalid", basetype);
- continue;
- }
- /* Note that the BINFO records which describe individual
- inheritances are *not* shared in the lattice! They
- cannot be shared because a given baseclass may be
- inherited with different `accessibility' by different
- derived classes. (Each BINFO record describing an
- individual inheritance contains flags which say what
- the `accessibility' of that particular inheritance is.) */
+ /* Note that the BINFO records which describe individual
+ inheritances are *not* shared in the lattice! They
+ cannot be shared because a given baseclass may be
+ inherited with different `accessibility' by different
+ derived classes. (Each BINFO record describing an
+ individual inheritance contains flags which say what
+ the `accessibility' of that particular inheritance is.) */
- base_binfo = make_binfo (integer_zero_node, basetype,
- TYPE_BINFO_VTABLE (basetype),
- TYPE_BINFO_VIRTUALS (basetype), 0);
+ base_binfo = make_binfo (integer_zero_node, basetype,
+ TYPE_BINFO_VTABLE (basetype),
+ TYPE_BINFO_VIRTUALS (basetype), NULL_TREE);
- TREE_VEC_ELT (binfos, i) = base_binfo;
- TREE_VIA_PUBLIC (base_binfo) = via_public;
- TREE_VIA_PROTECTED (base_binfo) = via_protected;
- TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
+ TREE_VEC_ELT (binfos, i) = base_binfo;
+ TREE_VIA_PUBLIC (base_binfo) = via_public;
+ TREE_VIA_PROTECTED (base_binfo) = via_protected;
+ TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
+ BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
- SET_CLASSTYPE_MARKED (basetype);
+ SET_CLASSTYPE_MARKED (basetype);
#if 0
-/* XYZZY TEST VIRTUAL BASECLASSES */
-if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
- && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
- && via_virtual == 0)
- {
- warning ("making type `%s' a virtual baseclass",
- TYPE_NAME_STRING (basetype));
- via_virtual = 1;
- }
+ /* XYZZY TEST VIRTUAL BASECLASSES */
+ if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
+ && via_virtual == 0)
+ {
+ warning ("making type `%s' a virtual baseclass",
+ TYPE_NAME_STRING (basetype));
+ via_virtual = 1;
+ }
#endif
- /* We are free to modify these bits because they are meaningless
- at top level, and BASETYPE is a top-level type. */
- if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
- TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
- }
-
- TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
- TREE_GETS_NEW (ref) |= TREE_GETS_NEW (basetype);
- TREE_GETS_PLACED_NEW (ref) |= TREE_GETS_PLACED_NEW (basetype);
- TREE_GETS_DELETE (ref) |= TREE_GETS_DELETE (basetype);
- CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
- i += 1;
+ /* We are free to modify these bits because they are meaningless
+ at top level, and BASETYPE is a top-level type. */
+ if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+ {
+ TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
+ TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
}
- }
- if (i)
- TREE_VEC_LENGTH (binfos) = i;
- else
- BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
-
- if (i > 1)
- TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
- else if (i == 1)
- TYPE_USES_MULTIPLE_INHERITANCE (ref)
- = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
- if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
- TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
- /* Unmark all the types. */
- while (--i >= 0)
- CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
- CLEAR_CLASSTYPE_MARKED (ref);
+ TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
+ TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
+ TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+ CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
+ i += 1;
+ }
}
+ if (i)
+ TREE_VEC_LENGTH (binfos) = i;
+ else
+ BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
- just_return:
+ if (i > 1)
+ TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
+ else if (i == 1)
+ TYPE_USES_MULTIPLE_INHERITANCE (ref)
+ = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
+ if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
+ TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
- /* Until the type is defined, tentatively accept whatever
- structure tag the user hands us. */
- if (TYPE_SIZE (ref) == NULL_TREE
- && ref != current_class_type
- /* Have to check this, in case we have contradictory tag info. */
- && IS_AGGR_TYPE_CODE (TREE_CODE (ref)))
- {
- if (tag_code == class_type)
- CLASSTYPE_DECLARED_CLASS (ref) = 1;
- else if (tag_code == record_type || tag_code == signature_type)
- CLASSTYPE_DECLARED_CLASS (ref) = 0;
- }
+ /* Unmark all the types. */
+ while (--i >= 0)
+ CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
+ CLEAR_CLASSTYPE_MARKED (ref);
pop_obstacks ();
-
- return ref;
}
+
\f
static tree current_local_enum = NULL_TREE;
TREE_ADDRESSABLE (b->tags) = 1;
current_local_enum = NULL_TREE;
+#if 0 /* This stuff gets cleared in finish_enum anyway. */
if (TYPE_VALUES (enumtype) != NULL_TREE)
/* Completely replace its old definition.
The old enumerators remain defined, however. */
TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
TYPE_SIZE (enumtype) = NULL_TREE;
- fixup_unsigned_type (enumtype);
+ fixup_signed_type (enumtype);
+#endif
/* We copy this value because enumerated type constants
are really of the type of the enumerator, not integer_type_node. */
enum_next_value = copy_node (integer_zero_node);
+ enum_overflow = 0;
GNU_xref_decl (current_function_decl, enumtype);
return enumtype;
finish_enum (enumtype, values)
register tree enumtype, values;
{
- register tree pair, tem;
- register HOST_WIDE_INT maxvalue = 0;
- register HOST_WIDE_INT minvalue = 0;
- register HOST_WIDE_INT i;
-
- TYPE_VALUES (enumtype) = values;
-
+ register tree minnode, maxnode;
/* Calculate the maximum value of any enumerator in this type. */
if (values)
{
+ register tree pair;
+ register tree value = DECL_INITIAL (TREE_VALUE (values));
+
/* Speed up the main loop by performing some precalculations */
-
- HOST_WIDE_INT value = TREE_INT_CST_LOW (TREE_VALUE (values));
TREE_TYPE (TREE_VALUE (values)) = enumtype;
- minvalue = maxvalue = value;
+ TREE_TYPE (value) = enumtype;
+ TREE_VALUE (values) = value;
+ minnode = maxnode = value;
for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
{
- value = TREE_INT_CST_LOW (TREE_VALUE (pair));
- if (value > maxvalue)
- maxvalue = value;
- else if (value < minvalue)
- minvalue = value;
+ value = DECL_INITIAL (TREE_VALUE (pair));
TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+ TREE_TYPE (value) = enumtype;
+ TREE_VALUE (pair) = value;
+ if (tree_int_cst_lt (maxnode, value))
+ maxnode = value;
+ else if (tree_int_cst_lt (value, minnode))
+ minnode = value;
}
}
+ else
+ maxnode = minnode = integer_zero_node;
- if (flag_short_enums)
- {
- /* Determine the precision this type needs, lay it out, and define it. */
+ TYPE_VALUES (enumtype) = values;
- for (i = maxvalue; i; i >>= 1)
- TYPE_PRECISION (enumtype)++;
+ {
+ int unsignedp = tree_int_cst_sgn (minnode) >= 0;
+ int lowprec = min_precision (minnode, unsignedp);
+ int highprec = min_precision (maxnode, unsignedp);
+ int precision = MAX (lowprec, highprec);
- if (!TYPE_PRECISION (enumtype))
- TYPE_PRECISION (enumtype) = 1;
+ TYPE_SIZE (enumtype) = NULL_TREE;
- /* Cancel the laying out previously done for the enum type,
- so that fixup_unsigned_type will do it over. */
- TYPE_SIZE (enumtype) = NULL_TREE;
+ /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
+ TYPE_PRECISION (enumtype) = precision;
+ if (unsignedp)
fixup_unsigned_type (enumtype);
- }
+ else
+ fixup_signed_type (enumtype);
+
+ if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node))
+ /* Use the width of the narrowest normal C type which is wide enough. */
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
+ (precision, 1));
+ else
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
- TREE_INT_CST_LOW (TYPE_MAX_VALUE (enumtype)) = maxvalue;
+ TYPE_SIZE (enumtype) = 0;
+ layout_type (enumtype);
+ }
- /* An enum can have some negative values; then it is signed. */
- if (minvalue < 0)
- {
- TREE_INT_CST_LOW (TYPE_MIN_VALUE (enumtype)) = minvalue;
- TREE_INT_CST_HIGH (TYPE_MIN_VALUE (enumtype)) = -1;
- TREE_UNSIGNED (enumtype) = 0;
- }
if (flag_cadillac)
cadillac_finish_enum (enumtype);
- /* Fix up all variant types of this enum type. */
- for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
- {
- TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
- TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
- TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
- TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
- TYPE_MODE (tem) = TYPE_MODE (enumtype);
- TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
- TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
- TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
- }
+ {
+ register tree tem;
+
+ /* Fix up all variant types of this enum type. */
+ for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
+ tem = TYPE_NEXT_VARIANT (tem))
+ {
+ TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
+ TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
+ TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
+ TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
+ TYPE_MODE (tem) = TYPE_MODE (enumtype);
+ TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
+ TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+ TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
+ }
+ }
/* Finish debugging output for this type. */
#if 0
}
else
{
- error ("enumerator value for `%s' not integer constant",
- IDENTIFIER_POINTER (name));
+ cp_error ("enumerator value for `%D' not integer constant", name);
value = NULL_TREE;
}
}
to keep that from happening. */
/* Default based on previous value. */
if (value == NULL_TREE)
- value = enum_next_value;
+ {
+ value = enum_next_value;
+ if (enum_overflow)
+ cp_error ("overflow in enumeration values at `%D'", name);
+ }
/* Remove no-op casts from the value. */
if (value)
STRIP_TYPE_NOPS (value);
- /* Make up for hacks in cp-lex.c. */
+ /* Make up for hacks in lex.c. */
if (value == integer_zero_node)
value = build_int_2 (0, 0);
else if (value == integer_one_node)
TREE_TYPE (value) = integer_type_node;
}
- result = saveable_tree_cons (name, value, NULL_TREE);
-
/* C++ associates enums with global, function, or class declarations. */
- /* There are a number of cases we need to be aware of here:
- current_class_type current_function_decl
- * global enums NULL NULL
- * fn-local enum NULL SET
- * class-local enum SET NULL
- * class->fn->enum SET SET
- * fn->class->enum SET SET
-
- Those last two make life interesting. If it's a fn-local enum which is
- itself inside a class, we need the enum to go into the fn's decls (our
- second case below). But if it's a class-local enum and the class itself
- is inside a function, we need that enum to go into the decls for the
- class. To achieve this last goal, we must see if, when both
- current_class_decl and current_function_decl are set, the class was
- declared inside that function. If so, we know to put the enum into
- the class's scope. */
-
- if ((current_class_type && ! current_function_decl)
- || (current_class_type && current_function_decl
- && TYPE_CONTEXT (current_class_type) == current_function_decl))
+ decl = current_scope ();
+ if (decl && decl == current_class_type)
{
/* This enum declaration is local to the class, so we must put
it in that class's list of decls. */
/* Set basis for default for next value. */
enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
integer_one_node, PLUS_EXPR);
+ enum_overflow = tree_int_cst_lt (enum_next_value, value);
+
if (enum_next_value == integer_one_node)
enum_next_value = copy_node (enum_next_value);
+ result = saveable_tree_cons (name, decl, NULL_TREE);
return result;
}
tree declarator, declspecs, raises;
int pre_parsed_p;
{
- extern tree EHS_decl;
tree decl1, olddecl;
tree ctype = NULL_TREE;
tree fntype;
extern int used_extern_spec;
int doing_friend = 0;
- if (flag_handle_exceptions && EHS_decl == NULL_TREE)
- init_exception_processing_1 ();
-
/* Sanity check. */
my_friendly_assert (TREE_VALUE (void_list_node) == void_type_node, 160);
my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
current_function_returns_value = 0;
current_function_returns_null = 0;
warn_about_return_type = 0;
- current_extern_inline = 0;
+ named_labels = 0;
+ shadowed_labels = 0;
current_function_assigns_this = 0;
current_function_just_assigned_this = 0;
current_function_parms_stored = 0;
original_result_rtx = NULL_RTX;
current_function_obstack_index = 0;
current_function_obstack_usage = 0;
+ base_init_insns = NULL_RTX;
+ protect_list = NULL_TREE;
+ current_base_init_list = NULL_TREE;
+ current_member_init_list = NULL_TREE;
clear_temp_name ();
doing_friend = 1;
}
- if ( !(DECL_VINDEX (decl1)
- && write_virtuals >= 2
- && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype)))
- current_extern_inline = TREE_PUBLIC (decl1) && DECL_INLINE (decl1);
-
raises = TYPE_RAISES_EXCEPTIONS (fntype);
/* In a fcn definition, arg types must be complete. */
/* If this doesn't return integer_type, complain. */
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
{
- warning ("return type for `main' changed to integer type");
+ if (pedantic || warn_return_type)
+ pedwarn ("return type for `main' changed to integer type");
TREE_TYPE (decl1) = fntype = default_function_type;
}
warn_about_return_type = 0;
DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, TREE_TYPE (fntype));
}
+ if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
+ && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
+ abstract_virtuals_error (decl1, TREE_TYPE (fntype));
+
if (warn_about_return_type)
warning ("return-type defaults to `int'");
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
+ if (DECL_INTERFACE_KNOWN (decl1))
+ {
+ if (DECL_NOT_REALLY_EXTERN (decl1))
+ DECL_EXTERNAL (decl1) = 0;
+ }
/* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external.
It doesn't matter whether it's inline or not. */
- if (interface_unknown == 0)
+ else if (interface_unknown == 0)
{
- TREE_PUBLIC (decl1) = 1;
- DECL_EXTERNAL (decl1) = (interface_only
- || (DECL_INLINE (decl1)
- && ! flag_implement_inlines));
+ if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
+ DECL_EXTERNAL (decl1)
+ = (interface_only
+ || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
+ else
+ DECL_EXTERNAL (decl1) = 0;
+ DECL_NOT_REALLY_EXTERN (decl1) = 0;
+ DECL_INTERFACE_KNOWN (decl1) = 1;
}
else
- /* This is a definition, not a reference.
- So normally clear DECL_EXTERNAL.
- However, `extern inline' acts like a declaration except for
- defining how to inline. So set DECL_EXTERNAL in that case. */
- DECL_EXTERNAL (decl1) = current_extern_inline;
-
- /* Now see if this is the implementation of a declared function. */
- if (ctype == NULL_TREE && current_lang_name == lang_name_cplusplus
- && !DECL_CONTEXT (decl1))
- {
- olddecl = lookup_name_current_level (DECL_NAME (decl1));
- if (olddecl && TREE_CODE (olddecl) != FUNCTION_DECL)
- olddecl = NULL_TREE;
- if (olddecl && DECL_NAME (decl1) != DECL_NAME (olddecl))
- {
- /* Collision between user and internal naming scheme. */
- olddecl = lookup_name_current_level (DECL_ASSEMBLER_NAME (decl1));
- if (olddecl == NULL_TREE)
- olddecl = decl1;
- }
- if (olddecl && olddecl != decl1
- && DECL_NAME (decl1) == DECL_NAME (olddecl))
- {
- if (TREE_CODE (olddecl) == FUNCTION_DECL
- && decls_match (decl1, olddecl))
- {
- olddecl = DECL_MAIN_VARIANT (olddecl);
- /* The following copy is needed to handle forcing a function's
- linkage to obey the linkage of the original decl. */
- DECL_ASSEMBLER_NAME (decl1) = DECL_ASSEMBLER_NAME (olddecl);
- DECL_OVERLOADED (decl1) = DECL_OVERLOADED (olddecl);
- if (! DECL_BUILT_IN (olddecl) && DECL_INITIAL (olddecl))
- redeclaration_error_message (decl1, olddecl);
- if (duplicate_decls (decl1, olddecl))
- decl1 = olddecl;
- else
- olddecl = NULL_TREE;
- }
- else
- olddecl = NULL_TREE;
+ {
+ /* This is a definition, not a reference.
+ So clear DECL_EXTERNAL. */
+ DECL_EXTERNAL (decl1) = 0;
+
+ if (DECL_THIS_INLINE (decl1) && ! DECL_C_STATIC (decl1))
+ DECL_DEFER_OUTPUT (decl1) = 1;
+ else
+ {
+ DECL_INTERFACE_KNOWN (decl1) = 1;
+ if (DECL_C_STATIC (decl1))
+ TREE_PUBLIC (decl1) = 0;
}
}
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
- if (olddecl)
- current_function_decl = olddecl;
- else if (pre_parsed_p == 0)
+ if (pre_parsed_p == 0)
{
- current_function_decl = pushdecl (decl1);
- if (TREE_CODE (current_function_decl) == TREE_LIST)
- {
- /* @@ revert to modified original declaration. */
- decl1 = DECL_MAIN_VARIANT (decl1);
- current_function_decl = decl1;
- }
- else
- {
- decl1 = current_function_decl;
- DECL_MAIN_VARIANT (decl1) = decl1;
- }
+ current_function_decl = decl1 = pushdecl (decl1);
+ DECL_MAIN_VARIANT (decl1) = decl1;
fntype = TREE_TYPE (decl1);
}
else
current_function_decl = decl1;
- if (DECL_OVERLOADED (decl1))
- decl1 = push_overloaded_decl (decl1, 1);
-
if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1))
{
if (TREE_CODE (fntype) == METHOD_TYPE)
}
restype = TREE_TYPE (fntype);
- pushlevel (0);
- current_binding_level->parm_flag = 1;
-
- /* Save the parm names or decls from this function's declarator
- where store_parm_decls will find them. */
- current_function_parms = last_function_parms;
- current_function_parm_tags = last_function_parm_tags;
-
- GNU_xref_function (decl1, current_function_parms);
-
- make_function_rtl (decl1);
-
if (ctype)
{
push_nested_class (ctype, 1);
push_memoized_context (0, 1);
}
+ pushlevel (0);
+ current_binding_level->parm_flag = 1;
+
+ /* Save the parm names or decls from this function's declarator
+ where store_parm_decls will find them. */
+ current_function_parms = last_function_parms;
+ current_function_parm_tags = last_function_parm_tags;
+
+ GNU_xref_function (decl1, current_function_parms);
+
+ make_function_rtl (decl1);
+
/* Allocate further tree nodes temporarily during compilation
of this function only. Tiemann moved up here from bottom of fn. */
temporary_allocation ();
register tree fndecl = current_function_decl;
register tree parm;
int parms_have_cleanups = 0;
- tree eh_decl;
/* This is either a chain of PARM_DECLs (when a prototype is used). */
tree specparms = current_function_parms;
/* Create a binding level for the parms. */
expand_start_bindings (0);
- /* Prepare to catch raises, if appropriate. */
- if (flag_handle_exceptions)
- {
- /* Get this cleanup to be run last, since it
- is a call to `longjmp'. */
- setup_exception_throw_decl ();
- eh_decl = current_binding_level->names;
- current_binding_level->names = TREE_CHAIN (current_binding_level->names);
- }
- if (flag_handle_exceptions)
- expand_start_try (integer_one_node, 0, 1);
-
if (specparms != NULL_TREE)
{
/* This case is when the function was defined with an ANSI prototype.
if (cleanup)
{
expand_decl (parm);
- expand_decl_cleanup (parm, cleanup);
+ if (! expand_decl_cleanup (parm, cleanup))
+ cp_error ("parser lost in parsing declaration of `%D'",
+ parm);
parms_have_cleanups = 1;
}
}
DECL_SAVED_INSNS (fndecl) = NULL_RTX;
expand_function_start (fndecl, parms_have_cleanups);
- if (flag_handle_exceptions)
- {
- /* Make the throw decl visible at this level, just
- not in the way of the parameters. */
- pushdecl (eh_decl);
- expand_decl_init (eh_decl);
- }
-
/* Create a binding contour which can be used to catch
cleanup-generated temporaries. Also, if the return value needs or
has initialization, deal with that now. */
if (flag_gc)
{
maybe_gc_cleanup = build_tree_list (NULL_TREE, error_mark_node);
- expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup);
+ if (! expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup))
+ cp_error ("parser lost in parsing declaration of `%D'", fndecl);
}
/* If this function is `main', emit a call to `__main'
if (flag_gc)
expand_expr (build_function_call (lookup_name (get_identifier ("__gc_main"), 0), NULL_TREE),
0, VOIDmode, 0);
-
- if (flag_dossier)
+#if 0
+ /* done at a different time */
+ if (flag_rtti)
output_builtin_tdesc_entries ();
+#endif
}
}
/* Give this error as many times as there are occurrences,
so that users can use Emacs compilation buffers to find
and fix all such places. */
- error ("ANSI C++ does not permit named return values");
+ pedwarn ("ANSI C++ does not permit named return values");
if (return_id != NULL_TREE)
{
/* Let `finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
pushdecl (decl);
- finish_decl (decl, init, 0, 0);
+ finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
}
}
-#if 0
-/* Generate code for default X() constructor. */
-static void
-build_default_constructor (fndecl)
- tree fndecl;
-{
- int i = CLASSTYPE_N_BASECLASSES (current_class_type);
- tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
- tree fields = TYPE_FIELDS (current_class_type);
- tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- parm = TREE_CHAIN (parm);
- parm = DECL_REFERENCE_SLOT (parm);
-
- while (--i >= 0)
- {
- tree basetype = TREE_VEC_ELT (binfos, i);
- if (TYPE_HAS_INIT_REF (basetype))
- {
- tree name = TYPE_NAME (basetype);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- current_base_init_list = tree_cons (name, parm, current_base_init_list);
- }
- }
- for (; fields; fields = TREE_CHAIN (fields))
- {
- tree name, init;
- if (TREE_STATIC (fields))
- continue;
- if (TREE_CODE (fields) != FIELD_DECL)
- continue;
- if (DECL_NAME (fields))
- {
- if (VFIELD_NAME_P (DECL_NAME (fields)))
- continue;
- if (VBASE_NAME_P (DECL_NAME (fields)))
- continue;
-
- /* True for duplicate members. */
- if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
- continue;
- }
-
- init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
- init = build_tree_list (NULL_TREE, init);
-
- current_member_init_list
- = tree_cons (DECL_NAME (fields), init, current_member_init_list);
- }
-}
-#endif
\f
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
constructors. */
void
-finish_function (lineno, call_poplevel)
+finish_function (lineno, call_poplevel, nested)
int lineno;
int call_poplevel;
+ int nested;
{
register tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE;
rtx head, last_parm_insn, mark;
- extern int sets_exception_throw_decl;
/* Label to use if this function is supposed to return a value. */
tree no_return_label = NULL_TREE;
tree decls = NULL_TREE;
store_parm_decls ();
}
- if (write_symbols != NO_DEBUG && TREE_CODE (fntype) != METHOD_TYPE)
+ if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/)
{
tree ttype = target_type (fntype);
tree parmdecl;
int ok_to_optimize_dtor = 0;
if (current_function_assigns_this)
- cond = build (NE_EXPR, integer_type_node,
+ cond = build (NE_EXPR, boolean_type_node,
current_class_decl, integer_zero_node);
else
{
/* These are two cases where we cannot delegate deletion. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
- || TREE_GETS_DELETE (current_class_type))
+ || TYPE_GETS_REG_DELETE (current_class_type))
exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
else
virtual_size = c_sizeof (current_class_type);
/* At the end, call delete if that's what's requested. */
- if (TREE_GETS_DELETE (current_class_type))
+ if (TYPE_GETS_REG_DELETE (current_class_type))
/* This NOP_EXPR means we are in a static call context. */
exprstmt =
build_method_call
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function
tables. */
- init_vtbl_ptrs (binfo, 1, 0);
+ expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_decl);
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- expand_expr_stmt (build_vbase_vtables_init (binfo, binfo,
- C_C_D, current_class_decl, 0));
+ expand_indirect_vtbls_init (binfo, C_C_D, current_class_decl, 0);
if (! ok_to_optimize_dtor)
{
cond = build_binary_op (NE_EXPR,
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
+ end_protect_partials ();
expand_label (ctor_label);
ctor_label = NULL_TREE;
if (call_poplevel)
{
decls = getdecls ();
- if (flag_handle_exceptions == 2)
- deactivate_exception_cleanups ();
expand_end_bindings (decls, decls != NULL_TREE, 0);
poplevel (decls != NULL_TREE, 0, 0);
}
current_class_decl, integer_zero_node, 1);
thenclause = build_modify_expr (current_class_decl, NOP_EXPR,
build_new (NULL_TREE, current_class_type, void_type_node, 0));
- if (flag_handle_exceptions == 2)
- {
- tree cleanup, cleanup_deallocate;
- tree virtual_size;
-
- /* This is the size of the virtual object pointed to by
- allocated_this. In this case, it is simple. */
- virtual_size = c_sizeof (current_class_type);
-
- allocated_this = build_decl (VAR_DECL, NULL_TREE, ptr_type_node);
- DECL_REGISTER (allocated_this) = 1;
- DECL_INITIAL (allocated_this) = error_mark_node;
- expand_decl (allocated_this);
- expand_decl_init (allocated_this);
- /* How we cleanup `this' if an exception was raised before
- we are ready to bail out. */
- cleanup = TREE_GETS_DELETE (current_class_type)
- ? build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, allocated_this, virtual_size, NULL_TREE)
- /* The size of allocated_this is wrong, and hence the
- second argument to operator delete will be wrong. */
- : build_delete (TREE_TYPE (allocated_this), allocated_this,
- integer_three_node,
- LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, 1);
- cleanup_deallocate
- = build_modify_expr (current_class_decl, NOP_EXPR, integer_zero_node);
- cleanup = tree_cons (NULL_TREE, cleanup,
- build_tree_list (NULL_TREE, cleanup_deallocate));
-
- expand_decl_cleanup (allocated_this,
- build (COND_EXPR, integer_type_node,
- build (NE_EXPR, integer_type_node,
- allocated_this, integer_zero_node),
- build_compound_expr (cleanup),
- integer_zero_node));
- }
}
CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
{
expand_start_cond (cond, 0);
expand_expr_stmt (thenclause);
- if (flag_handle_exceptions == 2)
- expand_assignment (allocated_this, current_class_decl, 0, 0);
expand_end_cond ();
}
if (mark != get_last_insn ())
reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
+ end_protect_partials ();
+
/* This is where the body of the constructor ends. */
expand_label (ctor_label);
ctor_label = NULL_TREE;
- if (flag_handle_exceptions == 2)
- {
- expand_assignment (allocated_this, integer_zero_node, 0, 0);
- if (call_poplevel)
- deactivate_exception_cleanups ();
- }
-
- pop_implicit_try_blocks (NULL_TREE);
if (call_poplevel)
{
- expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0);
+ decls = getdecls ();
+ expand_end_bindings (decls, decls != NULL_TREE, 0);
poplevel (decls != NULL_TREE, 1, 0);
}
/* Emit label at beginning of cleanup code for parameters. */
emit_label (cleanup_label);
-#if 1
- /* Cheap hack to get better code from GNU C++. Remove when cse is fixed. */
- if (exception_throw_decl && sets_exception_throw_decl == 0)
- expand_assignment (exception_throw_decl, integer_zero_node, 0, 0);
-#endif
-
- if (flag_handle_exceptions)
- {
- expand_end_try ();
- expand_start_except (0, 0);
- expand_end_except ();
- }
-
/* Get return value into register if that's where it's supposed to be. */
if (original_result_rtx)
fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
expand_label (no_return_label);
}
+ /* Generate rtl for function exit. */
+ expand_function_end (input_filename, lineno, 1);
+
+ if (flag_handle_exceptions)
+ expand_exception_blocks();
+
+ /* This must come after expand_function_end because cleanups might
+ have declarations (from inline functions) that need to go into
+ this function's blocks. */
+ if (current_binding_level->parm_flag != 1)
+ my_friendly_abort (122);
+ poplevel (1, 0, 1);
+
/* reset scope for C++: if we were in the scope of a class,
then when we finish this function, we are not longer so.
This cannot be done until we know for sure that no more
else
pop_memoized_context (1);
- /* Forget about all overloaded functions defined in
- this scope which go away. */
- while (overloads_to_forget)
- {
- IDENTIFIER_GLOBAL_VALUE (TREE_PURPOSE (overloads_to_forget))
- = TREE_VALUE (overloads_to_forget);
- overloads_to_forget = TREE_CHAIN (overloads_to_forget);
- }
-
- /* Generate rtl for function exit. */
- expand_function_end (input_filename, lineno, 1);
-
- /* This must come after expand_function_end because cleanups might
- have declarations (from inline functions) that need to go into
- this function's blocks. */
- if (current_binding_level->parm_flag != 1)
- my_friendly_abort (122);
- poplevel (1, 0, 1);
-
/* Must mark the RESULT_DECL as being in this function. */
DECL_CONTEXT (DECL_RESULT (fndecl)) = DECL_INITIAL (fndecl);
/* So we can tell if jump_optimize sets it to 1. */
can_reach_end = 0;
- /* ??? Compensate for Sun brain damage in dealing with data segments
- of PIC code. */
- if (flag_pic
- && (DECL_CONSTRUCTOR_P (fndecl)
- || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
- && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))
- DECL_INLINE (fndecl) = 0;
-
- if (DECL_EXTERNAL (fndecl)
- /* This function is just along for the ride. If we can make
- it inline, that's great. Otherwise, just punt it. */
- && (DECL_INLINE (fndecl) == 0
- || flag_no_inline
- || function_cannot_inline_p (fndecl)))
- {
- extern int rtl_dump_and_exit;
- int old_rtl_dump_and_exit = rtl_dump_and_exit;
- int inline_spec = DECL_INLINE (fndecl);
-
- /* This throws away the code for FNDECL. */
- rtl_dump_and_exit = 1;
- /* This throws away the memory of the code for FNDECL. */
- if (flag_no_inline)
- DECL_INLINE (fndecl) = 0;
- rest_of_compilation (fndecl);
- rtl_dump_and_exit = old_rtl_dump_and_exit;
- DECL_INLINE (fndecl) = inline_spec;
- }
- else
+ /* Run the optimizers and output the assembler code for this function. */
+ rest_of_compilation (fndecl);
+
+ if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
{
- /* Run the optimizers and output the assembler code for this
- function. */
- rest_of_compilation (fndecl);
+ /* Set DECL_EXTERNAL so that assemble_external will be called as
+ necessary. We'll clear it again in finish_file. */
+ if (! DECL_EXTERNAL (fndecl))
+ DECL_NOT_REALLY_EXTERN (fndecl) = 1;
+ DECL_EXTERNAL (fndecl) = 1;
+ mark_inline_for_output (fndecl);
}
if (ctype && TREE_ASM_WRITTEN (fndecl))
/* Free all the tree nodes making up this function. */
/* Switch back to allocating nodes permanently
until we start another function. */
- permanent_allocation (1);
+ if (! nested)
+ permanent_allocation (1);
if (flag_cadillac)
cadillac_finish_function (fndecl);
DECL_ARGUMENTS (fndecl) = NULL_TREE;
}
- /* Let the error reporting routines know that we're outside a function. */
- current_function_decl = NULL_TREE;
+ if (DECL_STATIC_CONSTRUCTOR (fndecl))
+ static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
+ if (DECL_STATIC_DESTRUCTOR (fndecl))
+ static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
+
+ if (! nested)
+ {
+ /* Let the error reporting routines know that we're outside a
+ function. For a nested function, this value is used in
+ pop_cp_function_context and then reset via pop_function_context. */
+ current_function_decl = NULL_TREE;
+ }
+
named_label_uses = NULL_TREE;
}
\f
return void_type_node;
}
- /* If we're expanding a template, a function must be explicitly declared
- inline if we're to compile it now. If it isn't, we have to wait to see
- whether it's needed, and whether an override exists. */
- if (flag_default_inline && !processing_template_defn)
+ DECL_THIS_INLINE (fndecl) = 1;
+
+ if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
+ if (processing_template_defn)
+ {
+ SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
+ repo_template_used (fndecl);
+ }
+
/* We read in the parameters on the maybepermanent_obstack,
but we won't be getting back to them until after we
may have clobbered them. So the call to preserve_data
}
if (DECL_CONSTRUCTOR_P (fndecl))
- grok_ctor_properties (current_class_type, fndecl);
+ {
+ if (! grok_ctor_properties (current_class_type, fndecl))
+ return void_type_node;
+ }
else if (IDENTIFIER_OPNAME_P (DECL_NAME (fndecl)))
grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl), 0);
}
- finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
+ finish_decl (fndecl, NULL_TREE, NULL_TREE, 0, 0);
/* Make a place for the parms */
pushlevel (0);
{
register tree fndecl = decl;
tree old_initial;
- tree context = DECL_CONTEXT (fndecl);
register tree link;
rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
if (! toplevel)
{
+ tree cleanup;
expand_decl (decl);
- expand_decl_cleanup (decl, maybe_build_cleanup (decl));
+ cleanup = maybe_build_cleanup (decl);
expand_decl_init (decl);
+ if (! expand_decl_cleanup (decl, cleanup))
+ cp_error ("parser lost in parsing declaration of `%D'",
+ decl);
}
}
+ /*
my_friendly_assert (current_binding_level->n_incomplete > 0, 164);
+ */
--current_binding_level->n_incomplete;
}
}
|| flag_expensive_optimizations)
flags |= LOOKUP_NONVIRTUAL;
- /* Use TYPE_MAIN_VARIANT so we don't get a warning about
- calling delete on a `const' variable. */
- if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (rval))))
- rval = build1 (NOP_EXPR, TYPE_POINTER_TO (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (rval)))), rval);
-
rval = build_delete (TREE_TYPE (rval), rval, integer_two_node, flags, 0);
if (TYPE_USES_VIRTUAL_BASECLASSES (type)
rval = build_compound_expr (tree_cons (NULL_TREE, rval,
build_tree_list (NULL_TREE, build_vbase_delete (type, decl))));
- current_binding_level->have_cleanups = 1;
- current_binding_level->more_exceptions_ok = 0;
-
if (TREE_CODE (decl) != PARM_DECL)
resume_momentary (temp);
cp_warning ("reference, not call, to function `%D'", exp);
warning ("at this point in file");
}
- if (TREE_RAISES (exp))
- {
- my_friendly_assert (flag_handle_exceptions, 165);
- if (flag_handle_exceptions == 2)
- {
- if (! current_binding_level->more_exceptions_ok)
- {
- extern struct nesting *nesting_stack, *block_stack;
-
- remove_implicit_immediately
- = (nesting_stack != block_stack);
- cplus_expand_start_try (1);
- }
- current_binding_level->have_exceptions = 1;
- }
- }
+#if 0
+ /* We should do this eventually, but right now this causes regex.o from
+ libg++ to miscompile, and tString to core dump. */
+ exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
+#endif
expand_expr_stmt (break_out_cleanups (exp));
-
- if (remove_implicit_immediately)
- pop_implicit_try_blocks (NULL_TREE);
}
/* Clean up any pending cleanups. This happens when a function call
cadillac_finish_stmt ();
}
+/* Change a static member function definition into a FUNCTION_TYPE, instead
+ of the METHOD_TYPE that we create when it's originally parsed.
+
+ WARNING: DO NOT pass &TREE_TYPE (decl) to FN or &TYPE_ARG_TYPES
+ (TREE_TYPE (decl)) to ARGTYPES, as doing so will corrupt the types of
+ other decls. Either pass the addresses of local variables or NULL. */
+
void
-pop_implicit_try_blocks (decl)
- tree decl;
+revert_static_member_fn (decl, fn, argtypes)
+ tree *decl, *fn, *argtypes;
{
- if (decl)
- {
- my_friendly_assert (current_binding_level->parm_flag == 3, 166);
- current_binding_level->names = TREE_CHAIN (decl);
- }
-
- while (current_binding_level->parm_flag == 3)
- {
- tree name = get_identifier ("(compiler error)");
- tree orig_ex_type = current_exception_type;
- tree orig_ex_decl = current_exception_decl;
- tree orig_ex_obj = current_exception_object;
- tree decl = cplus_expand_end_try (2);
+ tree tmp;
+ tree function = fn ? *fn : TREE_TYPE (*decl);
+ tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function);
- /* @@ It would be nice to make all these point
- to exactly the same handler. */
- /* Start hidden EXCEPT. */
- cplus_expand_start_except (name, decl);
- /* reraise ALL. */
- cplus_expand_reraise (NULL_TREE);
- current_exception_type = orig_ex_type;
- current_exception_decl = orig_ex_decl;
- current_exception_object = orig_ex_obj;
- /* This will reraise for us. */
- cplus_expand_end_except (error_mark_node);
- }
+ args = TREE_CHAIN (args);
+ tmp = build_function_type (TREE_TYPE (function), args);
+ tmp = build_type_variant (tmp, TYPE_READONLY (function),
+ TYPE_VOLATILE (function));
+ tmp = build_exception_variant (TYPE_METHOD_BASETYPE (function), tmp,
+ TYPE_RAISES_EXCEPTIONS (function));
+ TREE_TYPE (*decl) = tmp;
+ DECL_STATIC_FUNCTION_P (*decl) = 1;
+ if (fn)
+ *fn = tmp;
+ if (argtypes)
+ *argtypes = args;
+}
- if (decl)
- {
- TREE_CHAIN (decl) = current_binding_level->names;
- current_binding_level->names = decl;
- }
+int
+id_in_current_class (id)
+ tree id;
+{
+ return !!purpose_member (id, class_binding_level->class_shadowed);
}
-/* Push a cleanup onto the current binding contour that will cause
- ADDR to be cleaned up, in the case that an exception propagates
- through its binding contour. */
+struct cp_function
+{
+ int returns_value;
+ int returns_null;
+ int warn_about_return_type;
+ int assigns_this;
+ int just_assigned_this;
+ int parms_stored;
+ int temp_name_counter;
+ tree named_labels;
+ tree shadowed_labels;
+ tree ctor_label;
+ tree dtor_label;
+ tree protect_list;
+ tree base_init_list;
+ tree member_init_list;
+ rtx result_rtx;
+ rtx base_init_insns;
+ struct cp_function *next;
+ struct binding_level *binding_level;
+};
+
+struct cp_function *cp_function_chain;
+
+extern int temp_name_counter;
+
+/* Save and reinitialize the variables
+ used during compilation of a C++ function. */
void
-push_exception_cleanup (addr)
- tree addr;
+push_cp_function_context (context)
+ tree context;
{
- tree decl = build_decl (VAR_DECL, get_identifier (EXCEPTION_CLEANUP_NAME), ptr_type_node);
- tree cleanup;
-
- decl = pushdecl (decl);
- DECL_REGISTER (decl) = 1;
- store_init_value (decl, addr);
- expand_decl (decl);
- expand_decl_init (decl);
-
- cleanup = build (COND_EXPR, integer_type_node,
- build (NE_EXPR, integer_type_node,
- decl, integer_zero_node),
- build_delete (TREE_TYPE (addr), decl,
- lookup_name (in_charge_identifier, 0),
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0),
- integer_zero_node);
- expand_decl_cleanup (decl, cleanup);
+ struct cp_function *p
+ = (struct cp_function *) xmalloc (sizeof (struct cp_function));
+
+ push_function_context_to (context);
+
+ p->next = cp_function_chain;
+ cp_function_chain = p;
+
+ p->named_labels = named_labels;
+ p->shadowed_labels = shadowed_labels;
+ p->returns_value = current_function_returns_value;
+ p->returns_null = current_function_returns_null;
+ p->warn_about_return_type = warn_about_return_type;
+ p->binding_level = current_binding_level;
+ p->ctor_label = ctor_label;
+ p->dtor_label = dtor_label;
+ p->assigns_this = current_function_assigns_this;
+ p->just_assigned_this = current_function_just_assigned_this;
+ p->parms_stored = current_function_parms_stored;
+ p->result_rtx = original_result_rtx;
+ p->base_init_insns = base_init_insns;
+ p->protect_list = protect_list;
+ p->temp_name_counter = temp_name_counter;
+ p->base_init_list = current_base_init_list;
+ p->member_init_list = current_member_init_list;
}
-/* For each binding contour, emit code that deactivates the
- exception cleanups. All other cleanups are left as they were. */
+/* Restore the variables used during compilation of a C++ function. */
-static void
-deactivate_exception_cleanups ()
+void
+pop_cp_function_context (context)
+ tree context;
{
- struct binding_level *b = current_binding_level;
- tree xyzzy = get_identifier (EXCEPTION_CLEANUP_NAME);
- while (b != class_binding_level)
+ struct cp_function *p = cp_function_chain;
+ tree link;
+
+ /* Bring back all the labels that were shadowed. */
+ for (link = shadowed_labels; link; link = TREE_CHAIN (link))
+ if (DECL_NAME (TREE_VALUE (link)) != 0)
+ SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)),
+ TREE_VALUE (link));
+
+#if 0
+ if (DECL_SAVED_INSNS (current_function_decl) == 0)
{
- if (b->parm_flag == 3)
- {
- tree decls = b->names;
- while (decls)
- {
- if (DECL_NAME (decls) == xyzzy)
- expand_assignment (decls, integer_zero_node, 0, 0);
- decls = TREE_CHAIN (decls);
- }
- }
- b = b->level_chain;
+ /* Stop pointing to the local nodes about to be freed. */
+ /* But DECL_INITIAL must remain nonzero so we know this
+ was an actual function definition. */
+ DECL_INITIAL (current_function_decl) = error_mark_node;
+ DECL_ARGUMENTS (current_function_decl) = 0;
}
-}
-
-/* Change a static member function definition into a FUNCTION_TYPE, instead
- of the METHOD_TYPE that we create when it's originally parsed. */
-void
-revert_static_member_fn (fn, decl, argtypes)
- tree *fn, *decl, *argtypes;
-{
- tree tmp, function = *fn;
+#endif
- *argtypes = TREE_CHAIN (*argtypes);
- tmp = build_function_type (TREE_TYPE (function), *argtypes);
- tmp = build_type_variant (tmp, TYPE_READONLY (function),
- TYPE_VOLATILE (function));
- tmp = build_exception_variant (TYPE_METHOD_BASETYPE (function), tmp,
- TYPE_RAISES_EXCEPTIONS (function));
- TREE_TYPE (*decl) = tmp;
- *fn = tmp;
- DECL_STATIC_FUNCTION_P (*decl) = 1;
+ pop_function_context_from (context);
+
+ cp_function_chain = p->next;
+
+ named_labels = p->named_labels;
+ shadowed_labels = p->shadowed_labels;
+ current_function_returns_value = p->returns_value;
+ current_function_returns_null = p->returns_null;
+ warn_about_return_type = p->warn_about_return_type;
+ current_binding_level = p->binding_level;
+ ctor_label = p->ctor_label;
+ dtor_label = p->dtor_label;
+ protect_list = p->protect_list;
+ current_function_assigns_this = p->assigns_this;
+ current_function_just_assigned_this = p->just_assigned_this;
+ current_function_parms_stored = p->parms_stored;
+ original_result_rtx = p->result_rtx;
+ base_init_insns = p->base_init_insns;
+ temp_name_counter = p->temp_name_counter;
+ current_base_init_list = p->base_init_list;
+ current_member_init_list = p->member_init_list;
+
+ free (p);
}