/* 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.
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));
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 bool_type_node, true_node, false_node;
+tree boolean_type_node, boolean_true_node, boolean_false_node;
/* type `int ()' -- used for implicit declaration of functions. */
/* 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;
/* 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. */
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 disable GNU extensions. */
+/* Nonzero means don't recognize the non-ANSI builtin functions.
+ -ansi sets this. */
+
+extern int flag_no_nonansi_builtin;
+
+/* 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;
/* 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.
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,
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 || force)
for (shadowed = level->class_shadowed;
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;
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;
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;
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);
- TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
-
- /* 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. */
#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. */
context = current_scope ();
if (context)
c_decl = TREE_CODE (context) == FUNCTION_DECL
- ? context : TYPE_NAME (context);
+ ? 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;
#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_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 (newdecl)
{
- if (ANON_AGGRNAME_P (name))
- DECL_IGNORED_P (d) = 1;
- }
- TYPE_NAME (type) = d;
+ 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);
- if (context == NULL_TREE)
- /* Non-nested class. */
- DECL_NESTED_TYPENAME (d) = name;
- else if (context && TREE_CODE (context) == FUNCTION_DECL)
- {
- /* Function-nested class. */
- set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl),
- name, type);
- /* This builds the links for classes nested in fn scope. */
- DECL_CONTEXT (d) = context;
- }
-/* else if (TYPE_SIZE (current_class_type) == NULL_TREE)
-*/
- else if (context && IS_AGGR_TYPE (context))
- {
- /* Class-nested class. */
- set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
- name, type);
- /* This builds the links for classes nested in type scope. */
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;
{
for (i = 0; i < len; i++)
{
- tree newarg = TREE_VEC_ELT (newargs, i);
- tree oldarg = TREE_VEC_ELT (oldargs, 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) == IDENTIFIER_NODE)
+ else if (TREE_CODE (newarg) == TYPE_DECL)
/* continue */;
else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
return 0;
= "`%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. */
int new_defines_function;
tree previous_c_decl = NULL_TREE;
+ if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
+ DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl);
+
types_match = decls_match (newdecl, olddecl);
if (TREE_CODE (olddecl) != TREE_LIST)
after implicit decl. */
;
else if (TREE_CODE (olddecl) == FUNCTION_DECL
+ && 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. Ditto for overloads. */
- if (! TREE_PUBLIC (newdecl)
+ if (! DECL_PUBLIC (newdecl)
|| (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl)))
{
newdecl);
cp_error_at ("previous declaration `%#D' here", olddecl);
}
-
- if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
- TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2))
+ 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 if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
{
- /* 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);
+ cp_error ("conflicting types for `%#D'", newdecl);
cp_error_at ("previous declaration as `%#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 (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);
+ }
+ }
+
+ 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_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))
{
&& !(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);
- /* Merge the data types specified in the two decls. */
- tree newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
+ tree newtype;
- /* Make sure we put the new type in the same obstack as the old ones.
- If the old types are not both in the same obstack, use the permanent
- one. */
- if (oldtype && TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (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
{
end_temporary_allocation ();
}
+ /* Merge the data types specified in the two decls. */
+ newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
+
if (TREE_CODE (newdecl) == VAR_DECL)
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
/* Do this after calling `common_type' so that default
if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
{
- cp_error ("declaration of `%D' raises different exceptions...",
+ 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
- && TREE_CODE (newdecl) != TEMPLATE_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))
}
/* 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);
- if (TREE_CODE (newdecl) != FUNCTION_DECL)
- TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ {
+ 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_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;
- else if (TREE_CODE (newdecl) != FUNCTION_DECL)
- TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
+ else
+ {
+ TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
+
+ /* 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;
+ }
}
- /* 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_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 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 (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
if (! types_match)
{
DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
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)
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)
#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
&& ! DECL_TEMPLATE_IS_CLASS (x)))
&& is_overloaded_fn (t))
/* don't do anything just yet */;
+ else if (t == wchar_decl_node)
+ {
+ 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 (TREE_CODE (t) != TREE_CODE (x))
{
- if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL)
+ 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
{
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)
/* 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. */
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_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,
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 (++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 (! TREE_MANGLED (name))
- 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 (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));
}
}
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),
old = TREE_OPERAND (old, 0);
else
#endif
- if (TREE_CODE (old) == VAR_DECL)
- {
- cp_error_at ("previous non-function declaration `%#D'", old);
- cp_error ("conflicts with function declaration `%#D'", decl);
- return error_mark_node;
- }
- else if (TREE_CODE (old) == TYPE_DECL)
+ if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
{
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 (old))
{
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 (old || TREE_CODE (decl) == TEMPLATE_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 "`%#D' not declared in class";
else
return "redefinition of `%#D'";
}
-
- {
- tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
- tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
-
- if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
- t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
-
- for (; t1; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
- if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
- return "duplicate default arguments given for `%#D'";
- }
return 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
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;
- /* 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 `%#D'";
/* Reject two definitions. */
return "redefinition of `%#D'";
}
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;
&& 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);
}
{
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 (got_scope != NULL_TREE)
+ if (type)
{
- if (got_scope == void_type_node)
+ if (type == error_mark_node)
+ return error_mark_node;
+ else if (type == void_type_node)
val = IDENTIFIER_GLOBAL_VALUE (name);
- else if (TREE_CODE (got_scope) == TEMPLATE_TYPE_PARM
+ else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
/* TFIXME -- don't do this for UPTs in new model. */
- || TREE_CODE (got_scope) == UNINSTANTIATED_P_TYPE)
+ || TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
{
if (prefer_type > 0)
- val = create_nested_upt (got_scope, name);
+ val = create_nested_upt (type, name);
else
val = NULL_TREE;
}
- else if (! IS_AGGR_TYPE (got_scope))
+ else if (! IS_AGGR_TYPE (type))
/* Someone else will give an error about this if needed. */
val = NULL_TREE;
- else if (TYPE_BEING_DEFINED (got_scope))
+ else if (TYPE_BEING_DEFINED (type))
{
val = IDENTIFIER_CLASS_VALUE (name);
- if (val && DECL_CONTEXT (val) != got_scope)
+ 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)) == got_scope)
+ && DECL_CONTEXT (TREE_VALUE (t)) == type)
{
val = TREE_VALUE (t);
break;
}
}
if (val == NULL_TREE
- && CLASSTYPE_LOCAL_TYPEDECLS (got_scope))
- val = lookup_field (got_scope, name, 0, 1);
+ && CLASSTYPE_LOCAL_TYPEDECLS (type))
+ val = lookup_field (type, name, 0, 1);
}
- else if (got_scope == current_class_type)
+ else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
- val = lookup_field (got_scope, name, 0, 0);
-
- goto done;
+ 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
done:
if (val)
{
+ 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 ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
|| TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
- return val;
-
- if (IDENTIFIER_HAS_TYPE_VALUE (name))
- return TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
-
- if (TREE_TYPE (val) == error_mark_node)
- return error_mark_node;
+ ;
+ 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;
}
while (1)
{
for (t = b->names; t; t = TREE_CHAIN (t))
- if (DECL_NAME (t) == name)
+ if (DECL_NAME (t) == name || DECL_ASSEMBLER_NAME (t) == name)
goto out;
if (b->keep == 2)
b = b->level_chain;
}
}
- 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_ansi || pedantic)
- strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
+ 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));
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);
- bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
- TREE_SET_CODE (bool_type_node, BOOLEAN_TYPE);
- record_builtin_type (RID_BOOL, "bool", bool_type_node);
- false_node = build_int_2 (0, 0);
- TREE_TYPE (false_node) = bool_type_node;
- true_node = build_int_2 (1, 0);
- TREE_TYPE (true_node) = bool_type_node;
+ 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);
sizetype,
endlink)),
BUILT_IN_ALLOCA, "alloca");
-#if 0
- builtin_function ("alloca",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)),
- BUILT_IN_ALLOCA, NULL_PTR);
-#endif
+ /* 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 ("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
: 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);
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
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:
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,
NOT_BUILT_IN);
abort_fndecl
- = define_function ("abort",
+ = define_function ("__pure_virtual",
build_function_type (void_type_node, void_list_node),
NOT_BUILT_IN, 0, 0);
{
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
tree declspecs;
{
int found_tag = 0;
- int warned = 0;
tree ob_modifier = NULL_TREE;
register tree link;
register enum tree_code code, ok_code = ERROR_MARK;
code = TREE_CODE (value);
if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
{
- register tree name = TYPE_NAME (value);
+ my_friendly_assert (TYPE_NAME (value) != NULL_TREE, 261);
if (code == ENUMERAL_TYPE && TYPE_SIZE (value) == 0)
cp_error ("forward declaration of `%#T'", 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);
-
- 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;
- }
- else if (name != NULL_TREE || code == ENUMERAL_TYPE)
- ok_code = code;
-
- 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]
|| value == ridpointers[(int) RID_AUTO]
- || value == ridpointers[(int) RID_REGISTER])
+ || value == ridpointers[(int) RID_REGISTER]
+ || value == ridpointers[(int) RID_INLINE]
+ || value == ridpointers[(int) RID_VIRTUAL]
+ || value == ridpointers[(int) RID_EXPLICIT])
ob_modifier = value;
}
{
/* Anonymous unions are objects, that's why we only check for
inappropriate specifiers in this branch. */
- if (ob_modifier)
- cp_error ("`%D' can only be specified for objects and functions",
- ob_modifier);
- 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);
+ cp_error ("`%D' can only be specified for objects and functions",
+ ob_modifier);
+ }
- ename = TYPE_NAME (t);
- if (TREE_CODE (ename) == TYPE_DECL)
- ename = DECL_NAME (ename);
- decl = build_lang_field_decl (VAR_DECL, ename, t);
-
- pop_obstacks ();
- }
- }
- else if (found_tag == 0)
+ if (found_tag == 0)
pedwarn ("abstract declarator used as declaration");
- else if (!warned && found_tag > 1)
+ else if (found_tag > 1)
pedwarn ("multiple types in one declaration");
}
}
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 = 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. */
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)
else
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++. */
{
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 ();
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. */
+ tmp = convert_to_reference
+ (type, init, CONV_IMPLICIT, LOOKUP_SPECULATIVELY|LOOKUP_NORMAL, decl);
- /* 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
- (type, init, CONV_IMPLICIT,
- LOOKUP_SPECULATIVELY|LOOKUP_NORMAL, decl)))
+ if (tmp == error_mark_node)
+ goto fail;
+ else if (tmp != NULL_TREE)
{
- if (actual_init == error_mark_node)
- goto fail;
+ tree subtype = TREE_TYPE (type);
+ init = tmp;
- init = actual_init;
- is_reference = 1;
-
- 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);
-
/* ?? 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;
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. */
DECL_CONTEXT (decl) == NULL_TREE, 0);
goto finish_end;
}
- if (type != error_mark_node && IS_AGGR_TYPE (type)
- && CLASSTYPE_DECLARED_EXCEPTION (type))
- {
- 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;
}
{
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))
{
}
}
#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))
;
&& (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. Consts have to go
- into data, though, since the backend would put them in text
- otherwise. */
- if (flag_pic == 0
- && TREE_STATIC (decl)
- && (TREE_PUBLIC (decl) || was_readonly)
- && ! 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)))
&& 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));
else if (toplev && ! TREE_PUBLIC (decl))
{
/* If this is a static const, change its apparent linkage
- if it belongs to a #pragma interface. */
+ if it belongs to a #pragma interface. */
if (!interface_unknown)
{
TREE_PUBLIC (decl) = 1;
signature_error (decl, TREE_TYPE (type));
if (TREE_CODE (decl) == FUNCTION_DECL)
- {
-#if 0
- /* 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;
- }
-#endif
- }
+ ;
else if (DECL_EXTERNAL (decl))
;
else if (TREE_STATIC (decl) && type != error_mark_node)
{
emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
- expand_aggr_init (decl, init, 0);
+ 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. */
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
/* 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 (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.
not look, and -1 if we should not call `grokclassfn' at all. */
static tree
grokfndecl (ctype, type, declarator, virtualp, flags, quals,
- raises, check, publicp)
+ 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)
{
/* 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. */
t = make_lang_type (RECORD_TYPE);
/* Let the front-end know this is a pointer to member function. */
- TYPE_PTRMEMFUNC_FLAG(t) = 1;
+ 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);
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;
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))
dname = decl;
decl = NULL_TREE;
- if (IDENTIFIER_OPNAME_P (dname))
+ 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))
{
}
name = operator_name_string (dname);
}
- else
- name = IDENTIFIER_POINTER (dname);
break;
case RECORD_TYPE:
}
}
+ 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 (type)
- error ("extraneous `char' ignored");
- else
- {
- explicit_char = 1;
- type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
- }
- goto found;
- }
- if (id == ridpointers[(int) RID_BOOL])
+ 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 `bool' ignored");
- else
{
- 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 (pedantic && flag_ansi)
- pedwarn ("duplicate `long'");
+ 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
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;
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)
{
if (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)))
+ && return_type == return_normal)
/* Save warning until we know what is really going on. */
warn_about_return_type = 1;
}
- else if (decl_context == FIELD && declarator
- && TREE_CODE (declarator) == SCOPE_REF)
- /* OK -- access declaration */;
+ 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",
}
else if (return_type == return_conversion)
{
- if (comp_target_types (type, ctor_return_type, 1) == 0)
+ if (comptypes (type, ctor_return_type, 1) == 0)
cp_error ("operator `%T' declared to return `%T'",
ctor_return_type, type);
else
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);
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;
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)))
;
break;
}
- if (scanner == IDENTIFIER_AS_LIST (ridpointers [(int) RID_TYPEDEF]))
- {
- if (previous_declspec)
- TREE_CHAIN (previous_declspec)
- = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
- else
- declspecs
- = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
- }
+ if (previous_declspec)
+ TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner);
else
- TREE_VALUE (scanner) = ridpointers[(int) RID_STATIC];
+ 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. */
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);
{
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)
{
}
if (TREE_READONLY_DECL_P (size))
size = decl_constant_value (size);
- if (flag_ansi && integer_zerop (size))
+ if (pedantic && integer_zerop (size))
cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", dname);
if (TREE_CONSTANT (size))
{
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 (flag_ansi)
+ if (pedantic)
{
if (dname)
cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
else
cp_pedwarn ("ANSI C++ forbids variable-size array");
}
- dont_grok_size:
- itype =
- build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
/* 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)
- type = c_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;
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;
- }
{
RID_BIT_TYPE tmp_bits;
bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE));
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)
- ? 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);
}
&& (constp || volatilep))
{
if (constp)
- warning ("discarding `const' applied to a reference");
+ pedwarn ("discarding `const' applied to a reference");
if (volatilep)
- warning ("discarding `volatile' applied to a reference");
+ pedwarn ("discarding `volatile' applied to a reference");
constp = volatilep = 0;
}
}
/* 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);
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);
}
}
}
+ 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? */
{
/* Transfer const-ness of array into that of type pointed to. */
type = build_pointer_type
- (build_type_variant (TREE_TYPE (type), constp, volatilep));
+ (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);
+ else if (type == void_type_node && declarator)
+ {
+ error ("declaration of `%s' as void", name);
+ return NULL_TREE;
+ }
decl = build_decl (PARM_DECL, declarator, type);
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
- publicp = (RIDBIT_SETP (RID_EXTERN, specbits)
- || (ctype != NULL_TREE
- && funcdef_flag >= 0
- && RIDBIT_NOTSETP (RID_INLINE, specbits))
- || (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);
+ raises, friendp ? -1 : 0, publicp, inlinep);
if (decl == NULL_TREE)
return NULL_TREE;
+ decl = build_decl_attribute_variant (decl, decl_machine_attr);
- DECL_INLINE (decl) = inlinep;
+ 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);
+ raises, friendp ? -1 : 0, 1, 0);
if (decl == NULL_TREE)
return NULL_TREE;
-
- 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;
- return void_type_node;
}
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;
}
initialize the named nonstatic member.... This (or an
initializer list) is the only way to initialize
nonstatic const and reference members. */
- else if (flag_ansi || ! constp)
+ else if (pedantic || ! constp)
cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
constp ? "const member" : "member", declarator);
}
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) = !!staticp;
+ TREE_STATIC (decl) = 1;
+ /* In class context, 'static' means public access. */
+ TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = !!staticp;
}
else
{
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))
- || !(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 (! 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 (ctype)
+ {
+ ctype = NULL_TREE;
+ error ("cannot use `::' in parameter declaration");
+ }
- if (! 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;
+ /* 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 (RIDBIT_SETP (RID_EXTERN, specbits))
+ if (TREE_CODE (type) == ARRAY_TYPE)
{
- current_extern_inline = 1;
- if (flag_ansi)
- 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);
}
- }
- else
- {
- /* It's a variable. */
/* An uninitialized decl with `extern' is a reference. */
decl = grokvardecl (type, declarator, specbits, initialized);
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_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;
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_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_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_nonclass_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 (t && TREE_CODE (t) != code)
t = NULL_TREE;
- if (xref_next_defn)
+ 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))
- {
- if (TREE_MANGLED (name))
- ref = t;
- else
- ref = lookup_tag (code, name, b, 1);
- }
+ 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)
- {
- /* 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 1
- /* This code replaces similar code in layout_basetypes. */
- else if (TYPE_SIZE (basetype) == NULL_TREE)
- {
- cp_error ("base class `%T' has incomplete type", 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.) */
-
- 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;
-
- 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;
- }
-#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);
- 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;
-
- 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);
- }
+ xref_basetypes (code_type_node, name, ref, binfo);
just_return:
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_INCOMPLETE (basetype))
+ {
+ cp_error ("base class `%T' has incomplete type", 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.) */
+
+ 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;
+ BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
+
+ 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;
+ }
+#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);
+ 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;
+
+ 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);
+
+ pop_obstacks ();
+}
+
\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. */
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;
-
+ 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_TYPE (TREE_VALUE (values)) = enumtype;
- TREE_TYPE (DECL_INITIAL (TREE_VALUE (values))) = enumtype;
- TREE_VALUE (values) = DECL_INITIAL (TREE_VALUE (values));
- value = TREE_INT_CST_LOW (TREE_VALUE (values));
- 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 = DECL_INITIAL (TREE_VALUE (pair));
TREE_TYPE (TREE_VALUE (pair)) = enumtype;
- TREE_TYPE (DECL_INITIAL (TREE_VALUE (pair))) = enumtype;
- TREE_VALUE (pair) = DECL_INITIAL (TREE_VALUE (pair));
- value = TREE_INT_CST_LOW (TREE_VALUE (pair));
- if (value > maxvalue)
- maxvalue = value;
- else if (value < minvalue)
- minvalue = value;
+ 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;
TYPE_VALUES (enumtype) = values;
- if (flag_short_enums)
- {
- /* Determine the precision this type needs, lay it out, and define
- it. */
-
- /* First reset precision */
- TYPE_PRECISION (enumtype) = 0;
-
- 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);
- TREE_INT_CST_LOW (TYPE_MAX_VALUE (enumtype)) = maxvalue;
+ 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);
+
+ 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
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 = DECL_THIS_EXTERN (decl1) && DECL_INLINE (decl1);
-
raises = TYPE_RAISES_EXCEPTIONS (fntype);
/* In a fcn definition, arg types must be complete. */
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
{
if (pedantic || warn_return_type)
- warning ("return type for `main' changed to integer 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 if (DECL_EXPLICIT_INSTANTIATION (decl1))
- /* PUBLIC and EXTERNAL set by do_*_instantiation */;
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;
+ So clear DECL_EXTERNAL. */
+ DECL_EXTERNAL (decl1) = 0;
-#if 0
- DECL_DEFER_OUTPUT (decl1)
- = (DECL_INLINE (decl1) && (DECL_IMPLICIT_INSTANTIATION (decl1)
- || DECL_FUNCTION_MEMBER_P (decl1)));
-#endif
+ 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;
+ }
}
/* Record the decl so that the function name is defined.
}
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 ();
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
}
}
{
tree decl = DECL_RESULT (current_function_decl);
- if (flag_ansi)
+ if (pedantic)
/* 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. */
/* 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;
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
{
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
+ end_protect_partials ();
expand_label (ctor_label);
ctor_label = NULL_TREE;
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 (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);
}
expand_label (no_return_label);
}
- /* 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
- class members will ever be referenced in this function
- (i.e., calls to destructors). */
- if (current_class_name)
- {
- ctype = current_class_type;
- pop_nested_class (1);
- }
- else
- pop_memoized_context (1);
-
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 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
+ class members will ever be referenced in this function
+ (i.e., calls to destructors). */
+ if (current_class_name)
+ {
+ ctype = current_class_type;
+ pop_nested_class (1);
+ }
+ else
+ pop_memoized_context (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);
- }
+ /* Run the optimizers and output the assembler code for this function. */
+ rest_of_compilation (fndecl);
- if (DECL_INLINE (fndecl)
- && !TREE_ASM_WRITTEN (fndecl) && DECL_FUNCTION_MEMBER_P (fndecl))
+ if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (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);
}
/* 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;
}
+ DECL_THIS_INLINE (fndecl) = 1;
+
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
if (processing_template_defn)
- SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
+ {
+ 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
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);
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)
warning ("at this point in file");
}
+#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));
}
{
return !!purpose_member (id, class_binding_level->class_shadowed);
}
+
+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_cp_function_context (context)
+ tree context;
+{
+ 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;
+}
+
+/* Restore the variables used during compilation of a C++ function. */
+
+void
+pop_cp_function_context (context)
+ tree context;
+{
+ 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)
+ {
+ /* 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;
+ }
+#endif
+
+ 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);
+}