-Tue May 3 19:11:24 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu May 5 09:35:35 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * typeck.c (build_modify_expr): Warn about assignment to `this'.
+
+Wed May 4 15:55:49 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * init.c (build_delete): Use the global operator delete when
+ requested.
+
+ * decl.c (lookup_name_real): If we find the type we're looking in a
+ base class while defining a class, set IDENTIFIER_CLASS_VALUE for
+ the type.
+
+ * class.c (finish_struct): Remove a couple of dependencies on
+ language linkage.
+
+ * decl.c (pushtag): Classes do nest in extern "C" blocks.
+ (pushdecl): Only set DECL_NESTED_TYPENAME on the canonical one for
+ the type.
+ (pushtag): Remove another dependency on the language linkage.
+
+ * lex.c (cons_up_default_function): Don't set DECL_CLASS_CONTEXT to
+ a const-qualified type.
+
+ * decl.c (push_overloaded_decl): Throw away built-in decls here.
+ (duplicate_decls): Instead of here.
+
+Wed May 4 15:27:40 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * typeck.c (get_member_function_from_ptrfunc): Do The Right
+ Thing (I hope) if we're using thunks.
+
+Wed May 4 13:52:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * parse.y (specialization): aggr template_type_name ';'.
+ (named_class_head_sans_basetype): Use it.
+ (explicit_instantiation): Ditto.
+ (tmpl.2): Revert.
+
+ * cvt.c (build_type_conversion_1): Use convert_for_initialization,
+ rather than convert, to do conversions after the UDC.
+
+ * cp-tree.h (SHARED_MEMBER_P): This member is shared between all
+ instances of the class.
+
+ * search.c (lookup_field): If the entity found by two routes is the
+ same, it's not ambiguous.
+
+Wed May 4 12:10:00 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * decl.c (lookup_name_real): Check for a NULL TREE_VALUE,
+ to prevent the compiler from crashing ...
+
+Wed May 4 11:19:45 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * call.c (build_method_call): If we don't have an object, check
+ basetype_path to figure out where to look up the function.
+
+ * typeck.c (convert_for_initialization): Pass TYPE_BINFO (type) to
+ build_method_call in case exp is NULL_TREE.
+
+Tue May 3 16:02:53 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ Give a vtable entries a unique named type, for the sake of gdb.
+ * class.c (build_vtable_entry): The addres of a thunk now has
+ type vtable_entry_type, not ptr_type_node.
+ * method.c (make_thunk): Fix type of THUNK_DECL.
+ * class.c (add_virtual_function, override_one_vtable): Use
+ vfunc_ptr_type_node, instead of ptr_type_node.
+ * cp-tree.h (vfunc_ptr_type_node): New macro.
+ * decl.c (init_decl_processing): Make vtable_entry_type
+ be a unique type of pointer to a unique function type.
+
+Tue May 3 09:20:44 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * parse.y (do_explicit): Sets doing_explicit to 1.
+ (explicit_instantiation): Use do_explicit rather than TEMPLATE
+ directly, add "do_explicit error" rule.
+ (datadef): Set doing_explicit to 0 after an explicit instantiation.
+ (tmpl.2): Don't instantiate if we see a ';' unless we're doing an
+ explicit instantiation.
+ (named_class_head_sans_basetype): Remove aggr template_type_name
+ ';' again.
+
+Mon May 2 23:17:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * search.c (lookup_nested_tag): Lose.
+
+ * decl2.c (grokfield): Set DECL_CONTEXT on TYPE_DECLs.
+ (lookup_name_nonclass): Lose.
+
+ * decl.c (poplevel_class): Add force parameter.
+ (lookup_name_real): Fix handling of explicit scoping which specifies
+ a class currently being defined. Add 'nonclass' argument.
+ (lookup_name, lookup_name_nonclass): Shells for lookup_name_real.
+
+ * class.c (finish_struct): Don't unset IDENTIFIER_CLASS_VALUEs here.
+ (popclass): Force clearing of IDENTIFIER_CLASS_VALUEs if we're being
+ called from finish_struct.
+
+Mon May 2 19:06:21 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * decl.c (init_decl_processing), cp-tree.h: Removed memptr_type.
+ (It seeems redundant, given build_ptrmemfunc_type.)
+ * typeck.c (get_member_function_from_ptrfunc), gc.c (build_headof,
+ build_classof): Use vtable_entry_type instead of memptr_type.
+ * method.c (emit_thunk): Call poplevel with functionbody==0
+ to prevent DECL_INITIAL being set to a BLOCK.
+
+Mon May 2 15:02:11 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * parse.y (named_class_head_sans_basetype): Add "aggr
+ template_type_name ';'" rule for forward declaration of
+ specializations.
+
+Mon May 2 15:02:11 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * class.c (instantiate_type): Deal with pmf's.
* Make-lang.in (cc1plus): Don't depend on OBJS or BC_OBJS, since
stamp-objlist does.
+
* Makefile.in (../cc1plus): Depend on OBJDEPS.
(OBJDEPS): Dependency version of OBJS.
+Mon May 2 12:51:31 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * search.c (dfs_debug_mark): unmark TYPE_DECL_SUPPRESS_DEBUG, not
+ DECL_IGNORED_P.
+
+Fri Apr 29 12:29:56 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * class.c (finish_struct): Clear out memory of local tags. And
+ typedefs.
+
+ * decl2.c (grokclassfn): Don't set DECL_CONTEXT to a cv-qualified
+ type.
+ * search.c (get_matching_virtual): Be more helpful in error message.
+
+ * *: Use DECL_ARTIFICIAL (renamed from DECL_SYNTHESIZED).
+
+ * lex.c (default_assign_ref_body): Expect TYPE_NESTED_NAME to work.
+ (default_copy_constructor_body): Ditto.
+
+ * class.c (finish_struct): Don't gratuitously create multiple decls
+ for nested classes.
+
+Thu Apr 28 23:39:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ Avoid clobbering the arg types of other functions when reverting
+ static member functions.
+ * decl.c (revert_static_member_fn): Rearrange arguments, don't
+ require values for 'fn' and 'argtypes', add warning to comment
+ above.
+ (decls_match): Rearrange arguments in call to rsmf.
+ (grok_op_properties): Don't pass values for fn and argtypes.
+ * pt.c (instantiate_template): Don't pass values for fn and argtypes.
+
Thu Apr 28 16:29:11 1994 Doug Evans (dje@canuck.cygnus.com)
* Make-lang.in (cc1plus): Depend on stamp-objlist.
* Makefile.in (BC_OBJS): Delete.
- (OBJS): Cat ../stamp-objlist to get everything, except ../c-common.o.
+ (OBJS): Cat ../stamp-objlist to get language independent files.
+ Include ../c-common.o.
(../cc1plus): Delete reference to BC_OBJS.
+Thu Apr 28 02:12:08 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * search.c (compute_access): No really, deal with static members
+ properly. Would I lie to you?
+
+ Implement lexical hiding of function declarations.
+ * pt.c (tsubst): Use lookup_name to look for function decls to guide
+ instantiation.
+ * method.c (build_opfncall): Use lookup_name_nonclass to look for
+ non-member functions.
+ * init.c (do_friend): Use lookup_name_nonclass to look for
+ functions.
+ * error.c (ident_fndecl): Use lookup_name to look for functions.
+ * decl2.c (lookup_name_nonclass): New function, skips over
+ CLASS_VALUE.
+ * decl.c (struct binding_level): Lose overloads_shadowed field.
+ (poplevel): Don't deal with overloads_shadowed.
+ (push_overloaded_decl): Do lexical hiding for functions.
+ * class.c (instantiate_type): Don't check non-members if we have
+ members with the same name.
+ * call.c (build_method_call): Use lookup_name_nonclass instead of
+ IDENTIFIER_GLOBAL_VALUE to check for non-member functions.
+ (build_overload_call_real): Ditto.
+
+ * decl.c (duplicate_decls): Check for ambiguous overloads here.
+ (push_overloaded_decl): Instead of here.
+
+ * decl.c (pushdecl): Back out Chip's last change.
+
+ * decl.c (grok_op_properties): operators cannot be static members.
+
+ * cp-tree.h (DECL_SYNTHESIZED): DECL_SOURCE_LINE == 0
+ (SET_DECL_SYNTHESIZED): DECL_SOURCE_LINE = 0
+ * lex.c (cons_up_default_function): Use SET_DECL_SYNTHESIZED.
+
+ * method.c (do_inline_function_hair): Don't put friends of local
+ classes into global scope, either.
+
+ * typeck2.c (build_functional_cast): Don't look for a function call
+ interpretation.
+
Thu Apr 28 15:19:46 1994 Mike Stump (mrs@cygnus.com)
* cp-tree.h: disable use of backend EH.
(*.o): Use complete pathname to headers in parent dir.
(doc, info, dvi): Delete.
+Sun Apr 24 16:52:51 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * Make-lang.in (c++.install-common): Check for g++-cross.
+ * Makefile.in: Remove Cygnus cruft.
+ (config.status): Delete.
+ (RTL_H): Define.
+ (TREE_H): Use complete pathname, some native makes have minimal
+ VPATH support.
+ (*.o): Use complete pathname to headers in parent dir.
+ (doc, info, dvi): Delete.
+
Sun Apr 24 00:47:49 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (pushdecl): Avoid redundant warning on redeclaring function
* Language directory reorganization.
See parent makefile.
+Fri Apr 22 03:27:26 1994 Doug Evans (dje@cygnus.com)
+
+ * Language directory reorganization.
+ See parent makefile.
+
Thu Apr 21 18:27:57 1994 Per Bothner (bothner@kalessin.cygnus.com)
* cp-tree.h (THUNK_DELTA): It is normally negative, so
if (basetype != NULL_TREE)
;
/* call to a constructor... */
+ else if (basetype_path)
+ basetype = BINFO_TYPE (basetype_path);
else if (IDENTIFIER_HAS_TYPE_VALUE (name))
{
basetype = IDENTIFIER_TYPE_VALUE (name);
}
if (pass == 0)
{
- tree igv = IDENTIFIER_GLOBAL_VALUE (name);
+ tree igv = lookup_name_nonclass (name);
/* No exact match could be found. Now try to find match
using default conversions. */
goto found_and_maybe_warn;
}
- if ((flags & ~LOOKUP_GLOBAL) & (LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY))
+ if (flags & (LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY))
{
if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
== LOOKUP_SPECULATIVELY)
if (! flag_ansi_overloading)
{
+ tree fn;
+
/* This is a speed improvement that ends up not working properly in
the situation of fns with and without default parameters. I turned
this off in the new method so it'll go through the argument matching
code to properly diagnose a match/failure. (bpk) */
overload_name = build_decl_overload (fnname, parmtypes, 0);
+ fn = lookup_name_nonclass (overload_name);
/* Now check to see whether or not we can win.
Note that if we are called from `build_method_call',
then we cannot have a mis-match, because we would have
already found such a winning case. */
- if (IDENTIFIER_GLOBAL_VALUE (overload_name))
- if (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (overload_name)) != TREE_LIST)
- return build_function_call (DECL_MAIN_VARIANT (IDENTIFIER_GLOBAL_VALUE (overload_name)), parms);
+ if (fn && TREE_CODE (fn) == FUNCTION_DECL)
+ return build_function_call (DECL_MAIN_VARIANT (fn), parms);
}
- functions = IDENTIFIER_GLOBAL_VALUE (fnname);
+ functions = lookup_name_nonclass (fnname);
if (functions == NULL_TREE)
{
extern tree make_thunk ();
if (idelta)
{
- pfn = build1 (ADDR_EXPR, ptr_type_node,
+ pfn = build1 (ADDR_EXPR, vtable_entry_type,
make_thunk (pfn, idelta));
TREE_READONLY (pfn) = 1;
TREE_CONSTANT (pfn) = 1;
{
/* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
convert to void *. Make such a conversion here. */
- tree vfn = build1 (ADDR_EXPR, ptr_type_node, fndecl);
+ tree vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
TREE_CONSTANT (vfn) = 1;
#ifndef DUMB_USER
if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node;
- vfn = build1 (ADDR_EXPR, ptr_type_node, fndecl);
+ vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
TREE_CONSTANT (vfn) = 1;
/* We can use integer_zero_node, as we will will core dump
}
if (write_virtuals == 3 && CLASSTYPE_INTERFACE_KNOWN (t)
- && current_lang_name == lang_name_cplusplus && ! IS_SIGNATURE (t))
+ && ! IS_SIGNATURE (t))
{
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! interface_only;
last_x = tree_last (TYPE_FIELDS (t));
while (x)
{
+#if 0 /* What's wrong with using the decl the type already has? */
tree tag = build_lang_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x));
+ DECL_CONTEXT (tag) = t;
+#else
+ tree tag = TYPE_NAME (TREE_VALUE (x));
+#endif
+ DECL_CLASS_CONTEXT (tag) = t;
+
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
{
DECL_IGNORED_P (tag) = 1;
}
#endif /* DWARF_DEBUGGING_INFO */
- DECL_CONTEXT (tag) = t;
- DECL_CLASS_CONTEXT (tag) = t;
+
+ TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 0;
x = TREE_CHAIN (x);
last_x = chainon (last_x, tag);
}
else if (TYPE_NEEDS_CONSTRUCTING (t))
build_class_init_list (t);
- if (current_lang_name == lang_name_cplusplus)
- {
- if (! CLASSTYPE_DECLARED_EXCEPTION (t)
- && ! IS_SIGNATURE (t))
- embrace_waiting_friends (t);
+ if (! CLASSTYPE_DECLARED_EXCEPTION (t) && ! IS_SIGNATURE (t))
+ embrace_waiting_friends (t);
- /* Write out inline function definitions. */
- do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t));
- CLASSTYPE_INLINE_FRIENDS (t) = 0;
- }
+ /* Write out inline function definitions. */
+ do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t));
+ CLASSTYPE_INLINE_FRIENDS (t) = 0;
if (CLASSTYPE_VSIZE (t) != 0)
{
}
/* Get out of the current class scope. If we were in a class scope
- previously, that is the one popped to. The flag MODIFY tells
- whether the current scope declarations needs to be modified
- as a result of popping to the previous scope. */
+ previously, that is the one popped to. The flag MODIFY tells whether
+ the current scope declarations needs to be modified as a result of
+ popping to the previous scope. 0 is used for class definitions. */
void
popclass (modify)
int modify;
/* This code can be seen as a cache miss. When we've cached a
class' scope's bindings and we can't use them, we need to reset
them. This is it! */
- for (t = previous_class_values; t; t = TREE_CHAIN(t))
+ for (t = previous_class_values; t; t = TREE_CHAIN (t))
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
while (tags)
{
undo_template_name_overload (current_class_name, 0);
}
- poplevel_class ();
+ /* Force clearing of IDENTIFIER_CLASS_VALUEs after a class definition,
+ since not all class decls make it there currently. */
+ poplevel_class (! modify);
/* Since poplevel_class does the popping of class decls nowadays,
this really only frees the obstack used for these decls.
return save_elem;
}
name = DECL_NAME (TREE_VALUE (rhs));
+#if 0
if (TREE_CODE (lhstype) == FUNCTION_TYPE && globals < 0)
{
/* Try to instantiate from non-member functions. */
- rhs = IDENTIFIER_GLOBAL_VALUE (name);
+ rhs = lookup_name_nonclass (name);
if (rhs && TREE_CODE (rhs) == TREE_LIST)
{
/* This code seems to be missing a `return'. */
instantiate_type (lhstype, rhs, complain);
}
}
+#endif
}
if (complain)
error ("no static member functions named `%s'",
return rhs;
case ADDR_EXPR:
- if (TREE_CODE (lhstype) != POINTER_TYPE)
+ if (TYPE_PTRMEMFUNC_P (lhstype))
+ lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
+ else if (TREE_CODE (lhstype) != POINTER_TYPE)
{
if (complain)
error ("type for resolving address of overloaded function must be pointer type");
}
TREE_TYPE (rhs) = lhstype;
lhstype = TREE_TYPE (lhstype);
- TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
+ TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0),
+ complain);
if (TREE_OPERAND (rhs, 0) == error_mark_node)
return error_mark_node;
unsigned constructor_for_vbase_attr : 1;
unsigned mutable_flag : 1;
unsigned is_default_implementation : 1;
- unsigned synthesized : 1;
unsigned saved_inline : 1;
- unsigned dummy : 9;
+ unsigned dummy : 10;
tree access;
tree context;
member function. */
#define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function)
+/* Nonzero for a class member means that it is shared between all objects
+ of that class. */
+#define SHARED_MEMBER_P(NODE) \
+ (TREE_CODE (NODE) == VAR_DECL || TREE_CODE (NODE) == TYPE_DECL \
+ || TREE_CODE (NODE) == CONST_DECL)
+
/* Nonzero for FUNCTION_DECL means that this decl is a member function
(static or non-static). */
#define DECL_FUNCTION_MEMBER_P(NODE) \
#define DECL_PUBLIC(NODE) (DECL_LANG_FLAG_7 (NODE))
#endif
-/* This method was synthesized by cons_up_default_function. */
-#define DECL_SYNTHESIZED(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.synthesized)
+/* This _DECL represents a compiler-generated entity. */
+#define DECL_ARTIFICIAL(NODE) (DECL_SOURCE_LINE (NODE) == 0)
+#define SET_DECL_ARTIFICIAL(NODE) (DECL_SOURCE_LINE (NODE) = 0)
/* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp))
extern tree void_zero_node;
extern tree default_function_type;
extern tree vtable_entry_type;
-extern tree memptr_type;
extern tree sigtable_entry_type;
extern tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node;
extern tree Type_info_type_node;
extern tree exception_type_node, unknown_type_node;
extern tree opaque_type_node, signature_type_node;
+/* Node for "pointer to (virtual) function".
+ This may be distinct from ptr_type_node so gdb can distinuish them. */
+#define vfunc_ptr_type_node \
+ (flag_vtable_thunks ? vtable_entry_type : ptr_type_node)
+
/* Array type `(void *)[]' */
extern tree vtbl_type_node;
extern tree delta_type_node;
extern void add_block_current_level PROTO((tree));
extern void set_block PROTO((tree));
extern void pushlevel_class PROTO((void));
-extern tree poplevel_class PROTO((void));
+extern tree poplevel_class PROTO((int));
/* skip print_other_binding_stack and print_binding_level */
extern void print_binding_stack PROTO((void));
extern void push_to_top_level PROTO((void));
extern tree reparse_absdcl_as_casts PROTO((tree, tree));
extern tree reparse_decl_as_expr PROTO((tree, tree));
extern tree finish_decl_parsing PROTO((tree));
+extern tree lookup_name_nonclass PROTO((tree));
/* in edsel.c */
&& (TREE_READONLY (TREE_TYPE (TREE_TYPE (rval)))
> TREE_READONLY (TREE_TYPE (xtype))))
warning ("user-defined conversion casting away `const'");
- return convert (xtype, rval);
+ rval = convert_for_initialization (NULL_TREE, xtype, rval, flags,
+ "conversion", NULL_TREE, 0);
+ if (rval == error_mark_node)
+ return NULL_TREE;
+ return rval;
}
/* Convert an aggregate EXPR to type XTYPE. If a conversion
tree int_ftype_cptr_cptr_sizet;
/* C++ extensions */
-tree memptr_type, vtable_entry_type;
+tree vtable_entry_type;
tree delta_type_node;
tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node;
tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type;
/* Same, for IDENTIFIER_TYPE_VALUE. */
tree type_shadowed;
- /* Same, for IDENTIFIER_GLOBAL_VALUE for overloaded functions. */
- tree overloads_shadowed;
-
/* For each level (except not the global one),
a chain of BLOCK nodes for all the levels
that were entered and exited one level down. */
for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link))
IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->overloads_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_GLOBAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
/* If the level being exited is the top level of a function,
check over all the labels. */
while (current_binding_level->parm_flag == 2);
}
-/* ...and a poplevel for class declarations. */
+/* ...and a poplevel for class declarations. FORCE is used to force
+ clearing out of CLASS_VALUEs after a class definition. */
tree
-poplevel_class ()
+poplevel_class (force)
+ int force;
{
register struct binding_level *level = class_binding_level;
tree block = NULL_TREE;
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
next time we're entering a class scope, it is the same class. */
- if (current_class_depth != 1)
+ if (current_class_depth != 1 || force)
for (shadowed = level->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
if (b->parm_flag != 2
|| TYPE_SIZE (current_class_type) != NULL_TREE)
{
- if (current_lang_name == lang_name_cplusplus)
- d = lookup_nested_type (type, cdecl);
- else
- d = NULL_TREE;
+ d = lookup_nested_type (type, cdecl);
if (d == NULL_TREE)
{
}
TYPE_NAME (type) = d;
- if (context == NULL_TREE || current_lang_name != lang_name_cplusplus)
+ if (context == NULL_TREE)
/* Non-nested class. */
DECL_NESTED_TYPENAME (d) = name;
else if (context && TREE_CODE (context) == FUNCTION_DECL)
is METHOD_TYPE. Change that to FUNCTION_TYPE, and
proceed. */
if (TREE_CODE (f1) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (olddecl))
- revert_static_member_fn (&f1, &newdecl, &p1);
+ revert_static_member_fn (&newdecl, &f1, &p1);
else if (TREE_CODE (f2) == METHOD_TYPE
&& DECL_STATIC_FUNCTION_P (newdecl))
- revert_static_member_fn (&f2, &olddecl, &p2);
+ revert_static_member_fn (&olddecl, &f2, &p2);
/* Here we must take care of the case where new default
parameters are specified. Also, warn if an old
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl))
&& DECL_ASSEMBLER_NAME (newdecl) == DECL_ASSEMBLER_NAME (olddecl))
+ /* Redeclaring a builtin as another function is handled in
+ push_overloaded_decl. */
{
/* If you declare a built-in or predefined function name as static,
the old definition is overridden,
but optionally warn this was a bad choice of name. */
if (! TREE_PUBLIC (newdecl))
- {
- if (warn_shadow)
- cp_warning ("shadowing %s function `%#D'",
- DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- newdecl);
- /* Discard the old built-in function. */
- }
- else if (! types_match)
+ if (warn_shadow)
+ cp_warning ("shadowing %s function `%#D'",
+ DECL_BUILT_IN (olddecl) ? "built-in" : "library",
+ newdecl);
+ /* Likewise, if the built-in is not ansi, then programs can override
+ it even globally without an error. */
+ else if (! DECL_BUILT_IN (olddecl))
+ cp_warning ("library function `%#D' redeclared as non-function `%#D'",
+ olddecl, newdecl);
+ else
{
cp_warning ("declaration of `%#D'", newdecl);
cp_warning ("conflicts with built-in declaration `%#D'",
olddecl);
}
- if (TREE_CODE (newdecl) != FUNCTION_DECL)
- return 0;
-
- if (! types_match)
- TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
+ return 0;
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
newdecl);
cp_error_at ("previous declaration `%#D' here", olddecl);
}
-
- return 0;
+
+ if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
+ TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2))
+ {
+ cp_error ("new declaration `%#D'", newdecl);
+ cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+ }
+ else
+ return 0;
}
/* Already complained about this, so don't do so again. */
/* Optionally warn about more than one declaration for the same name,
but don't warn about a function declaration followed by a definition. */
if (warn_redundant_decls
- && DECL_SOURCE_LINE (olddecl) != 0
+ && ! DECL_ARTIFICIAL (olddecl)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
/* Don't warn about extern decl followed by (tentative) definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl)))
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
+ if (! types_match)
+ {
+ DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
+ DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (newdecl);
+ DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
+ DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
+ DECL_RTL (olddecl) = DECL_RTL (newdecl);
+ }
if (new_defines_function)
/* If defining a function declared with other language
linkage, use the previously declared language linkage. */
nglobals = len;
#endif
- /* Don't change DECL_CONTEXT of virtual methods. */
if (x != current_function_decl
- && (TREE_CODE (x) != FUNCTION_DECL
- || !DECL_VIRTUAL_P (x))
+ /* Don't change DECL_CONTEXT of virtual methods. */
+ && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
&& ! DECL_CONTEXT (x))
DECL_CONTEXT (x) = current_function_decl;
/* A local declaration for a function doesn't constitute nesting. */
char *file;
int line;
- if (DECL_EXTERNAL (x))
- t = lookup_name (name, 0);
- else
- t = lookup_name_current_level (name);
+ t = lookup_name_current_level (name);
if (t == error_mark_node)
{
/* error_mark_node is 0 for a while during initialization! */
/* Maybe warn if shadowing something else. */
else if (warn_shadow && !DECL_EXTERNAL (x)
/* No shadow warnings for internally generated vars. */
- && DECL_SOURCE_LINE (x) != 0
+ && ! DECL_ARTIFICIAL (x)
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
{
if (current_class_name)
{
- if (!DECL_NESTED_TYPENAME (x))
+ if (!DECL_NESTED_TYPENAME (TYPE_NAME (TREE_TYPE (x))))
set_nested_typename (x, current_class_name, DECL_NAME (x),
TREE_TYPE (x));
}
return 0;
}
-/* DECL is a FUNCTION_DECL which may have other definitions already in place.
- We get around this by making IDENTIFIER_GLOBAL_VALUE (DECL_NAME (DECL))
- point to a list of all the things that want to be referenced by that name.
- It is then up to the users of that name to decide what to do with that
+/* DECL is a FUNCTION_DECL which may have other definitions already in
+ place. We get around this by making the value of the identifier point
+ to a list of all the things that want to be referenced by that name. It
+ is then up to the users of that name to decide what to do with that
list.
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
int forgettable;
{
tree orig_name = DECL_NAME (decl);
- tree glob = IDENTIFIER_GLOBAL_VALUE (orig_name);
+ tree old;
+ int doing_global = (global_bindings_p () || ! forgettable
+ || flag_traditional || pseudo_global_level_p ());
+
+ if (doing_global)
+ {
+ old = IDENTIFIER_GLOBAL_VALUE (orig_name);
+ if (old && TREE_CODE (old) == FUNCTION_DECL
+ && (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
+ {
+ if (! decls_match (decl, old)
+ && (DECL_LANGUAGE (decl) == lang_c
+ || compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)),
+ TYPE_ARG_TYPES (TREE_TYPE (old)), 2)))
+ {
+ cp_warning ("declaration of `%#D'", decl);
+ cp_warning ("conflicts with built-in declaration `%#D'", old);
+ }
+ old = NULL_TREE;
+ }
+ }
+ else
+ {
+ old = IDENTIFIER_LOCAL_VALUE (orig_name);
+
+ if (! purpose_member (orig_name, current_binding_level->shadowed))
+ {
+ current_binding_level->shadowed
+ = tree_cons (orig_name, old, current_binding_level->shadowed);
+ old = NULL_TREE;
+ }
+ }
- if (glob)
+ if (old)
{
+#if 0
/* We cache the value of builtin functions as ADDR_EXPRs
in the name space. Convert it to some kind of _DECL after
remembering what to forget. */
- if (TREE_CODE (glob) == ADDR_EXPR)
- glob = TREE_OPERAND (glob, 0);
-
- else if (TREE_CODE (decl) == TEMPLATE_DECL)
- {
- tree tmp;
-
- for (tmp = get_first_fn (glob); tmp; tmp = DECL_CHAIN (tmp))
- if (decl == tmp || duplicate_decls (decl, tmp))
- return decl;
- }
- else if (TREE_CODE (glob) == VAR_DECL)
+ if (TREE_CODE (old) == ADDR_EXPR)
+ old = TREE_OPERAND (old, 0);
+ else
+#endif
+ if (TREE_CODE (old) == VAR_DECL)
{
- cp_error_at ("previous non-function declaration `%#D'", glob);
+ 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 (glob) == TYPE_DECL)
+ else if (TREE_CODE (old) == TYPE_DECL)
{
- tree t = TREE_TYPE (glob);
+ tree t = TREE_TYPE (old);
if (IS_AGGR_TYPE (t) && warn_shadow)
cp_warning ("`%#D' hides constructor for `%#T'", decl, t);
}
- else if (is_overloaded_fn (glob))
+ else if (is_overloaded_fn (old))
{
tree tmp;
- for (tmp = get_first_fn (glob); tmp; tmp = DECL_CHAIN (tmp))
- {
- if (decl == tmp || duplicate_decls (decl, tmp))
- return tmp;
- /* Avoid doing things about built-ins, since duplicate_decls
- will have given warnings/errors for them. */
- if (!DECL_BUILT_IN (tmp) && !DECL_BUILT_IN_NONANSI (tmp)
- && compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)),
- TYPE_ARG_TYPES (TREE_TYPE (tmp)), 2))
- {
- cp_error ("new declaration `%#D'", decl);
- cp_error_at ("ambiguates old declaration `%#D'", tmp);
- }
- }
+ for (tmp = get_first_fn (old); tmp; tmp = DECL_CHAIN (tmp))
+ if (decl == tmp || duplicate_decls (decl, tmp))
+ return tmp;
}
}
- if (forgettable
- && ! flag_traditional
- && (glob == NULL_TREE || TREE_PERMANENT (glob) == 1)
- && !global_bindings_p ()
- && !pseudo_global_level_p ())
- current_binding_level->overloads_shadowed
- = tree_cons (orig_name, glob,
- current_binding_level->overloads_shadowed);
-
- if (glob || TREE_CODE (decl) == TEMPLATE_DECL)
+ if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{
- if (glob && is_overloaded_fn (glob))
- DECL_CHAIN (decl) = get_first_fn (glob);
+ if (old && is_overloaded_fn (old))
+ DECL_CHAIN (decl) = get_first_fn (old);
else
DECL_CHAIN (decl) = NULL_TREE;
- glob = tree_cons (orig_name, decl, NULL_TREE);
- TREE_TYPE (glob) = unknown_type_node;
+ old = tree_cons (orig_name, decl, NULL_TREE);
+ TREE_TYPE (old) = unknown_type_node;
}
else
/* orig_name is not ambiguous. */
- glob = decl;
-
- IDENTIFIER_GLOBAL_VALUE (orig_name) = glob;
+ old = decl;
+
+ if (doing_global)
+ IDENTIFIER_GLOBAL_VALUE (orig_name) = old;
+ else
+ IDENTIFIER_LOCAL_VALUE (orig_name) = old;
+
return decl;
}
\f
of internal entities. They can't be accessed,
and they should be cleaned up
by the time we get to the label. */
- && DECL_SOURCE_LINE (new_decls) != 0
+ && ! DECL_ARTIFICIAL (new_decls)
&& ((DECL_INITIAL (new_decls) != NULL_TREE
&& DECL_INITIAL (new_decls) != error_mark_node)
|| TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
Otherwise we prefer non-TYPE_DECLs. */
tree
-lookup_name (name, prefer_type)
+lookup_name_real (name, prefer_type, nonclass)
tree name;
- int prefer_type;
+ int prefer_type, nonclass;
{
register tree val;
int yylex = 0;
else if (! IS_AGGR_TYPE (got_scope))
/* Someone else will give an error about this if needed. */
val = NULL_TREE;
+ else if (TYPE_BEING_DEFINED (got_scope))
+ {
+ val = IDENTIFIER_CLASS_VALUE (name);
+ if (val && DECL_CONTEXT (val) != got_scope)
+ {
+ 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)
+ {
+ val = TREE_VALUE (t);
+ break;
+ }
+ }
+ }
+ if (val == NULL_TREE
+ && CLASSTYPE_LOCAL_TYPEDECLS (got_scope))
+ val = lookup_field (got_scope, name, 0, 1);
+ }
else if (got_scope == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
- else if (TYPE_BEING_DEFINED (got_scope))
- val = lookup_nested_tag (got_scope, name);
else
val = lookup_field (got_scope, name, 0, 0);
val = IDENTIFIER_LOCAL_VALUE (name);
/* In C++ class fields are between local and global scope,
just before the global scope. */
- else if (current_class_type)
+ else if (current_class_type && ! nonclass)
{
val = IDENTIFIER_CLASS_VALUE (name);
if (val == NULL_TREE
- && TYPE_SIZE (current_class_type) == NULL_TREE
+ && TYPE_BEING_DEFINED (current_class_type)
&& CLASSTYPE_LOCAL_TYPEDECLS (current_class_type))
+ /* Try to find values from base classes if we are presently
+ defining a type. We are presently only interested in
+ TYPE_DECLs. */
{
- /* Try to find values from base classes
- if we are presently defining a type.
- We are presently only interested in TYPE_DECLs. */
val = lookup_field (current_class_type, name, 0, 1);
- if (val == error_mark_node)
- return val;
- if (val && TREE_CODE (val) != TYPE_DECL)
- val = NULL_TREE;
+ if (val)
+ pushdecl_class_level (val);
}
/* yylex() calls this with -2, since we should never start digging for
return val;
}
+tree
+lookup_name_nonclass (name)
+ tree name;
+{
+ return lookup_name_real (name, 0, 1);
+}
+
+tree
+lookup_name (name, prefer_type)
+ tree name;
+ int prefer_type;
+{
+ return lookup_name_real (name, prefer_type, 0);
+}
+
/* Similar to `lookup_name' but look only at current binding level. */
tree
pushdecl (lookup_name (get_identifier ("__gc_main"), 0));
}
- /* Simplify life by making a "memptr_type". Give its
- fields names so that the debugger can use them. */
-
- memptr_type = make_lang_type (RECORD_TYPE);
- fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
- delta_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier,
- delta_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier,
- ptr_type_node);
- finish_builtin_type (memptr_type, VTBL_PTR_TYPE, fields, 2,
- double_type_node);
-
- /* Make this part of an invisible union. */
- fields[3] = copy_node (fields[2]);
- TREE_TYPE (fields[3]) = delta_type_node;
- DECL_NAME (fields[3]) = delta2_identifier;
- DECL_MODE (fields[3]) = TYPE_MODE (delta_type_node);
- DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
- TREE_UNSIGNED (fields[3]) = 0;
- TREE_CHAIN (fields[2]) = fields[3];
- memptr_type = build_type_variant (memptr_type, 1, 0);
- record_builtin_type (RID_MAX, VTBL_PTR_TYPE, memptr_type);
-
if (flag_vtable_thunks)
- vtable_entry_type = ptr_type_node;
+ {
+ /* Make sure we get a unique function type, so we can give
+ its pointer type a name. (This wins for gdb.) */
+ tree vfunc_type = make_node (FUNCTION_TYPE);
+ TREE_TYPE (vfunc_type) = integer_type_node;
+ TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
+ layout_type (vfunc_type);
+
+ vtable_entry_type = build_pointer_type (vfunc_type);
+ }
else
- vtable_entry_type = memptr_type;
+ {
+ vtable_entry_type = make_lang_type (RECORD_TYPE);
+ fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
+ delta_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier,
+ delta_type_node);
+ fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier,
+ ptr_type_node);
+ finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2,
+ double_type_node);
+
+ /* Make this part of an invisible union. */
+ fields[3] = copy_node (fields[2]);
+ TREE_TYPE (fields[3]) = delta_type_node;
+ DECL_NAME (fields[3]) = delta2_identifier;
+ DECL_MODE (fields[3]) = TYPE_MODE (delta_type_node);
+ DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
+ TREE_UNSIGNED (fields[3]) = 0;
+ TREE_CHAIN (fields[2]) = fields[3];
+ vtable_entry_type = build_type_variant (vtable_entry_type, 1, 0);
+ }
+ record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
vtbl_type_node
= build_array_type (vtable_entry_type, NULL_TREE);
grok_ctor_properties (ctype, decl);
if (check == 0 && ! current_function_decl)
{
- /* FIXME: this should only need to look at IDENTIFIER_GLOBAL_VALUE. */
+ /* FIXME: this should only need to look at
+ IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
if (tmp == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
/* When the compiler encounters the definition of A::operator new, it
doesn't look at the class declaration to find out if it's static. */
if (methodp)
- revert_static_member_fn (&TREE_TYPE (decl), &decl,
- &TYPE_ARG_TYPES (TREE_TYPE (decl)));
+ revert_static_member_fn (&decl, NULL, NULL);
/* Take care of function decl if we had syntax errors. */
if (argtypes == NULL_TREE)
|| name == ansi_opname[(int) VEC_DELETE_EXPR])
{
if (methodp)
- revert_static_member_fn (&TREE_TYPE (decl), &decl,
- &TYPE_ARG_TYPES (TREE_TYPE (decl)));
+ revert_static_member_fn (&decl, NULL, NULL);
if (argtypes == NULL_TREE)
TREE_TYPE (decl) =
/* An operator function must either be a non-static member function
or have at least one parameter of a class, a reference to a class,
an enumeration, or a reference to an enumeration. 13.4.0.6 */
- if (! methodp)
+ if (! methodp || DECL_STATIC_FUNCTION_P (decl))
{
if (OPERATOR_TYPENAME_P (name)
|| name == ansi_opname[(int) CALL_EXPR]
{
tree p = argtypes;
+ if (DECL_STATIC_FUNCTION_P (decl))
+ cp_error ("`%D' must be either a non-static member function or a non-member function", decl);
+
if (p)
for (; TREE_VALUE (p) != void_type_node ; p = TREE_CHAIN (p))
{
}
/* Change a static member function definition into a FUNCTION_TYPE, instead
- of the METHOD_TYPE that we create when it's originally parsed. */
+ of the METHOD_TYPE that we create when it's originally parsed.
+
+ WARNING: DO NOT pass &TREE_TYPE (decl) to FN or &TYPE_ARG_TYPES
+ (TREE_TYPE (decl)) to ARGTYPES, as doing so will corrupt the types of
+ other decls. Either pass the addresses of local variables or NULL. */
+
void
-revert_static_member_fn (fn, decl, argtypes)
- tree *fn, *decl, *argtypes;
+revert_static_member_fn (decl, fn, argtypes)
+ tree *decl, *fn, *argtypes;
{
- tree tmp, function = *fn;
+ tree tmp;
+ tree function = fn ? *fn : TREE_TYPE (*decl);
+ tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function);
- *argtypes = TREE_CHAIN (*argtypes);
- tmp = build_function_type (TREE_TYPE (function), *argtypes);
+ args = TREE_CHAIN (args);
+ tmp = build_function_type (TREE_TYPE (function), args);
tmp = build_type_variant (tmp, TYPE_READONLY (function),
TYPE_VOLATILE (function));
tmp = build_exception_variant (TYPE_METHOD_BASETYPE (function), tmp,
TYPE_RAISES_EXCEPTIONS (function));
TREE_TYPE (*decl) = tmp;
- *fn = tmp;
DECL_STATIC_FUNCTION_P (*decl) = 1;
+ if (fn)
+ *fn = tmp;
+ if (argtypes)
+ *argtypes = args;
}
tree fn_name = DECL_NAME (function);
tree arg_types;
tree parm;
+ tree qualtype;
if (fn_name == NULL_TREE)
{
}
if (quals)
- ctype = grok_method_quals (ctype, function, quals);
+ qualtype = grok_method_quals (ctype, function, quals);
+ else
+ qualtype = ctype;
arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
of virtual baseclasses or not. */
parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
/* Mark the artificial `__in_chrg' parameter as "artificial". */
- DECL_SOURCE_LINE (parm) = 0;
+ SET_DECL_ARTIFICIAL (parm);
DECL_ARG_TYPE (parm) = integer_type_node;
DECL_REGISTER (parm) = 1;
TREE_CHAIN (parm) = last_function_parms;
parm = build_decl (PARM_DECL, this_identifier, type);
/* Mark the artificial `this' parameter as "artificial". */
- DECL_SOURCE_LINE (parm) = 0;
+ SET_DECL_ARTIFICIAL (parm);
DECL_ARG_TYPE (parm) = type;
/* We can make this a register, so long as we don't
accidentally complain if someone tries to take its address. */
DECL_ASSEMBLER_NAME (function) = get_identifier (buf);
parm = build_decl (PARM_DECL, in_charge_identifier, const_integer_type);
/* Mark the artificial `__in_chrg' parameter as "artificial". */
- DECL_SOURCE_LINE (parm) = 0;
+ SET_DECL_ARTIFICIAL (parm);
TREE_USED (parm) = 1;
#if 0
/* We don't need to mark the __in_chrg parameter itself as `const'
/* This is the same chain as DECL_ARGUMENTS (...). */
TREE_CHAIN (last_function_parms) = parm;
- TREE_TYPE (function) = build_cplus_method_type (ctype, void_type_node,
+ TREE_TYPE (function) = build_cplus_method_type (qualtype, void_type_node,
arg_types);
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
arg_types = hash_tree_chain (integer_type_node,
TREE_CHAIN (arg_types));
TREE_TYPE (function)
- = build_cplus_method_type (ctype,
+ = build_cplus_method_type (qualtype,
TREE_TYPE (TREE_TYPE (function)),
arg_types);
arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
/* Only true for static member functions. */
- these_arg_types = hash_tree_chain (TYPE_POINTER_TO (ctype), arg_types);
+ these_arg_types = hash_tree_chain (TYPE_POINTER_TO (qualtype),
+ arg_types);
DECL_ASSEMBLER_NAME (function)
= build_decl_overload (fn_name, these_arg_types,
if (TREE_CODE (value) == TYPE_DECL)
{
DECL_NONLOCAL (value) = 1;
+ DECL_CONTEXT (value) = current_class_type;
+ DECL_CLASS_CONTEXT (value) = current_class_type;
CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
pushdecl_class_level (value);
return value;
vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node);
#endif
DECL_IGNORED_P (vars) = 1;
- DECL_SOURCE_LINE (vars) = 0;
+ SET_DECL_ARTIFICIAL (vars);
pushdecl (vars);
#endif
ident_fndecl (t)
tree t;
{
- tree n = IDENTIFIER_GLOBAL_VALUE (t);
+ tree n = lookup_name (t, 0);
if (TREE_CODE (n) == FUNCTION_DECL)
return n;
{
/* @@ Should be able to ingest later definitions of this function
before use. */
- tree decl = IDENTIFIER_GLOBAL_VALUE (declarator);
+ tree decl = lookup_name_nonclass (declarator);
if (decl == NULL_TREE)
{
warning ("implicitly declaring `%s' as struct",
{
tree dtor = DECL_MAIN_VARIANT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0));
tree basetypes = TYPE_BINFO (type);
+ tree passed_auto_delete;
+ tree do_delete = NULL_TREE;
+
+ if (use_global_delete)
+ {
+ tree cond = fold (build (BIT_AND_EXPR, integer_type_node,
+ auto_delete, integer_one_node));
+ tree call = build_builtin_call
+ (void_type_node, BID, build_tree_list (NULL_TREE, addr));
+
+ cond = fold (build (COND_EXPR, void_type_node, cond,
+ call, void_zero_node));
+ if (cond != void_zero_node)
+ do_delete = cond;
+
+ passed_auto_delete = fold (build (BIT_AND_EXPR, integer_type_node,
+ auto_delete, integer_two_node));
+ }
+ else
+ passed_auto_delete = auto_delete;
if (flags & LOOKUP_PROTECT)
{
if (function == error_mark_node)
return error_mark_node;
TREE_TYPE (function) = build_pointer_type (TREE_TYPE (dtor));
- TREE_CHAIN (parms) = build_tree_list (NULL_TREE, auto_delete);
+ TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete);
expr = build_function_call (function, parms);
+ if (do_delete)
+ expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
if (ptr && (flags & LOOKUP_DESTRUCTOR) == 0)
{
/* Handle the case where a virtual destructor is
but that's now obsolete. */
my_friendly_assert (DECL_INITIAL (dtor) != void_type_node, 221);
- TREE_CHAIN (parms) = build_tree_list (NULL_TREE, auto_delete);
+ TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete);
expr = build_function_call (dtor, parms);
+ if (do_delete)
+ expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
if (ifexp != integer_one_node)
expr = build (COND_EXPR, void_type_node,
}
#endif /* DEBUG_DEFAULT_FUNCTIONS */
- DECL_CLASS_CONTEXT (fn) = type;
+ DECL_CLASS_CONTEXT (fn) = TYPE_MAIN_VARIANT (type);
/* Show that this function was generated by the compiler. */
-#if 0
- DECL_SOURCE_LINE (fn) = 0;
-#else
- DECL_SYNTHESIZED (fn) = 1;
-#endif
+ SET_DECL_ARTIFICIAL (fn);
return fn;
}
btype = BINFO_TYPE (binfo);
name = TYPE_NESTED_NAME (btype);
- if (!name) name = DECL_NAME(TYPE_NAME(btype));
s = IDENTIFIER_POINTER (name);
tneed = (2 * strlen (s)) + 33;
btype = BINFO_TYPE (binfo);
name = TYPE_NESTED_NAME (btype);
- if (!name) name = DECL_NAME(TYPE_NAME(btype));
s = IDENTIFIER_POINTER (name);
tneed = (2 * strlen (s)) + 30;
}
/* Allow this decl to be seen in global scope */
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (fndecl)) = fndecl;
+ if (! current_function_decl)
+ IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (fndecl)) = fndecl;
}
friend_list = TREE_CHAIN (friend_list);
else
fnname = ansi_opname[(int) code];
- global_fn = IDENTIFIER_GLOBAL_VALUE (fnname);
+ global_fn = lookup_name_nonclass (fnname);
/* This is the last point where we will accept failure. This
may be too eager if we wish an overloaded operator not to match,
thunk = build_decl (THUNK_DECL, get_identifier (buffer),
TREE_TYPE (func_decl));
DECL_RESULT (thunk)
- = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
+ = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type));
make_function_rtl (thunk);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
expand_end_bindings (NULL, 1, 0);
- poplevel (0, 0, 1);
+ poplevel (0, 0, 0);
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
error message if the user supplies an empty conditional expression. */
static char *cond_stmt_keyword;
+static int doing_explicit;
+
/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
int have_extern_spec;
int used_extern_spec;
%type <ttype> qualified_type_name complete_type_name notype_identifier
%type <ttype> complex_type_name nested_name_specifier_1
%type <itype> nomods_initdecls nomods_initdcl0
-%type <ttype> new_initializer new_placement
+%type <ttype> new_initializer new_placement specialization
/* in order to recognize aggr tags as defining and thus shadowing. */
%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
| declmods ';'
{ pedwarn ("empty declaration"); }
| explicit_instantiation ';'
+ { doing_explicit = 0; }
| typed_declspecs ';'
{
tree t = $<ttype>$;
| PTYPENAME_DEFN
;
+do_explicit: TEMPLATE %prec EMPTY
+ { doing_explicit = 1; }
+ ;
+
explicit_instantiation:
- TEMPLATE aggr template_type
- { do_type_instantiation ($3); }
- | TEMPLATE typed_declspecs declarator
+ do_explicit specialization template_instantiation
+ { do_type_instantiation ($3 ? $3 : $2); }
+ | do_explicit typed_declspecs declarator
{ do_function_instantiation ($2, $3); }
+ | do_explicit error
;
template_type:
{ $$ = lookup_template_class ($$, $3, NULL_TREE); }
;
-tmpl.2: %prec EMPTY
- /* Always do expansion if it hasn't been done already. */
+tmpl.2:
+ /* empty */ %prec EMPTY
{ $$ = instantiate_class_template ($<ttype>0, 1); }
;
{ error ("no body nor ';' separates two class, struct or union declarations"); }
;
+specialization:
+ aggr template_type_name ';'
+ {
+ yyungetc (';', 1); current_aggr = $$; $$ = $2;
+ if (doing_explicit)
+ instantiate_class_template ($$, 1);
+ }
+ ;
+
named_class_head_sans_basetype:
aggr identifier
{ current_aggr = $$; $$ = $2; }
overload_template_name ($$, 0); }
| aggr template_type_name ':'
{ yyungetc (':', 1); goto aggr2; }
+ | specialization
;
named_class_head_sans_basetype_defn:
{ $$ = ansi_opname[VEC_NEW_EXPR]; }
| operator DELETE '[' ']'
{ $$ = ansi_opname[VEC_DELETE_EXPR]; }
- /* Should we be pushing into class scope to parse this? */
+ /* Names here should be looked up in class scope ALSO. */
| operator typed_typespecs conversion_declarator
{ $$ = grokoptypename ($2, $3); }
| operator error
tree decls;
int got_it = 0;
- decls = IDENTIFIER_GLOBAL_VALUE (r);
+ decls = lookup_name (r, 0);
if (decls == NULL_TREE)
/* no match */;
else if (TREE_CODE (decls) == TREE_LIST)
&& DECL_STATIC_FUNCTION_P (fndecl))
{
tree olddecl = DECL_RESULT (tmpl);
- revert_static_member_fn (&TREE_TYPE (olddecl), &DECL_RESULT (tmpl),
- &TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
+ revert_static_member_fn (&DECL_RESULT (tmpl), NULL, NULL);
/* Chop off the this pointer that grokclassfn so kindly added
for us (it didn't know yet if the fn was static or not). */
DECL_ARGUMENTS (olddecl) = TREE_CHAIN (DECL_ARGUMENTS (olddecl));
PUBLIC_RETURN;
/* Member found immediately within object. */
- if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE || static_mem)
+ if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE)
{
/* Are we (or an enclosing scope) friends with the class that has
FIELD? */
types = basetype_path;
via_protected = 0;
access = access_default;
- protected_ok = 0;
+ protected_ok = static_mem && current_class_type
+ && ACCESSIBLY_DERIVED_FROM_P (BINFO_TYPE (types), current_class_type);
while (1)
{
we know that binfo of a virtual base class will always == itself when
found along any line. (mrs) */
- /* Things for memoization. */
char *errstr = 0;
/* Set this to nonzero if we don't know how to compute
if (nval || lookup_fnfields_here (type, name)>=0)
{
- if (rval_binfo && hides (rval_binfo_h, binfo_h))
+ if (nval && nval == rval && SHARED_MEMBER_P (nval))
+ {
+ /* This is ok, the member found is the same [class.ambig] */
+ }
+ else if (rval_binfo && hides (rval_binfo_h, binfo_h))
{
/* This is ok, the member found is in rval_binfo, not
here (binfo). */
/* For now, don't try this. */
int protect = complain;
- /* Things for memoization. */
char *errstr = 0;
/* Set this to nonzero if we don't know how to compute
TREE_TYPE (entry) = NULL_TREE;
}
- if (errstr && protect)
- {
- error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
- return error_mark_node;
- }
return rvals;
}
rval = NULL_TREE;
else
{
/* This is ambiguous. */
- errstr = "request for member `%s' is ambiguous";
+ errstr = "request for method `%D' is ambiguous";
rvals = error_mark_node;
break;
}
if (errstr && protect)
{
- error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type));
+ cp_error (errstr, name);
rvals = error_mark_node;
}
if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE
&& ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
{
- cp_error ("conflicting return type specified for virtual function `%D'", fndecl);
+ cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
+ cp_error ("overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
}
break;
/* We cannot rely on some alien method to solve our problems,
so we must write out the debug info ourselves. */
if (write_symbols != DWARF_DEBUG)
- DECL_IGNORED_P (TYPE_NAME (t)) = 0;
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
if (! TREE_ASM_WRITTEN (TYPE_NAME (t)))
rest_of_type_compilation (t, global_bindings_p ());
}
n_outer_fields_searched = 0;
n_contexts_saved = 0;
}
-
-tree
-lookup_nested_tag (type, name)
- tree type, name;
-{
- tree tags = CLASSTYPE_TAGS (type);
-
- for (; tags; tags = TREE_CHAIN (tags))
- {
- /* The TREE_PURPOSE of an enum tag (which becomes a member of the
- enclosing class) is set to the name for the enum type. So, if
- name is `bar', and we strike `baz' for `enum bar { baz }', then
- this test will be true. */
- if (TREE_PURPOSE (tags) == name)
- break;
- }
- if (tags)
- return TYPE_NAME (TREE_VALUE (tags));
-
- if (TYPE_CONTEXT (type))
- return lookup_nested_tag (TYPE_CONTEXT (type), name);
-
- return NULL_TREE;
-}
return instance;
vtbl = convert_pointer_to (ptr_type_node, instance);
- vtbl = build (PLUS_EXPR,
- build_pointer_type (build_pointer_type (memptr_type)),
- vtbl, convert (sizetype, delta2));
+ vtbl
+ = build (PLUS_EXPR,
+ build_pointer_type (build_pointer_type (vtable_entry_type)),
+ vtbl, convert (sizetype, delta2));
vtbl = build_indirect_ref (vtbl, NULL_PTR);
aref = build_array_ref (vtbl, size_binop (MINUS_EXPR,
index,
integer_one_node));
- aref = save_expr (aref);
+ if (! flag_vtable_thunks)
+ {
+ aref = save_expr (aref);
- /* Save the intermediate result in a SAVE_EXPR so we don't have to
- compute each component of the virtual function pointer twice. */
- if (/* !building_cleanup && */ TREE_CODE (aref) == INDIRECT_REF)
- TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
+ /* Save the intermediate result in a SAVE_EXPR so we don't have to
+ compute each component of the virtual function pointer twice. */
+ if (/* !building_cleanup && */ TREE_CODE (aref) == INDIRECT_REF)
+ TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
- delta = build (PLUS_EXPR, integer_type_node,
- build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node),
- delta);
+ delta = build (PLUS_EXPR, integer_type_node,
+ build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node),
+ delta);
+ }
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (*instance_ptrptr),
*instance_ptrptr,
convert (integer_type_node, delta));
- e2 = build_component_ref (aref, pfn_identifier, 0, 0);
+ if (flag_vtable_thunks)
+ e2 = aref;
+ else
+ e2 = build_component_ref (aref, pfn_identifier, 0, 0);
e3 = PFN_FROM_PTRMEMFUNC (function);
TREE_TYPE (e2) = TREE_TYPE (e3);
/* check to see if there is an assignment to `this' */
if (lhs == current_class_decl)
{
- if (flag_this_is_variable > 0
- && DECL_NAME (current_function_decl) != NULL_TREE
- && current_class_name != DECL_NAME (current_function_decl))
- warning ("assignment to `this' not in constructor or destructor");
+ if (DECL_NAME (current_function_decl) != NULL_TREE)
+ {
+ /* ARM 18.3.3 and draft standard section C.11 say that assigning
+ something to this is an anachronism. */
+ if (pedantic)
+ warning ("anachronistic assignment to `this' pointer");
+ else if (flag_this_is_variable > 0
+ && current_class_name != DECL_NAME (current_function_decl))
+ warning ("assignment to `this' not in constructor or destructor");
+ }
current_function_just_assigned_this = 1;
}
{
/* Allow array assignment in compiler-generated code. */
if ((pedantic || flag_ansi)
- && ! DECL_SYNTHESIZED (current_function_decl))
+ && ! DECL_ARTIFICIAL (current_function_decl))
pedwarn ("ANSI C++ forbids assignment between arrays");
/* Have to wrap this in RTL_EXPR for two cases:
{
tree init = build_method_call (exp, constructor_name_full (type),
build_tree_list (NULL_TREE, rhs),
- NULL_TREE, LOOKUP_NORMAL);
+ TYPE_BINFO (type), LOOKUP_NORMAL);
if (init == error_mark_node)
return error_mark_node;
/* Return a tree node for the expression TYPENAME '(' PARMS ')'.
- Because we cannot tell whether this construct is really
- a function call or a call to a constructor or a request for
- a type conversion, we try all three, and report any ambiguities
- we find. */
+ Because we cannot tell whether this construct is really a call to a
+ constructor or a request for a type conversion, we try both, and
+ report any ambiguities we find. */
tree
build_functional_cast (exp, parms)
tree exp;
or a C cast in C++'s `functional' notation. */
tree type, name = NULL_TREE;
tree expr_as_ctor = NULL_TREE;
- tree expr_as_method = NULL_TREE;
- tree expr_as_fncall = NULL_TREE;
tree expr_as_conversion = NULL_TREE;
if (exp == error_mark_node || parms == error_mark_node)
name = DECL_NAME (name);
}
- /* Try evaluating as a call to a function. */
- if (IDENTIFIER_CLASS_VALUE (name)
- && (TREE_CODE (IDENTIFIER_CLASS_VALUE (name)) == TREE_LIST
- || TREE_CODE (IDENTIFIER_CLASS_VALUE (name)) == FUNCTION_DECL))
- {
- expr_as_method = build_method_call (current_class_decl, name, parms,
- NULL_TREE, LOOKUP_SPECULATIVELY);
- if (expr_as_method == error_mark_node)
- expr_as_method = NULL_TREE;
- }
-
- if (IDENTIFIER_GLOBAL_VALUE (name)
- && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TREE_LIST
- || TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == FUNCTION_DECL))
- {
- expr_as_fncall = build_overload_call (name, parms, 0,
- (struct candidate *)0);
- if (expr_as_fncall == NULL_TREE)
- expr_as_fncall = error_mark_node;
- }
-
if (! IS_AGGR_TYPE (type))
{
/* this must build a C cast */
if (parms == NULL_TREE)
- {
- if (expr_as_method || expr_as_fncall)
- goto return_function;
-
- return build1 (NOP_EXPR, type, integer_zero_node);
- }
- if (expr_as_method
- || (expr_as_fncall && expr_as_fncall != error_mark_node))
- {
- cp_error ("ambiguity between cast to `%#T' and function call", type);
- return error_mark_node;
- }
+ return build1 (NOP_EXPR, type, integer_zero_node);
return build_c_cast (type, build_compound_expr (parms));
}
if (TYPE_SIZE (type) == NULL_TREE)
{
- if (expr_as_method || expr_as_fncall)
- goto return_function;
cp_error ("type `%T' is not yet defined", type);
return error_mark_node;
}
expr_as_conversion
= build_type_conversion (CONVERT_EXPR, type, TREE_VALUE (parms), 0);
- if (! TYPE_NEEDS_CONSTRUCTING (type) && parms != NULL_TREE)
+ if (! TYPE_HAS_CONSTRUCTOR (type) && parms != NULL_TREE)
{
char *msg = 0;
}
else msg = "type `%T' does not have a constructor";
- if ((expr_as_method || expr_as_fncall) && expr_as_conversion)
- msg = "ambiguity between conversion to `%T' and function call";
- else if (expr_as_method || expr_as_fncall)
- goto return_function;
- else if (expr_as_conversion)
+ if (expr_as_conversion)
return expr_as_conversion;
cp_error (msg, type);
return error_mark_node;
}
-#if 0
- /* Constructors are not inherited... --jason */
- if (! TYPE_HAS_CONSTRUCTOR (type))
- {
- if (expr_as_method || expr_as_fncall)
- goto return_function;
- if (expr_as_conversion)
- return expr_as_conversion;
-
- /* Look through this type until we find the
- base type which has a constructor. */
- do
- {
- tree binfos = TYPE_BINFO_BASETYPES (type);
- int i, index = 0;
-
- while (binfos && TREE_VEC_LENGTH (binfos) == 1
- && ! TYPE_HAS_CONSTRUCTOR (type))
- {
- type = BINFO_TYPE (TREE_VEC_ELT (binfos, 0));
- binfos = TYPE_BINFO_BASETYPES (type);
- }
- if (TYPE_HAS_CONSTRUCTOR (type))
- break;
- /* Hack for MI. */
- i = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- if (i == 0) break;
- while (--i > 0)
- {
- if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (TREE_VEC_ELT (binfos, i))))
- {
- if (index == 0)
- index = i;
- else
- {
- error ("multiple base classes with constructor, ambiguous");
- type = 0;
- break;
- }
- }
- }
- if (type == 0)
- break;
- } while (! TYPE_HAS_CONSTRUCTOR (type));
- if (type == 0)
- return error_mark_node;
- }
- name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
-
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 321);
-#endif
-
{
int flags = LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN;
if (expr_as_ctor && expr_as_ctor != error_mark_node)
{
-#if 0
- /* mrs Mar 12, 1992 I claim that if it is a constructor, it is
- impossible to be an expr_as_method, without being a
- constructor call. */
- if (expr_as_method
- || (expr_as_fncall && expr_as_fncall != error_mark_node))
-#else
- if (expr_as_fncall && expr_as_fncall != error_mark_node)
-#endif
- {
- cp_warning ("function hides constructor for class `%T'", type);
- return expr_as_fncall;
- }
- else if (expr_as_conversion && expr_as_conversion != error_mark_node)
+ if (expr_as_conversion && expr_as_conversion != error_mark_node)
{
/* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
cp_error ("ambiguity between conversion to `%T' and constructor",
}
if (expr_as_conversion)
- {
- if (expr_as_method || expr_as_fncall)
- {
- cp_error ("ambiguity between conversion to `%T' and function call",
- type);
- return error_mark_node;
- }
- return expr_as_conversion;
- }
- return_function:
- if (expr_as_method)
- return build_method_call (current_class_decl, name, parms,
- NULL_TREE, LOOKUP_NORMAL);
- if (expr_as_fncall)
- return expr_as_fncall == error_mark_node
- ? build_overload_call (name, parms, LOOKUP_COMPLAIN, (struct candidate *)0)
- : expr_as_fncall;
+ return expr_as_conversion;
+
cp_error ("no suitable conversion to `%T' exists", type);
return error_mark_node;
}