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;
/* 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;
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;
#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. */
= "`%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) && ! DECL_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. */
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)
&& !(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
}
/* 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);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
- DECL_DECLARED_STATIC (newdecl) = DECL_DECLARED_STATIC (olddecl);
+ 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
}
}
- /* 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)
{
+ DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl);
+
+ /* If either decl says `inline', this fn is inline, unless its
+ definition was passed already. */
+ if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
+ DECL_INLINE (olddecl) = 1;
+ DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+
if (! types_match)
{
DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
/* 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 (duplicate_decls (x, oldglobal))
+ if (decls_match (x, oldglobal))
/* OK */;
else
{
/* 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";
}
}
+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. */
{
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
}
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
/* 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)))
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)
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;
definition or EOF) if appropriate. */
TREE_PUBLIC (decl) = 1;
- if (publicp)
- ;
- else
- DECL_DECLARED_STATIC (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)
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. */
}
/* 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);
- decl = build_decl_attribute_variant (decl, decl_machine_attr);
+ raises, friendp ? -1 : 0, publicp, inlinep);
if (decl == NULL_TREE)
return NULL_TREE;
+ decl = build_decl_attribute_variant (decl, decl_machine_attr);
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
-
- DECL_INLINE (decl) = inlinep;
}
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 (TYPE_SIZE (type) == NULL_TREE && !staticp
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
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'. */
- publicp
- = !(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;
cp_pedwarn ("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");
- illegal_static = 1;
- }
else if (current_function_decl)
{
/* FIXME need arm citation */
RIDBIT_RESET (RID_STATIC, specbits);
}
}
-
- /* Record presence of `inline', if it is reasonable. */
- if (inlinep)
- {
- tree last = tree_last (TYPE_ARG_TYPES (type));
-
- 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;
-
- if (RIDBIT_SETP (RID_EXTERN, specbits))
- {
- current_extern_inline = 1;
- if (pedantic)
- pedwarn ("ANSI C++ does not permit `extern inline'");
- }
- }
}
else
{
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)
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;
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. */
TREE_STATIC (decl1) = 1;
if (DECL_INTERFACE_KNOWN (decl1))
- /* We know. */;
+ {
+ 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. */
else if (interface_unknown == 0)
{
- if (DECL_DECLARED_STATIC (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
+ if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
DECL_EXTERNAL (decl1)
= (interface_only
- || (DECL_INLINE (decl1) && ! flag_implement_inlines));
+ || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
else
- DECL_EXTERNAL (decl1) = current_extern_inline;
- DECL_INTERFACE_KNOWN (decl1) = 1;
- }
- else if (current_extern_inline)
- {
- /* `extern inline' acts like a declaration except for
- defining how to inline. So set DECL_EXTERNAL in that case. */
- DECL_EXTERNAL (decl1) = 1;
+ DECL_EXTERNAL (decl1) = 0;
+ DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
}
else
/* This is a definition, not a reference.
So clear DECL_EXTERNAL. */
DECL_EXTERNAL (decl1) = 0;
-
- if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1)
- || DECL_TEMPLATE_INSTANTIATION (decl1)))
- /* We know nothing yet */;
+
+ if (DECL_THIS_INLINE (decl1) && ! DECL_C_STATIC (decl1))
+ DECL_DEFER_OUTPUT (decl1) = 1;
else
{
DECL_INTERFACE_KNOWN (decl1) = 1;
- if (DECL_DECLARED_STATIC (decl1))
+ if (DECL_C_STATIC (decl1))
TREE_PUBLIC (decl1) = 0;
}
-
- DECL_DEFER_OUTPUT (decl1) = ! DECL_INTERFACE_KNOWN (decl1);
}
/* Record the decl so that the function name is defined.
expand_expr (build_function_call (lookup_name (get_identifier ("__gc_main"), 0), NULL_TREE),
0, VOIDmode, 0);
#if 0
- /* done at a differnet time */
+ /* done at a different time */
if (flag_rtti)
output_builtin_tdesc_entries ();
#endif
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 import_export_inline. */
- if (TREE_PUBLIC (fndecl))
- DECL_EXTERNAL (fndecl) = 1;
+ 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);
}
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
int returns_value;
int returns_null;
int warn_about_return_type;
- int extern_inline;
int assigns_this;
int just_assigned_this;
int parms_stored;
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;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
p->warn_about_return_type = warn_about_return_type;
- p->extern_inline = current_extern_inline;
p->binding_level = current_binding_level;
p->ctor_label = ctor_label;
p->dtor_label = dtor_label;
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. */
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
warn_about_return_type = p->warn_about_return_type;
- current_extern_inline = p->extern_inline;
current_binding_level = p->binding_level;
ctor_label = p->ctor_label;
dtor_label = p->dtor_label;
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);
}