parent
dd07092ebe
commit
c91a56d266
126
gcc/cp/ChangeLog
126
gcc/cp/ChangeLog
|
@ -1,10 +1,134 @@
|
|||
Fri Mar 29 09:41:02 1996 Jeffrey A. Law <law@cygnus.com
|
||||
Mon Apr 1 09:03:13 1996 Bob Manson <manson@charmed.cygnus.com>
|
||||
|
||||
* class.c (finish_struct_1): Propagate the TYPE_PACKED
|
||||
flag for the type to the type's fields.
|
||||
|
||||
Sat Mar 30 12:14:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
|
||||
|
||||
* parse.y (complex_parmlist, ELLIPSES): Take out ARM-based warning.
|
||||
|
||||
Fri Mar 29 15:51:36 1996 Bob Manson <manson@charmed.cygnus.com>
|
||||
|
||||
* class.c (base_info, finish_base_struct): Replace
|
||||
needs_virtual_dtor with base_has_virtual.
|
||||
|
||||
(finish_struct_1): Remove the old code that tried to make default
|
||||
destructors virtual. Use base_has_virtual when checking if we need
|
||||
to add a vtable entry for the rtti code.
|
||||
|
||||
Fri Mar 29 14:02:36 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* pt.c (push_template_decl): Complain about template decl with
|
||||
inappropriate declaration.
|
||||
|
||||
Fri Mar 29 12:15:35 1996 Bob Manson <manson@charmed.cygnus.com>
|
||||
|
||||
* typeck.c (build_x_unary_op): Remove bogus check for taking
|
||||
the address of a member function.
|
||||
|
||||
Fri Mar 29 11:56:02 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* parse.y (constructor_declarator): Only push the class if
|
||||
we are not already in the class.
|
||||
|
||||
Fri Mar 29 09:41:02 1996 Jeffrey A. Law <law@cygnus.com>
|
||||
|
||||
* method.c (emit_thunk): Remove current_call_is_indirect nonsense.
|
||||
Add additional argument to INIT_CUMULATIVE_ARGS.
|
||||
|
||||
Thu Mar 28 16:41:39 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* decl.c (shadow_tag): Fix error about anon union with methods.
|
||||
|
||||
* parse.y (self_reference): Only generate a self-reference if this
|
||||
is a non-template class.
|
||||
(opt.component_decl_list): Only use it if it was generated.
|
||||
|
||||
* parse.y (component_decl_1): Use constructor_declarator.
|
||||
(fn.def2): Ditto.
|
||||
(notype_component_declarator0): Ditto.
|
||||
|
||||
Thu Mar 28 15:11:35 1996 Bob Manson <manson@charmed.cygnus.com>
|
||||
|
||||
* typeck.c (build_x_unary_op): Add checks for taking the address
|
||||
of a TARGET_EXPR or of a member function, and give appropriate
|
||||
warnings.
|
||||
|
||||
Thu Mar 28 14:49:26 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* pt.c (process_template_parm): Allow template type parms to be
|
||||
used as types for template const parms.
|
||||
|
||||
Wed Mar 27 15:51:19 1996 Mike Stump <mrs@cygnus.com>
|
||||
|
||||
* init.c (expand_vec_init): Ensure the eh cleanups are on the
|
||||
function_obstack.
|
||||
|
||||
Wed Mar 27 10:14:30 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* decl.c (lookup_name_real): Be even more picky about the
|
||||
ambiguous lookup warning.
|
||||
(grokdeclarator): Tweak SCOPE_REF constructor declarators here.
|
||||
* parse.y (constructor_declarator): Rather than here.
|
||||
|
||||
* parse.y (constructor_declarator): New nonterminal.
|
||||
(fn.def1): Use it.
|
||||
(explicit_instantiation): Ditto.
|
||||
|
||||
Tue Mar 26 13:41:33 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
Add implicit declaration of class name at class scope.
|
||||
* decl.c (lookup_name_real): Restrict pedwarn about ambiguous lookup.
|
||||
* parse.y (self_reference): New nonterminal.
|
||||
(opt.component_decl_list): Use it.
|
||||
(fn.def1): Add nested_name_specifier type_name cases.
|
||||
* class.c (build_self_reference): New function.
|
||||
(finish_struct): Handle access_default later, move self-reference
|
||||
decl to the end.
|
||||
* pt.c (lookup_template_class): Handle getting a TYPE_DECL.
|
||||
* cp-tree.h: Adjust.
|
||||
|
||||
* pt.c (do_function_instantiation): Separate handling of member
|
||||
functions and non-member functions properly.
|
||||
|
||||
Mon Mar 25 14:23:22 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* pt.c (process_template_parm): Improve error for 'volatile class K'.
|
||||
|
||||
* class.c (finish_struct_1): Check the right slot for destructors.
|
||||
|
||||
* decl.c (start_enum): Complain about enum templates.
|
||||
|
||||
Mon Mar 25 13:25:31 1996 Mike Stump <mrs@cygnus.com>
|
||||
|
||||
* init.c (resolve_offset_ref): Offset pointers to member data by one.
|
||||
* typeck.c (unary_complex_lvalue): Ditto.
|
||||
|
||||
Mon Mar 25 13:30:42 1996 Bob Manson <manson@charmed.cygnus.com>
|
||||
|
||||
* typeck.c (c_expand_return): Check for a returned local
|
||||
array name, similar to the check for an ADDR_EXPR.
|
||||
|
||||
Mon Mar 25 13:07:19 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* decl.c (cp_finish_decl): Don't build cleanups for static
|
||||
variables here.
|
||||
|
||||
Fri Mar 22 17:57:55 1996 Mike Stump <mrs@cygnus.com>
|
||||
|
||||
* typeck.c (build_modify_expr): Fix error messages to be more
|
||||
accurate.
|
||||
* cp-tree.h (assop_as_string): Parallel to op_as_string, but for
|
||||
assignment operators.
|
||||
* error.c (assop_as_string): Ditto. Add support for `%Q' for
|
||||
assignment operators.
|
||||
|
||||
Fri Mar 22 13:48:29 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* decl.c (grokdeclarator): Call bad_specifiers for typedefs. Also
|
||||
give an error if initialized. Pedwarn about nested type with the
|
||||
same name as its enclosing class.
|
||||
|
||||
* pt.c (tsubst, case TYPE_DECL): Set DECL_CONTEXT.
|
||||
|
||||
* typeck.c (require_complete_type): Be sure to instantiate the
|
||||
|
|
|
@ -1384,7 +1384,7 @@ struct base_info
|
|||
char cant_synth_copy_ctor;
|
||||
char cant_synth_asn_ref;
|
||||
char no_const_asn_ref;
|
||||
char needs_virtual_dtor;
|
||||
char base_has_virtual;
|
||||
};
|
||||
|
||||
/* Record information about type T derived from its base classes.
|
||||
|
@ -1520,9 +1520,8 @@ finish_base_struct (t, b, t_binfo)
|
|||
|
||||
if (TYPE_VIRTUAL_P (basetype))
|
||||
{
|
||||
/* If there's going to be a destructor needed, make
|
||||
sure it will be virtual. */
|
||||
b->needs_virtual_dtor = 1;
|
||||
/* Remember that the baseclass has virtual members. */
|
||||
b->base_has_virtual = 1;
|
||||
|
||||
/* Don't borrow virtuals from virtual baseclasses. */
|
||||
if (TREE_VIA_VIRTUAL (base_binfo))
|
||||
|
@ -2973,7 +2972,7 @@ finish_struct_1 (t, attributes, warn_anon)
|
|||
tree fields = TYPE_FIELDS (t);
|
||||
tree fn_fields = TYPE_METHODS (t);
|
||||
tree x, last_x, method_vec;
|
||||
int needs_virtual_dtor;
|
||||
int base_has_virtual;
|
||||
int all_virtual;
|
||||
int has_virtual;
|
||||
int max_has_virtual;
|
||||
|
@ -3083,7 +3082,7 @@ finish_struct_1 (t, attributes, warn_anon)
|
|||
cant_synth_copy_ctor = base_info.cant_synth_copy_ctor;
|
||||
cant_synth_asn_ref = base_info.cant_synth_asn_ref;
|
||||
no_const_asn_ref = base_info.no_const_asn_ref;
|
||||
needs_virtual_dtor = base_info.needs_virtual_dtor;
|
||||
base_has_virtual = base_info.base_has_virtual;
|
||||
n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo));
|
||||
aggregate = 0;
|
||||
}
|
||||
|
@ -3100,7 +3099,7 @@ finish_struct_1 (t, attributes, warn_anon)
|
|||
cant_synth_copy_ctor = 0;
|
||||
cant_synth_asn_ref = 0;
|
||||
no_const_asn_ref = 0;
|
||||
needs_virtual_dtor = 0;
|
||||
base_has_virtual = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -3172,6 +3171,9 @@ finish_struct_1 (t, attributes, warn_anon)
|
|||
{
|
||||
GNU_xref_member (current_class_name, x);
|
||||
|
||||
if (TREE_CODE (x) == FIELD_DECL)
|
||||
DECL_PACKED (x) |= TYPE_PACKED (t);
|
||||
|
||||
/* Handle access declarations. */
|
||||
if (TREE_CODE (x) == USING_DECL)
|
||||
{
|
||||
|
@ -3537,7 +3539,7 @@ finish_struct_1 (t, attributes, warn_anon)
|
|||
&& !IS_SIGNATURE (t))
|
||||
{
|
||||
/* Here we must cons up a destructor on the fly. */
|
||||
tree dtor = cons_up_default_function (t, name, needs_virtual_dtor != 0);
|
||||
tree dtor = cons_up_default_function (t, name, 0);
|
||||
check_for_override (dtor, t);
|
||||
|
||||
/* If we couldn't make it work, then pretend we didn't need it. */
|
||||
|
@ -3550,11 +3552,6 @@ finish_struct_1 (t, attributes, warn_anon)
|
|||
TREE_CHAIN (dtor) = fn_fields;
|
||||
fn_fields = dtor;
|
||||
|
||||
if (DECL_VINDEX (dtor) == NULL_TREE
|
||||
&& (needs_virtual_dtor
|
||||
|| pending_virtuals != NULL_TREE
|
||||
|| pending_hard_virtuals != NULL_TREE))
|
||||
DECL_VINDEX (dtor) = error_mark_node;
|
||||
if (DECL_VINDEX (dtor))
|
||||
pending_virtuals = add_virtual_function (pending_virtuals,
|
||||
&has_virtual, dtor, t);
|
||||
|
@ -3563,7 +3560,7 @@ finish_struct_1 (t, attributes, warn_anon)
|
|||
}
|
||||
|
||||
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
|
||||
if (flag_rtti && (max_has_virtual > 0 || needs_virtual_dtor) &&
|
||||
if (flag_rtti && (max_has_virtual > 0 || base_has_virtual) &&
|
||||
has_virtual == 0)
|
||||
has_virtual = 1;
|
||||
|
||||
|
@ -4132,7 +4129,7 @@ finish_struct_1 (t, attributes, warn_anon)
|
|||
TYPE_NONCOPIED_PARTS (t) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield);
|
||||
|
||||
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
|
||||
&& DECL_VINDEX (TREE_VEC_ELT (method_vec, 0)) == NULL_TREE)
|
||||
&& DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)
|
||||
cp_warning ("`%#T' has virtual functions but non-virtual destructor",
|
||||
t);
|
||||
}
|
||||
|
@ -4212,6 +4209,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
|
|||
tree name = TYPE_NAME (t);
|
||||
tree x, last_x = NULL_TREE;
|
||||
tree access;
|
||||
tree dummy = NULL_TREE;
|
||||
|
||||
if (TREE_CODE (name) == TYPE_DECL)
|
||||
{
|
||||
|
@ -4233,25 +4231,33 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
|
|||
if (IS_SIGNATURE (t))
|
||||
append_signature_fields (list_of_fieldlists);
|
||||
|
||||
/* Move our self-reference declaration to the end of the field list so
|
||||
any real field with the same name takes precedence. */
|
||||
if (list_of_fieldlists
|
||||
&& TREE_VALUE (list_of_fieldlists)
|
||||
&& DECL_ARTIFICIAL (TREE_VALUE (list_of_fieldlists)))
|
||||
{
|
||||
dummy = TREE_VALUE (list_of_fieldlists);
|
||||
list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
|
||||
}
|
||||
|
||||
if (last_x && list_of_fieldlists)
|
||||
TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
|
||||
|
||||
/* For signatures, we made all methods `public' in the parser and
|
||||
reported an error if a access specifier was used. */
|
||||
if (CLASSTYPE_DECLARED_CLASS (t) == 0)
|
||||
{
|
||||
if (list_of_fieldlists
|
||||
&& TREE_PURPOSE (list_of_fieldlists) == access_default_node)
|
||||
TREE_PURPOSE (list_of_fieldlists) = access_public_node;
|
||||
}
|
||||
else if (list_of_fieldlists
|
||||
&& TREE_PURPOSE (list_of_fieldlists) == access_default_node)
|
||||
TREE_PURPOSE (list_of_fieldlists) = access_private_node;
|
||||
|
||||
while (list_of_fieldlists)
|
||||
{
|
||||
access = TREE_PURPOSE (list_of_fieldlists);
|
||||
|
||||
/* For signatures, we made all methods `public' in the parser and
|
||||
reported an error if a access specifier was used. */
|
||||
if (access == access_default_node)
|
||||
{
|
||||
if (CLASSTYPE_DECLARED_CLASS (t) == 0)
|
||||
access = access_public_node;
|
||||
else
|
||||
access = access_private_node;
|
||||
}
|
||||
|
||||
for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x))
|
||||
{
|
||||
TREE_PRIVATE (x) = access == access_private_node;
|
||||
|
@ -4298,16 +4304,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
|
|||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Handle access declarations. */
|
||||
if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF)
|
||||
{
|
||||
tree n = DECL_NAME (x);
|
||||
x = build_decl
|
||||
(USING_DECL, DECL_NAME (TREE_OPERAND (n, 1)), TREE_TYPE (x));
|
||||
DECL_RESULT (x) = n;
|
||||
}
|
||||
#endif
|
||||
if (TREE_CODE (x) != TYPE_DECL)
|
||||
DECL_FIELD_CONTEXT (x) = t;
|
||||
|
||||
|
@ -4330,7 +4326,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
|
|||
|
||||
/* Now add the tags, if any, to the list of TYPE_DECLs
|
||||
defined for this type. */
|
||||
if (CLASSTYPE_TAGS (t))
|
||||
if (CLASSTYPE_TAGS (t) || dummy)
|
||||
{
|
||||
x = CLASSTYPE_TAGS (t);
|
||||
while (x)
|
||||
|
@ -4350,6 +4346,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
|
|||
x = TREE_CHAIN (x);
|
||||
last_x = chainon (last_x, tag);
|
||||
}
|
||||
if (dummy)
|
||||
last_x = chainon (last_x, dummy);
|
||||
if (fields == NULL_TREE)
|
||||
fields = last_x;
|
||||
CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
|
||||
|
@ -5298,6 +5296,7 @@ print_class_statistics ()
|
|||
decls that may be cached in the previous_class_values list. For now, let's
|
||||
use the permanent obstack, later we may create a dedicated obstack just
|
||||
for this purpose. The effect is undone by pop_obstacks. */
|
||||
|
||||
void
|
||||
maybe_push_cache_obstack ()
|
||||
{
|
||||
|
@ -5305,3 +5304,24 @@ maybe_push_cache_obstack ()
|
|||
if (current_class_depth == 1)
|
||||
current_obstack = &permanent_obstack;
|
||||
}
|
||||
|
||||
/* Build a dummy reference to ourselves so Derived::Base (and A::A) works,
|
||||
according to [class]:
|
||||
The class-name is also inserted
|
||||
into the scope of the class itself. For purposes of access checking,
|
||||
the inserted class name is treated as if it were a public member name. */
|
||||
|
||||
tree
|
||||
build_self_reference ()
|
||||
{
|
||||
tree name = constructor_name (current_class_type);
|
||||
tree value = build_lang_decl (TYPE_DECL, name, current_class_type);
|
||||
DECL_NONLOCAL (value) = 1;
|
||||
DECL_CONTEXT (value) = current_class_type;
|
||||
DECL_CLASS_CONTEXT (value) = current_class_type;
|
||||
CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
|
||||
DECL_ARTIFICIAL (value) = 1;
|
||||
|
||||
pushdecl_class_level (value);
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -1967,6 +1967,7 @@ extern tree instantiate_type PROTO((tree, tree, int));
|
|||
extern void print_class_statistics PROTO((void));
|
||||
extern void maybe_push_cache_obstack PROTO((void));
|
||||
extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *));
|
||||
extern tree build_self_reference PROTO((void));
|
||||
|
||||
/* in cvt.c */
|
||||
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
|
||||
|
@ -2254,6 +2255,7 @@ extern char *code_as_string PROTO((enum tree_code, int));
|
|||
extern char *language_as_string PROTO((enum languages, int));
|
||||
extern char *parm_as_string PROTO((int, int));
|
||||
extern char *op_as_string PROTO((enum tree_code, int));
|
||||
extern char *assop_as_string PROTO((enum tree_code, int));
|
||||
extern char *cv_as_string PROTO((tree, int));
|
||||
|
||||
/* in method.c */
|
||||
|
@ -2290,7 +2292,6 @@ extern tree lookup_template_class PROTO((tree, tree, tree));
|
|||
extern int uses_template_parms PROTO((tree));
|
||||
extern tree instantiate_class_template PROTO((tree));
|
||||
extern tree instantiate_template PROTO((tree, tree *));
|
||||
extern void overload_template_name PROTO((tree));
|
||||
extern int type_unification PROTO((tree, tree *, tree, tree, int *, int));
|
||||
struct tinst_level *tinst_for_decl PROTO((void));
|
||||
extern void mark_decl_instantiated PROTO((tree, int));
|
||||
|
|
|
@ -4501,12 +4501,18 @@ lookup_name_real (name, prefer_type, nonclass)
|
|||
done:
|
||||
if (val)
|
||||
{
|
||||
/* This should only warn about types used in qualified-ids. */
|
||||
if (from_obj && from_obj != val)
|
||||
{
|
||||
cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%D')",
|
||||
name, got_object, from_obj);
|
||||
cp_pedwarn (" does not match lookup in the current scope (`%D')",
|
||||
val);
|
||||
if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL
|
||||
&& TREE_CODE (val) == TYPE_DECL
|
||||
&& TREE_TYPE (from_obj) != TREE_TYPE (val))
|
||||
{
|
||||
cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%#T')",
|
||||
name, got_object, TREE_TYPE (from_obj));
|
||||
cp_pedwarn (" does not match lookup in the current scope (`%#T')",
|
||||
TREE_TYPE (val));
|
||||
}
|
||||
}
|
||||
|
||||
if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
|
||||
|
@ -5700,14 +5706,15 @@ shadow_tag (declspecs)
|
|||
{
|
||||
/* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
|
||||
function members. */
|
||||
if (TYPE_METHODS (t))
|
||||
error ("an anonymous union cannot have function members");
|
||||
|
||||
if (TYPE_FIELDS (t))
|
||||
{
|
||||
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
|
||||
NULL_TREE, NULL_TREE);
|
||||
finish_anon_union (decl);
|
||||
}
|
||||
else
|
||||
error ("anonymous union cannot have a function member");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -6525,7 +6532,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
|
|||
cp_error ("storage size of `%D' isn't constant", decl);
|
||||
}
|
||||
|
||||
if (!DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type))
|
||||
if (! DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)
|
||||
/* Cleanups for static variables are handled by `finish_file'. */
|
||||
&& ! TREE_STATIC (decl))
|
||||
{
|
||||
int yes = suspend_momentary ();
|
||||
cleanup = maybe_build_cleanup (decl);
|
||||
|
@ -7676,8 +7685,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
|
|||
ctype = cname;
|
||||
}
|
||||
|
||||
if (ctype
|
||||
&& TREE_OPERAND (decl, 1) == constructor_name_full (ctype))
|
||||
if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
|
||||
&& ((DECL_NAME (TREE_OPERAND (decl, 1))
|
||||
== constructor_name_full (ctype))
|
||||
|| (DECL_NAME (TREE_OPERAND (decl, 1))
|
||||
== constructor_name (ctype))))
|
||||
TREE_OPERAND (decl, 1) = constructor_name (ctype);
|
||||
next = &TREE_OPERAND (decl, 1);
|
||||
decl = *next;
|
||||
|
@ -9030,6 +9042,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
|
|||
|
||||
if (decl_context == FIELD)
|
||||
{
|
||||
if (declarator == current_class_name)
|
||||
cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class",
|
||||
declarator);
|
||||
decl = build_lang_decl (TYPE_DECL, declarator, type);
|
||||
if (IS_SIGNATURE (current_class_type) && opaque_typedef)
|
||||
SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1;
|
||||
|
@ -9064,6 +9079,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
|
|||
error ("non-object member `%s' cannot be declared mutable", name);
|
||||
}
|
||||
|
||||
bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
|
||||
inlinep, friendp, raises != NULL_TREE);
|
||||
|
||||
if (initialized)
|
||||
error ("typedef declaration includes an initializer");
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
@ -10597,15 +10618,19 @@ start_enum (name)
|
|||
enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
|
||||
|
||||
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
|
||||
cp_error ("multiple definition of enum `%T'", enumtype);
|
||||
cp_error ("multiple definition of `%#T'", enumtype);
|
||||
else
|
||||
{
|
||||
enumtype = make_node (ENUMERAL_TYPE);
|
||||
pushtag (name, enumtype, 0);
|
||||
}
|
||||
|
||||
if (b->pseudo_global)
|
||||
cp_error ("template declaration of `%#T'", enumtype);
|
||||
|
||||
if (current_class_type)
|
||||
TREE_ADDRESSABLE (b->tags) = 1;
|
||||
|
||||
current_local_enum = NULL_TREE;
|
||||
|
||||
/* We copy this value because enumerated type constants
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef char* cp_printer ();
|
|||
#define L language_as_string
|
||||
#define O op_as_string
|
||||
#define P parm_as_string
|
||||
#define Q assop_as_string
|
||||
#define T type_as_string
|
||||
#define V cv_as_string
|
||||
|
||||
|
@ -46,7 +47,7 @@ cp_printer * cp_printers[256] =
|
|||
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
|
||||
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
|
||||
_, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */
|
||||
P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
|
||||
P, Q, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
|
||||
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
|
||||
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
|
||||
};
|
||||
|
@ -56,6 +57,7 @@ cp_printer * cp_printers[256] =
|
|||
#undef L
|
||||
#undef O
|
||||
#undef P
|
||||
#undef Q
|
||||
#undef T
|
||||
#undef V
|
||||
#undef _
|
||||
|
@ -1503,6 +1505,20 @@ op_as_string (p, v)
|
|||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
assop_as_string (p, v)
|
||||
enum tree_code p;
|
||||
int v;
|
||||
{
|
||||
static char buf[] = "operator ";
|
||||
|
||||
if (p == 0)
|
||||
return "{unknown}";
|
||||
|
||||
strcpy (buf + 9, assignop_tab [p]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
args_as_string (p, v)
|
||||
tree p;
|
||||
|
|
|
@ -2071,6 +2071,14 @@ resolve_offset_ref (exp)
|
|||
addr = convert_pointer_to (basetype, addr);
|
||||
member = convert (ptrdiff_type_node,
|
||||
build_unary_op (ADDR_EXPR, member, 0));
|
||||
|
||||
/* Pointer to data mebers are offset by one, so that a null
|
||||
pointer with a real value of 0 is distinguishable from an
|
||||
offset of the first member of a structure. */
|
||||
member = build_binary_op (MINUS_EXPR, member,
|
||||
convert (ptrdiff_type_node, integer_one_node),
|
||||
0);
|
||||
|
||||
return build1 (INDIRECT_REF, type,
|
||||
build (PLUS_EXPR, build_pointer_type (type),
|
||||
addr, member));
|
||||
|
@ -3399,13 +3407,31 @@ expand_vec_init (decl, base, maxindex, init, from_array)
|
|||
use_variable (DECL_RTL (base2));
|
||||
}
|
||||
expand_end_loop ();
|
||||
if (TYPE_NEEDS_DESTRUCTOR (type))
|
||||
end_protect (build_array_eh_cleanup (rval,
|
||||
build_binary_op (MINUS_EXPR,
|
||||
maxindex,
|
||||
iterator,
|
||||
1),
|
||||
type));
|
||||
if (TYPE_NEEDS_DESTRUCTOR (type) && flag_handle_exceptions)
|
||||
{
|
||||
/* We have to ensure that this can live to the cleanup
|
||||
expansion time, since we know it is only ever needed
|
||||
once, generate code now. */
|
||||
push_obstacks_nochange ();
|
||||
resume_temporary_allocation ();
|
||||
{
|
||||
tree e1, e2 = make_node (RTL_EXPR);
|
||||
TREE_TYPE (e2) = void_type_node;
|
||||
RTL_EXPR_RTL (e2) = const0_rtx;
|
||||
TREE_SIDE_EFFECTS (e2) = 1;
|
||||
start_sequence_for_rtl_expr (e2);
|
||||
|
||||
e1 = build_array_eh_cleanup
|
||||
(rval,
|
||||
build_binary_op (MINUS_EXPR, maxindex, iterator, 1),
|
||||
type);
|
||||
expand_expr (e1, const0_rtx, VOIDmode, 0);
|
||||
RTL_EXPR_SEQUENCE (e2) = get_insns ();
|
||||
end_sequence ();
|
||||
end_protect (e2);
|
||||
}
|
||||
pop_obstacks ();
|
||||
}
|
||||
expand_end_cond ();
|
||||
if (obey_regdecls)
|
||||
use_variable (DECL_RTL (iterator));
|
||||
|
|
112
gcc/cp/parse.y
112
gcc/cp/parse.y
|
@ -210,7 +210,7 @@ empty_parms ()
|
|||
|
||||
%type <ttype> structsp opt.component_decl_list component_decl_list
|
||||
%type <ttype> component_decl component_decl_1 components notype_components
|
||||
%type <ttype> component_declarator component_declarator0
|
||||
%type <ttype> component_declarator component_declarator0 self_reference
|
||||
%type <ttype> notype_component_declarator notype_component_declarator0
|
||||
%type <ttype> after_type_component_declarator after_type_component_declarator0
|
||||
%type <ttype> enumlist enumerator
|
||||
|
@ -231,7 +231,7 @@ empty_parms ()
|
|||
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
|
||||
%token <ttype> PRE_PARSED_CLASS_DECL
|
||||
%type <ttype> fn.def1 /* Not really! */
|
||||
%type <ttype> fn.def2 return_id fn.defpen
|
||||
%type <ttype> fn.def2 return_id fn.defpen constructor_declarator
|
||||
%type <itype> ctor_initializer_opt
|
||||
%type <ttype> named_class_head named_class_head_sans_basetype
|
||||
%type <ttype> named_complex_class_head_sans_basetype
|
||||
|
@ -551,6 +551,51 @@ fndef:
|
|||
{}
|
||||
;
|
||||
|
||||
constructor_declarator:
|
||||
nested_name_specifier type_name '('
|
||||
{
|
||||
$$ = build_parse_node (SCOPE_REF, $1, $2);
|
||||
if ($1 != current_class_type)
|
||||
{
|
||||
push_nested_class ($1, 3);
|
||||
TREE_COMPLEXITY ($$) = current_class_depth;
|
||||
}
|
||||
}
|
||||
parmlist ')' type_quals
|
||||
{ $$ = build_parse_node (CALL_EXPR, $<ttype>4, $5, $7); }
|
||||
| nested_name_specifier type_name LEFT_RIGHT type_quals
|
||||
{
|
||||
$$ = build_parse_node (SCOPE_REF, $1, $2);
|
||||
if ($1 != current_class_type)
|
||||
{
|
||||
push_nested_class ($1, 3);
|
||||
TREE_COMPLEXITY ($$) = current_class_depth;
|
||||
}
|
||||
$$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $4);
|
||||
}
|
||||
| global_scope nested_name_specifier type_name '('
|
||||
{
|
||||
$$ = build_parse_node (SCOPE_REF, $2, $3);
|
||||
if ($2 != current_class_type)
|
||||
{
|
||||
push_nested_class ($2, 3);
|
||||
TREE_COMPLEXITY ($$) = current_class_depth;
|
||||
}
|
||||
}
|
||||
parmlist ')' type_quals
|
||||
{ $$ = build_parse_node (CALL_EXPR, $<ttype>5, $6, $8); }
|
||||
| global_scope nested_name_specifier type_name LEFT_RIGHT type_quals
|
||||
{
|
||||
$$ = build_parse_node (SCOPE_REF, $2, $3);
|
||||
if ($2 != current_class_type)
|
||||
{
|
||||
push_nested_class ($2, 3);
|
||||
TREE_COMPLEXITY ($$) = current_class_depth;
|
||||
}
|
||||
$$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $5);
|
||||
}
|
||||
;
|
||||
|
||||
fn.def1:
|
||||
typed_declspecs declarator exception_specification_opt
|
||||
{ tree specs, attrs;
|
||||
|
@ -571,6 +616,18 @@ fn.def1:
|
|||
YYERROR1;
|
||||
reinit_parse_for_function ();
|
||||
$$ = NULL_TREE; }
|
||||
| declmods constructor_declarator exception_specification_opt
|
||||
{ tree specs, attrs;
|
||||
split_specs_attrs ($1, &specs, &attrs);
|
||||
if (! start_function (specs, $2, $3, attrs, 0))
|
||||
YYERROR1;
|
||||
reinit_parse_for_function ();
|
||||
$$ = NULL_TREE; }
|
||||
| constructor_declarator exception_specification_opt
|
||||
{ if (! start_function (NULL_TREE, $$, $2, NULL_TREE, 0))
|
||||
YYERROR1;
|
||||
reinit_parse_for_function ();
|
||||
$$ = NULL_TREE; }
|
||||
;
|
||||
|
||||
/* more C++ complexity. See component_decl for a comment on the
|
||||
|
@ -578,13 +635,6 @@ fn.def1:
|
|||
fn.def2:
|
||||
typed_declspecs '(' parmlist ')' type_quals exception_specification_opt
|
||||
{ tree specs = strip_attrs ($1);
|
||||
if (TREE_VALUE (specs) == current_class_type)
|
||||
{
|
||||
if (TREE_CHAIN (specs) == NULL_TREE)
|
||||
specs = get_decl_list (current_class_name);
|
||||
else
|
||||
TREE_VALUE (specs) = current_class_name;
|
||||
}
|
||||
$$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5);
|
||||
$$ = start_method (TREE_CHAIN (specs), $$, $6);
|
||||
rest_of_mdef:
|
||||
|
@ -608,6 +658,11 @@ fn.def2:
|
|||
$$ = start_method (specs, $2, $3); goto rest_of_mdef; }
|
||||
| notype_declarator exception_specification_opt
|
||||
{ $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; }
|
||||
| declmods constructor_declarator exception_specification_opt
|
||||
{ tree specs = strip_attrs ($1);
|
||||
$$ = start_method (specs, $2, $3); goto rest_of_mdef; }
|
||||
| constructor_declarator exception_specification_opt
|
||||
{ $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; }
|
||||
;
|
||||
|
||||
return_id: RETURN IDENTIFIER
|
||||
|
@ -726,6 +781,8 @@ explicit_instantiation:
|
|||
do_function_instantiation (specs, $3, NULL_TREE); }
|
||||
| TEMPLATE notype_declarator
|
||||
{ do_function_instantiation (NULL_TREE, $2, NULL_TREE); }
|
||||
| TEMPLATE constructor_declarator
|
||||
{ do_function_instantiation (NULL_TREE, $2, NULL_TREE); }
|
||||
| SCSPEC TEMPLATE aggr template_type
|
||||
{ do_type_instantiation ($4, $1); }
|
||||
| SCSPEC TEMPLATE typed_declspecs declarator
|
||||
|
@ -733,6 +790,8 @@ explicit_instantiation:
|
|||
do_function_instantiation (specs, $4, $1); }
|
||||
| SCSPEC TEMPLATE notype_declarator
|
||||
{ do_function_instantiation (NULL_TREE, $3, $1); }
|
||||
| SCSPEC TEMPLATE constructor_declarator
|
||||
{ do_function_instantiation (NULL_TREE, $3, $1); }
|
||||
;
|
||||
|
||||
/* The TYPENAME expansions are to deal with use of a template class name as
|
||||
|
@ -2408,15 +2467,26 @@ left_curly: '{'
|
|||
}
|
||||
;
|
||||
|
||||
self_reference:
|
||||
/* empty */
|
||||
{
|
||||
if (CLASSTYPE_TEMPLATE_INFO (current_class_type))
|
||||
$$ = NULL_TREE;
|
||||
else
|
||||
$$ = build_self_reference ();
|
||||
}
|
||||
;
|
||||
|
||||
opt.component_decl_list:
|
||||
/* empty */
|
||||
{ $$ = NULL_TREE; }
|
||||
| component_decl_list
|
||||
self_reference
|
||||
{ if ($$) $$ = build_tree_list (access_public_node, $$); }
|
||||
| self_reference component_decl_list
|
||||
{
|
||||
if (current_aggr == signature_type_node)
|
||||
$$ = build_tree_list (access_public_node, $$);
|
||||
$$ = build_tree_list (access_public_node, $2);
|
||||
else
|
||||
$$ = build_tree_list (access_default_node, $$);
|
||||
$$ = build_tree_list (access_default_node, $2);
|
||||
if ($1) $$ = tree_cons (access_public_node, $1, $$);
|
||||
}
|
||||
| opt.component_decl_list VISSPEC ':' component_decl_list
|
||||
{
|
||||
|
@ -2488,6 +2558,9 @@ component_decl_1:
|
|||
| notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
|
||||
{ $$ = grokfield ($$, NULL_TREE, $2, $5, $3,
|
||||
build_tree_list ($4, NULL_TREE)); }
|
||||
| constructor_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
|
||||
{ $$ = grokfield ($$, NULL_TREE, $2, $5, $3,
|
||||
build_tree_list ($4, NULL_TREE)); }
|
||||
| ':' expr_no_commas
|
||||
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
|
||||
| error
|
||||
|
@ -2597,6 +2670,12 @@ notype_component_declarator0:
|
|||
$<ttype>0 = current_declspecs;
|
||||
$$ = grokfield ($$, current_declspecs, $2, $5, $3,
|
||||
build_tree_list ($4, prefix_attributes)); }
|
||||
| constructor_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
|
||||
{ split_specs_attrs ($<ttype>0, ¤t_declspecs,
|
||||
&prefix_attributes);
|
||||
$<ttype>0 = current_declspecs;
|
||||
$$ = grokfield ($$, current_declspecs, $2, $5, $3,
|
||||
build_tree_list ($4, prefix_attributes)); }
|
||||
| IDENTIFIER ':' expr_no_commas maybe_attribute
|
||||
{ split_specs_attrs ($<ttype>0, ¤t_declspecs,
|
||||
&prefix_attributes);
|
||||
|
@ -2781,7 +2860,7 @@ direct_after_type_declarator:
|
|||
| '(' after_type_declarator ')'
|
||||
{ $$ = $2; }
|
||||
| nested_name_specifier type_name %prec EMPTY
|
||||
{ push_nested_class (TREE_TYPE ($$), 3);
|
||||
{ push_nested_class ($1, 3);
|
||||
$$ = build_parse_node (SCOPE_REF, $$, $2);
|
||||
TREE_COMPLEXITY ($$) = current_class_depth; }
|
||||
| type_name %prec EMPTY
|
||||
|
@ -3694,9 +3773,6 @@ complex_parmlist:
|
|||
}
|
||||
| ELLIPSIS
|
||||
{
|
||||
/* ARM $8.2.5 has this as a boxed-off comment. */
|
||||
if (pedantic)
|
||||
warning ("use of `...' without a first argument is non-portable");
|
||||
$$ = NULL_TREE;
|
||||
}
|
||||
| TYPENAME_ELLIPSIS
|
||||
|
|
38
gcc/cp/pt.c
38
gcc/cp/pt.c
|
@ -114,9 +114,13 @@ process_template_parm (list, next)
|
|||
PARM, 0, NULL_TREE, NULL_TREE);
|
||||
/* A template parameter is not modifiable. */
|
||||
TREE_READONLY (parm) = 1;
|
||||
if (IS_AGGR_TYPE (TREE_TYPE (parm)))
|
||||
if (IS_AGGR_TYPE (TREE_TYPE (parm))
|
||||
&& TREE_CODE (TREE_TYPE (parm)) != TEMPLATE_TYPE_PARM)
|
||||
{
|
||||
sorry ("aggregate template parameter types");
|
||||
cp_error ("`%#T' is not a valid type for a template constant parameter",
|
||||
TREE_TYPE (parm));
|
||||
if (DECL_NAME (parm) == NULL_TREE)
|
||||
error (" a template type parameter must begin with `class' or `typename'");
|
||||
TREE_TYPE (parm) = void_type_node;
|
||||
}
|
||||
tinfo = make_node (TEMPLATE_CONST_PARM);
|
||||
|
@ -235,8 +239,10 @@ push_template_decl (decl)
|
|||
if (TREE_CODE (decl) == TYPE_DECL)
|
||||
tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
|
||||
else if (! DECL_TEMPLATE_INFO (decl))
|
||||
/* A member definition that doesn't match anything in the class. */
|
||||
return;
|
||||
{
|
||||
cp_error ("template definition of non-template `%#D'", decl);
|
||||
return;
|
||||
}
|
||||
else
|
||||
tmpl = DECL_TI_TEMPLATE (decl);
|
||||
}
|
||||
|
@ -609,6 +615,11 @@ lookup_template_class (d1, arglist, in_decl)
|
|||
if (! template)
|
||||
template = IDENTIFIER_CLASS_VALUE (d1);
|
||||
}
|
||||
else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
|
||||
{
|
||||
template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
|
||||
d1 = DECL_NAME (template);
|
||||
}
|
||||
else if (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' && IS_AGGR_TYPE (d1))
|
||||
{
|
||||
template = CLASSTYPE_TI_TEMPLATE (d1);
|
||||
|
@ -2728,12 +2739,15 @@ do_function_instantiation (declspecs, declarator, storage)
|
|||
}
|
||||
|
||||
/* If we've already seen this template instance, use it. */
|
||||
if (name = DECL_ASSEMBLER_NAME (decl),
|
||||
fn = IDENTIFIER_GLOBAL_VALUE (name),
|
||||
fn && DECL_TEMPLATE_INSTANTIATION (fn))
|
||||
result = fn;
|
||||
else if (fn && DECL_CONTEXT (fn))
|
||||
;
|
||||
if (DECL_FUNCTION_MEMBER_P (decl))
|
||||
{
|
||||
if (DECL_TEMPLATE_INSTANTIATION (decl))
|
||||
result = decl;
|
||||
else if (name = DECL_ASSEMBLER_NAME (decl),
|
||||
fn = IDENTIFIER_GLOBAL_VALUE (name),
|
||||
fn && DECL_TEMPLATE_INSTANTIATION (fn))
|
||||
result = fn;
|
||||
}
|
||||
else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
|
||||
{
|
||||
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
|
||||
|
@ -2779,10 +2793,10 @@ do_function_instantiation (declspecs, declarator, storage)
|
|||
cp_error ("storage class `%D' applied to template instantiation",
|
||||
storage);
|
||||
|
||||
if (! extern_p)
|
||||
instantiate_decl (result);
|
||||
mark_decl_instantiated (result, extern_p);
|
||||
repo_template_instantiated (result, extern_p);
|
||||
if (! extern_p)
|
||||
instantiate_decl (result);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -3999,6 +3999,13 @@ build_x_unary_op (code, xarg)
|
|||
return build_opfncall (code, LOOKUP_NORMAL, xarg,
|
||||
NULL_TREE, NULL_TREE);
|
||||
}
|
||||
|
||||
if (code == ADDR_EXPR)
|
||||
{
|
||||
if (TREE_CODE (xarg) == TARGET_EXPR)
|
||||
warning ("taking address of temporary");
|
||||
}
|
||||
|
||||
return build_unary_op (code, xarg, 0);
|
||||
}
|
||||
|
||||
|
@ -4499,17 +4506,30 @@ unary_complex_lvalue (code, arg)
|
|||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Add in the offset to the right subobject. */
|
||||
offset = get_delta_difference (DECL_FIELD_CONTEXT (t),
|
||||
TREE_TYPE (TREE_OPERAND (arg, 0)),
|
||||
0);
|
||||
|
||||
/* Add in the offset to the field. */
|
||||
offset = size_binop (PLUS_EXPR, offset,
|
||||
size_binop (EASY_DIV_EXPR,
|
||||
DECL_FIELD_BITPOS (t),
|
||||
size_int (BITS_PER_UNIT)));
|
||||
|
||||
/* We offset all pointer to data memebers by 1 so that we can
|
||||
distinguish between a null pointer to data member and the first
|
||||
data member of a structure. */
|
||||
offset = size_binop (PLUS_EXPR, offset, size_int (1));
|
||||
|
||||
return convert (build_pointer_type (TREE_TYPE (arg)), offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* This seems to be obsolete now (and posssibly wrong, compare with
|
||||
resolve_offset_ref). */
|
||||
if (TREE_CODE (arg) == OFFSET_REF)
|
||||
{
|
||||
tree left = TREE_OPERAND (arg, 0), left_addr;
|
||||
|
@ -4530,6 +4550,7 @@ unary_complex_lvalue (code, arg)
|
|||
build1 (NOP_EXPR, integer_type_node, left_addr),
|
||||
build1 (NOP_EXPR, integer_type_node, right_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We permit compiler to make function calls returning
|
||||
objects of aggregate type look like lvalues. */
|
||||
|
@ -5558,7 +5579,7 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||
}
|
||||
else
|
||||
{
|
||||
cp_error ("no match for `%O(%#T, %#T)'", modifycode,
|
||||
cp_error ("no match for `%Q(%#T, %#T)'", modifycode,
|
||||
TREE_TYPE (lhs), TREE_TYPE (rhs));
|
||||
return error_mark_node;
|
||||
}
|
||||
|
@ -5567,6 +5588,12 @@ build_modify_expr (lhs, modifycode, rhs)
|
|||
{
|
||||
lhs = stabilize_reference (lhs);
|
||||
newrhs = build_binary_op (modifycode, lhs, rhs, 1);
|
||||
if (newrhs == error_mark_node)
|
||||
{
|
||||
cp_error (" in evaluation of `%Q(%#T, %#T)'", modifycode,
|
||||
TREE_TYPE (lhs), TREE_TYPE (rhs));
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle a cast used as an "lvalue".
|
||||
|
@ -6977,6 +7004,15 @@ c_expand_return (retval)
|
|||
&& !TREE_PUBLIC (whats_returned))
|
||||
cp_warning_at ("address of local variable `%D' returned", whats_returned);
|
||||
}
|
||||
else if (TREE_CODE (retval) == VAR_DECL)
|
||||
{
|
||||
if (TREE_CODE (TREE_TYPE (retval)) == ARRAY_TYPE
|
||||
&& DECL_NAME (retval)
|
||||
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (retval))
|
||||
&& !TREE_STATIC (retval)
|
||||
&& !TREE_PUBLIC (retval))
|
||||
cp_warning_at ("address of local array `%D' returned", retval);
|
||||
}
|
||||
|
||||
/* Now deal with possible C++ hair:
|
||||
(1) Compute the return value.
|
||||
|
|
Loading…
Reference in New Issue