diff options
author | Mike Stump <mrs@gcc.gnu.org> | 1996-11-12 19:49:48 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 1996-11-12 19:49:48 +0000 |
commit | 9a3b49acbc192d01f3138409547ba438607812a5 (patch) | |
tree | 85cd8cd7131e818db5e41babcf683a757099ac52 /gcc | |
parent | 3aad04640f70b2c9f75638e2c2143459df4461b7 (diff) | |
download | gcc-9a3b49acbc192d01f3138409547ba438607812a5.zip gcc-9a3b49acbc192d01f3138409547ba438607812a5.tar.gz gcc-9a3b49acbc192d01f3138409547ba438607812a5.tar.bz2 |
90th Cygnus<->FSF quick merge
From-SVN: r13141
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 109 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/class.c | 13 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 14 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 224 | ||||
-rw-r--r-- | gcc/cp/decl.c | 87 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 23 | ||||
-rw-r--r-- | gcc/cp/error.c | 38 | ||||
-rw-r--r-- | gcc/cp/lang-options.h | 2 | ||||
-rw-r--r-- | gcc/cp/method.c | 8 | ||||
-rw-r--r-- | gcc/cp/parse.y | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 47 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 22 | ||||
-rw-r--r-- | gcc/cp/search.c | 21 | ||||
-rw-r--r-- | gcc/cp/tree.c | 10 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 37 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 4 |
17 files changed, 399 insertions, 267 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b5cf22a..a5cd339 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,112 @@ +Tue Nov 12 08:39:17 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (cp_finish_decl): In MINIMAL_PARSE_MODE, only try to use + the DECL_VINDEX of DECL if it's set. + + * tree.c (mapcar): Handle RTL_EXPR. + +Mon Nov 11 13:57:31 1996 Jason Merrill <jason@yorick.cygnus.com> + + * pt.c (current_template_args): New fn. + (push_template_decl): Use it. + * decl.c (grokdeclarator): Use it. + + * decl2.c (build_expr_from_tree): Dereference ref vars. + + * decl.c (grokdeclarator): Generalize handling of TYPENAME_TYPEs in + the decl-specifier-seq. + + * decl.c (grok_op_properties): Don't force the type of a conversion + op to be complete. Don't warn about converting to the same type + for template instantiations. + + * decl2.c (finish_file): Don't call instantiate_decl on synthesized + methods. + +Mon Nov 11 13:20:34 1996 Bob Manson <manson@charmed.cygnus.com> + + * typeck.c (get_delta_difference): Remove previous bogusness. + Don't give errors if force is set. + +Fri Nov 8 17:38:44 1996 Jason Merrill <jason@yorick.cygnus.com> + + * decl2.c (finish_file): Don't emit debug info. + * decl.c (start_function): Call note_debug_info_needed for context. + (start_decl): Likewise. + (cp_finish_decl): Not here. + (finish_function): Or here. + (pushdecl): Lose obsolete code. + (grokdeclarator): Still do the long long thing after complaining. + (finish_enum): Don't call rest_of_type_compilation + for DWARF. + * class.c (finish_struct_1): Don't call rest_of_type_compilation + for DWARF. + * search.c (dfs_debug_mark): For DWARF, just call + rest_of_type_compilation. + (note_debug_info_needed): Don't do anything if we're in a template. + * parse.y (named_complex_class_head_sans_basetype): Likewise. + * method.c (synthesize_method): For non-local classes, + push_to_top_level first. + +Fri Nov 8 11:52:28 1996 Bob Manson <manson@charmed.cygnus.com> + + * typeck.c (get_delta_difference): Add no_error parameter. + (build_ptrmemfunc): Call get_delta_difference with no_error set; + we don't want error messages when converting unrelated + pointer-to-member functions. + +Thu Nov 7 11:16:24 1996 Mike Stump <mrs@cygnus.com> + + * error.c (dump_expr): Improve the wording on error messages that + involve pointer to member functions. + +Tue Nov 5 17:12:05 1996 Mike Stump <mrs@cygnus.com> + + * cvt.c (cp_convert_to_pointer): Move code for conversions from + (::*)() to void* or (*)() up a bit, so that we can convert from + METHOD_TYPEs as well. + +Tue Nov 5 14:54:17 1996 Jason Merrill <jason@yorick.cygnus.com> + + * rtti.c (get_tinfo_fn): Make sure 'type' is permanent. + There are no 'member' types. + (get_tinfo_fn_dynamic): Diagnose typeid of overloaded fn. + (build_x_typeid): Handle errors. + +Mon Nov 4 17:43:12 1996 Mike Stump <mrs@cygnus.com> + + * typeck.c (convert_for_assignment): Handle anachronistic implicit + conversions from (::*)() to void* or (*)(). + * cvt.c (cp_convert_to_pointer): Likewise. + (cp_convert_to_pointer_force): Remove cp_convert_to_pointer + conversions from here. + * decl2.c (lang_decode_option): Add -W{no-,}pmf-conversions. + * lang-options.h: Likewise. + * decl2.c (warn_pmf2ptr): Define. + * cp-tree.h: Declare it. + * typeck2.c (digest_init): Allow pmfs down into + convert_for_initialization. + +Sun Nov 3 09:43:00 1996 Jason Merrill <jason@yorick.cygnus.com> + + * typeck.c (c_expand_return): Fix for returning overloaded fn. + +Fri Nov 1 08:53:17 1996 Jason Merrill <jason@yorick.cygnus.com> + + * cp-tree.h (DIRECT_BIND): Change from INDIRECT_BIND. + * decl.c (grok_reference_init): Pass DIRECT_BIND. + * cvt.c (build_up_reference): Don't mark 'this' addressable. Use + DIRECT_BIND. + * call.c (convert_like): Don't pass INDIRECT_BIND. + * typeck.c (convert_arguments): Likewise. + * typeck.c (mark_addressable): Allow &this if flag_this_is_variable. + +Thu Oct 31 17:08:49 1996 Jason Merrill <jason@yorick.cygnus.com> + + * typeck.c (mark_addressable): Support TARGET_EXPR, unify with + similar code in build_up_ref. + * cvt.c (build_up_reference): Drastically simplify. + Mon Oct 28 12:45:05 1996 Jeffrey A Law (law@cygnus.com) * typeck.c (signed_or_unsigned_type): If the given type already diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 80258c0..576ed3a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4900,7 +4900,7 @@ convert_like (convs, expr) case REF_BIND: return convert_to_reference (TREE_TYPE (convs), expr, - CONV_IMPLICIT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION|INDIRECT_BIND, + CONV_IMPLICIT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION, error_mark_node); case LVALUE_CONV: return decay_conversion (expr); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 28391dc..356c9ca 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -873,7 +873,7 @@ modify_vtable_entry (old_entry_in_list, new_entry, fndecl) } } -/* Access the virtual function table entry i. VIRTUALS is the virtual +/* Access the virtual function table entry N. VIRTUALS is the virtual function table's initializer. */ static tree @@ -4188,7 +4188,10 @@ finish_struct_1 (t, warn_anon) For example, if a member function is seen and we decide to write out that member function, then we can change the value of the DECL_IGNORED_P slot, and the type will be output when - that member function's debug info is written out. */ + that member function's debug info is written out. + + We can't do this with DWARF, which does not support name + references between translation units. */ if (CLASSTYPE_METHOD_VEC (t)) { extern tree pending_vtables; @@ -4209,10 +4212,10 @@ finish_struct_1 (t, warn_anon) } else if (CLASSTYPE_INTERFACE_ONLY (t)) TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1; - } - /* Finish debugging output for this type. */ - rest_of_type_compilation (t, toplevel_bindings_p ()); + /* Finish debugging output for this type. */ + rest_of_type_compilation (t, toplevel_bindings_p ()); + } return t; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4326491..f9f76a3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -243,6 +243,11 @@ extern int warn_format; extern int warn_nonvdtor; +/* Non-zero means warn when we convert a pointer to member function + into a pointer to (void or function). */ + +extern int warn_pmf2ptr; + /* Non-zero means warn when a function is declared extern and later inline. */ extern int warn_extern_inline; @@ -1845,9 +1850,9 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already in the parameter list. LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried. - INDIRECT_BIND means that if a temporary is created, it should be created so - that it lives only as long as WITH_CLEANUP_EXPRs live, else if a temporary - is created then it should live as long as the current variable bindings. + DIRECT_BIND means that if a temporary is created, it should be created so + that it lives as long as the current variable bindings; otherwise it + only lives until the end of the complete-expression. LOOKUP_SPECULATIVELY means return NULL_TREE if we cannot find what we are after. Note, LOOKUP_COMPLAIN is checked and error messages printed before LOOKUP_SPECULATIVELY is checked. @@ -1865,7 +1870,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ #define LOOKUP_HAS_IN_CHARGE (32) #define LOOKUP_SPECULATIVELY (64) #define LOOKUP_ONLYCONVERTING (128) -#define INDIRECT_BIND (256) +#define DIRECT_BIND (256) #define LOOKUP_NO_CONVERSION (512) #define LOOKUP_DESTRUCTOR (512) #define LOOKUP_NO_TEMP_BIND (1024) @@ -2290,6 +2295,7 @@ extern void begin_template_parm_list PROTO((void)); extern tree process_template_parm PROTO((tree, tree)); extern tree end_template_parm_list PROTO((tree)); extern void end_template_decl PROTO((void)); +extern tree current_template_args PROTO((void)); extern void push_template_decl PROTO((tree)); extern tree lookup_template_class PROTO((tree, tree, tree)); extern int uses_template_parms PROTO((tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index cd40b9a..68b3d6c 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -154,6 +154,50 @@ cp_convert_to_pointer (type, expr) if (TYPE_PTRMEMFUNC_P (intype)) intype = TYPE_PTRMEMFUNC_FN_TYPE (intype); + /* Handle anachronistic conversions from (::*)() to void* or (*)(). */ + if (TREE_CODE (type) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE + || TREE_TYPE (type) == void_type_node)) + { + /* Allow an implicit this pointer for pointer to member + functions. */ + if (TREE_CODE (intype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE) + { + tree decl, basebinfo; + tree fntype = TREE_TYPE (intype); + tree t = TYPE_METHOD_BASETYPE (fntype); + + if (current_class_type == 0 + || get_base_distance (t, current_class_type, 0, &basebinfo) + == -1) + { + decl = build1 (NOP_EXPR, t, error_mark_node); + } + else if (current_class_ptr == 0) + decl = build1 (NOP_EXPR, t, error_mark_node); + else + decl = current_class_ref; + + expr = build (OFFSET_REF, fntype, decl, expr); + } + + if (TREE_CODE (expr) == OFFSET_REF + && TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) + expr = resolve_offset_ref (expr); + if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) + expr = build_addr_func (expr); + if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) + { + if (TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE) + if (pedantic || warn_pmf2ptr) + cp_pedwarn ("converting from `%T' to `%T'", TREE_TYPE (expr), + type); + return build1 (NOP_EXPR, type, expr); + } + intype = TREE_TYPE (expr); + } + form = TREE_CODE (intype); if (form == POINTER_TYPE || form == REFERENCE_TYPE) @@ -282,44 +326,6 @@ convert_to_pointer_force (type, expr) form = TREE_CODE (intype); } - if (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) - { - /* Allow an implicit this pointer for pointer to member - functions. */ - if (TYPE_PTRMEMFUNC_P (intype)) - { - tree decl, basebinfo; - tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype)); - tree t = TYPE_METHOD_BASETYPE (fntype); - - if (current_class_type == 0 - || get_base_distance (t, current_class_type, 0, &basebinfo) == -1) - { - decl = build1 (NOP_EXPR, t, error_mark_node); - } - else if (current_class_ptr == 0) - decl = build1 (NOP_EXPR, t, error_mark_node); - else - decl = current_class_ref; - - expr = build (OFFSET_REF, fntype, decl, expr); - intype = TREE_TYPE (expr); - } - - if (TREE_CODE (expr) == OFFSET_REF && TREE_CODE (intype) == METHOD_TYPE) - expr = resolve_offset_ref (expr); - if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) - expr = build_addr_func (expr); - if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) - { - if (pedantic - && TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE) - cp_pedwarn ("cannot convert `%T' to `%T'", intype, type); - return build1 (NOP_EXPR, type, expr); - } - } - if (form == POINTER_TYPE) { intype = TYPE_MAIN_VARIANT (intype); @@ -355,7 +361,6 @@ convert_to_pointer_force (type, expr) } return build_vbase_path (code, type, expr, path, 0); } - return build1 (NOP_EXPR, type, expr); } return cp_convert_to_pointer (type, expr); @@ -366,7 +371,7 @@ convert_to_pointer_force (type, expr) value we have to begin with is in ARG. FLAGS controls how we manage access checking. - INDIRECT_BIND in FLAGS controls how any temporarys are generated. + DIRECT_BIND in FLAGS controls how any temporarys are generated. CHECKCONST controls if we report error messages on const subversion. */ static tree @@ -512,72 +517,20 @@ build_up_reference (type, arg, flags, checkconst) but complain if we need a reference to something declared as `register'. */ - case RESULT_DECL: - if (staticp (targ)) - literal_flag = 1; - TREE_ADDRESSABLE (targ) = 1; - put_var_into_stack (targ); - break; - case PARM_DECL: -#if 0 - if (targ == current_class_ptr) - { - error ("address of `this' not available"); -/* #if 0 */ - /* This code makes the following core dump the compiler on a sun4, - if the code below is used. - - class e_decl; - class a_decl; - typedef a_decl* a_ref; - - class a_s { - public: - a_s(); - void* append(a_ref& item); - }; - class a_decl { - public: - a_decl (e_decl *parent); - a_s generic_s; - a_s decls; - e_decl* parent; - }; - - class e_decl { - public: - e_decl(); - a_s implementations; - }; - - void foobar(void *); - - a_decl::a_decl(e_decl *parent) { - parent->implementations.append(this); - } - */ - - TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */ - put_var_into_stack (targ); - break; -/* #else */ - return error_mark_node; -/* #endif */ - } -#endif - /* Fall through. */ + /* 'this' is not an lvalue. */ + if (targ == current_class_ptr && ! flag_this_is_variable) + break; + + case RESULT_DECL: case VAR_DECL: case CONST_DECL: - if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ) - && !DECL_ARTIFICIAL (targ)) - cp_warning ("address needed to build reference for `%D', which is declared `register'", - targ); - else if (staticp (targ)) + if (staticp (targ)) literal_flag = 1; - TREE_ADDRESSABLE (targ) = 1; - put_var_into_stack (targ); + /* Fall through. */ + case TARGET_EXPR: + mark_addressable (targ); break; case COMPOUND_EXPR: @@ -632,75 +585,30 @@ build_up_reference (type, arg, flags, checkconst) TREE_REFERENCE_EXPR (rval) = 1; return rval; - case TARGET_EXPR: - TREE_ADDRESSABLE (targ) = 1; - put_var_into_stack (TREE_OPERAND (targ, 0)); - break; - default: break; } - if (TREE_ADDRESSABLE (targ) == 0) + if ((flags&DIRECT_BIND) + && ! real_lvalue_p (targ)) { - if (! (flags&INDIRECT_BIND) - && toplevel_bindings_p ()) + if (toplevel_bindings_p ()) { - tree temp = get_temp_name (argtype, 0); - /* Give this new temp some rtl and initialize it. */ - DECL_INITIAL (temp) = targ; - TREE_STATIC (temp) = 1; - cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); - /* Do this after declaring it static. */ - rval = build_unary_op (ADDR_EXPR, temp, 0); - TREE_TYPE (rval) = type; - literal_flag = TREE_CONSTANT (rval); - goto done; - } - - if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype)) - { - arg = build_cplus_new (argtype, targ); - } - else if (flags&INDIRECT_BIND) - { - /* This should be the default, not the below code. */ - /* All callers except grok_reference_init should probably - use INDIRECT_BIND. */ - tree slot = build (VAR_DECL, argtype); - layout_decl (slot, 0); - arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE); + arg = get_temp_name (argtype, 1); + literal_flag = 1; } else { - tree temp = get_temp_name (argtype, 0); - rval = build_unary_op (ADDR_EXPR, temp, 0); - if (binfo && !BINFO_OFFSET_ZEROP (binfo)) - rval = convert_pointer_to (target_type, rval); - else - TREE_TYPE (rval) = type; - - temp = build (MODIFY_EXPR, argtype, temp, arg); - TREE_SIDE_EFFECTS (temp) = 1; - return build (COMPOUND_EXPR, type, temp, rval); + arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype)); + DECL_ARTIFICIAL (arg) = 1; } + DECL_INITIAL (arg) = targ; + cp_finish_decl (arg, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); } - - if (! (flags&INDIRECT_BIND)) + else if (TREE_ADDRESSABLE (targ) == 0 && !(flags&DIRECT_BIND)) { - if (TREE_CODE (arg) == TARGET_EXPR) - { - tree decl = TREE_OPERAND (arg, 0); - tree cleanup; - - if (! toplevel_bindings_p () && ! DECL_RTL (decl)) - { - expand_decl (decl); - cleanup = maybe_build_cleanup (decl); - if (cleanup) - expand_decl_cleanup (decl, cleanup); - } - } + tree slot = build_decl (VAR_DECL, NULL_TREE, argtype); + arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE); } rval = build1 (ADDR_EXPR, type, arg); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7c8c28b..dbb2a90 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3085,20 +3085,6 @@ pushdecl (x) if (global_bindings_p ()) TYPE_NAME (type) = x; } - else - { - tree tname = DECL_NAME (name); - - /* This is a disgusting kludge for dealing with UPTs. */ - if (global_bindings_p () && ANON_AGGRNAME_P (tname)) - { - /* do gratuitous C++ typedefing, and make sure that - we access this type either through TREE_TYPE field - or via the tags list. */ - TYPE_NAME (TREE_TYPE (x)) = x; - pushtag (tname, TREE_TYPE (x), 0); - } - } my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140); if (type != error_mark_node @@ -5823,6 +5809,12 @@ start_decl (declarator, declspecs, initialized) } } + /* Do this before the decl is actually defined so that the DWARF debug + info for the class reflects the declaration, rather than the + definition, of this decl. */ + if (TREE_CODE (decl) == VAR_DECL && context) + note_debug_info_needed (context); + if (initialized) { if (! toplevel_bindings_p () @@ -6085,7 +6077,8 @@ grok_reference_init (decl, type, init, cleanupp) } tmp = convert_to_reference - (type, init, CONV_IMPLICIT, LOOKUP_SPECULATIVELY|LOOKUP_NORMAL, decl); + (type, init, CONV_IMPLICIT, + LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl); if (tmp == error_mark_node) goto fail; @@ -6218,7 +6211,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) { if (init && DECL_INITIAL (decl)) DECL_INITIAL (decl) = init; - if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl)) + if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl) + && DECL_VINDEX (decl)) { tree stmt = DECL_VINDEX (decl); DECL_VINDEX (decl) = NULL_TREE; @@ -6466,10 +6460,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) /* Let debugger know it should output info for this type. */ note_debug_info_needed (ttype); - if (TREE_STATIC (decl) && DECL_CONTEXT (decl) - && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') - note_debug_info_needed (DECL_CONTEXT (decl)); - if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) && DECL_SIZE (decl) != NULL_TREE && ! TREE_CONSTANT (DECL_SIZE (decl))) @@ -7813,7 +7803,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) { if (pedantic && ! in_system_header) pedwarn ("ANSI C++ does not support `long long'"); - else if (longlong) + if (longlong) error ("`long long long' is too long for GCC"); else longlong = 1; @@ -7834,18 +7824,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) else { type = TREE_TYPE (id); - if (TREE_CODE (type) == TYPENAME_TYPE - && TYPE_CONTEXT (type) == current_class_type) - { - /* Members of the current class get resolved immediately; - we couldn't catch this one earlier because we hadn't - pushed into the class yet. */ - if (TREE_TYPE (type)) - type = TREE_TYPE (type); - else - type = make_typename_type (TYPE_CONTEXT (type), - TYPE_IDENTIFIER (type)); - } TREE_VALUE (spec) = type; } goto found; @@ -8810,6 +8788,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ; else if (TREE_COMPLEXITY (declarator) == current_class_depth) { + /* Resolve any TYPENAME_TYPEs from the decl-specifier-seq + that refer to ctype. They couldn't be resolved earlier + because we hadn't pushed into the class yet. + Example: resolve 'B<T>::type' in + 'B<typename B<T>::type> B<T>::f () { }'. */ + if (current_template_parms + && uses_template_parms (type) + && uses_template_parms (current_class_type)) + { + tree args = current_template_args (); + type = tsubst (type, &TREE_VEC_ELT (args, 0), + TREE_VEC_LENGTH (args), NULL_TREE); + } + /* This pop_nested_class corresponds to the push_nested_class used to push into class scope for parsing the argument list of a function decl, in @@ -8831,19 +8823,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) } ctype = TREE_OPERAND (declarator, 0); - if (TREE_CODE (ctype) == TYPENAME_TYPE - && TYPE_CONTEXT (ctype) == current_class_type) - { - /* Members of the current class get resolved immediately; - we couldn't catch this one earlier because we hadn't - pushed into the class yet. */ - if (TREE_TYPE (ctype)) - ctype = TREE_TYPE (ctype); - else - ctype = make_typename_type (TYPE_CONTEXT (ctype), - TYPE_IDENTIFIER (ctype)); - } - if (sname == NULL_TREE) goto done_scoping; @@ -10139,7 +10118,7 @@ grok_op_properties (decl, virtualp, friendp) || name == ansi_opname[(int) METHOD_CALL_EXPR]) return; /* no restrictions on args */ - if (IDENTIFIER_TYPENAME_P (name)) + if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl)) { tree t = TREE_TYPE (name); if (TREE_CODE (t) == VOID_TYPE) @@ -10153,7 +10132,9 @@ grok_op_properties (decl, virtualp, friendp) if (t == current_class_type) what = "the same type"; + /* Don't force t to be complete here. */ else if (IS_AGGR_TYPE (t) + && TYPE_SIZE (t) && DERIVED_FROM_P (t, current_class_type)) what = "a base class"; @@ -10735,7 +10716,8 @@ finish_enum (enumtype, values) } /* Finish debugging output for this type. */ - rest_of_type_compilation (enumtype, global_bindings_p ()); + if (write_symbols != DWARF_DEBUG) + rest_of_type_compilation (enumtype, global_bindings_p ()); return enumtype; } @@ -11014,6 +10996,12 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) } } + /* Do this before the decl is actually defined so that the DWARF debug + info for the class reflects the declaration, rather than the + definition, of this decl. */ + if (DECL_FUNCTION_MEMBER_P (decl1)) + note_debug_info_needed (DECL_CLASS_CONTEXT (decl1)); + /* Warn if function was previously implicitly declared (but not if we warned then). */ if (! warn_implicit @@ -12000,9 +11988,6 @@ finish_function (lineno, call_poplevel, nested) mark_inline_for_output (fndecl); } - if (ctype && TREE_ASM_WRITTEN (fndecl)) - note_debug_info_needed (ctype); - current_function_returns_null |= can_reach_end; /* Since we don't normally go through c_expand_return for constructors, diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 4bd06a3..5055d20 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -42,7 +42,6 @@ extern tree cleanups_this_call; static void grok_function_init PROTO((tree, tree)); void import_export_decl (); extern int current_class_depth; -extern int symout_time; /* A list of virtual function tables we must make sure to write out. */ tree pending_vtables; @@ -242,6 +241,10 @@ int warn_reorder; /* Non-zero means warn when synthesis behavior differs from Cfront's. */ int warn_synth; +/* Non-zero means warn when we convert a pointer to member function + into a pointer to (void or function). */ +int warn_pmf2ptr = 1; + /* Nonzero means `$' can be in an identifier. See cccp.c for reasons why this breaks some obscure ANSI C programs. */ @@ -555,6 +558,8 @@ lang_decode_option (p) warn_reorder = setting; else if (!strcmp (p, "synth")) warn_synth = setting; + else if (!strcmp (p, "pmf-conversions")) + warn_pmf2ptr = setting; else if (!strcmp (p, "comment")) ; /* cpp handles this one. */ else if (!strcmp (p, "comments")) @@ -2642,9 +2647,6 @@ extern int parse_time, varconst_time; extern tree pending_templates; extern tree maybe_templates; -#define TIMEVAR(VAR, BODY) \ -do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0) - extern struct obstack permanent_obstack; extern tree get_id_2 (); @@ -2711,7 +2713,8 @@ finish_file () instantiate_class_template (decl); if (CLASSTYPE_TEMPLATE_INSTANTIATION (decl)) for (vars = TYPE_METHODS (decl); vars; vars = TREE_CHAIN (vars)) - instantiate_decl (vars); + if (! DECL_ARTIFICIAL (vars)) + instantiate_decl (vars); } else instantiate_decl (decl); @@ -2768,13 +2771,6 @@ finish_file () { tree decl = TREE_VALUE (vars); -#ifdef DWARF_DEBUGGING_INFO - /* Output DWARF information for file-scope tentative data object - declarations. */ - - if (write_symbols == DWARF_DEBUG) - TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 1)); -#endif if (DECL_TEMPLATE_INSTANTIATION (decl) && ! DECL_IN_AGGR_P (decl)) { @@ -3430,6 +3426,9 @@ build_expr_from_tree (t) case TYPEID_EXPR: return build_x_typeid (build_expr_from_tree (TREE_OPERAND (t, 0))); + case VAR_DECL: + return convert_from_reference (t); + default: return t; } diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 80eb8e9..5adab9d 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1262,6 +1262,44 @@ dump_expr (t, nop) break; case CONSTRUCTOR: + if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) + { + tree idx = build_component_ref (t, index_identifier, NULL_TREE, 0); + + if (integer_all_onesp (idx)) + { + tree pfn = PFN_FROM_PTRMEMFUNC (t); + dump_expr (pfn); + break; + } + if (TREE_CODE (idx) == INTEGER_CST + && TREE_INT_CST_HIGH (idx) == 0) + { + tree virtuals; + unsigned HOST_WIDE_INT n; + + t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t))); + t = TYPE_METHOD_BASETYPE (t); + virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t))); + + n = TREE_INT_CST_LOW (idx); + + /* Map vtable index back one, to allow for the null pointer to + member. */ + --n; + + while (n > 0 && virtuals) + { + --n; + virtuals = TREE_CHAIN (virtuals); + } + if (virtuals) + { + dump_expr (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals))); + break; + } + } + } OB_PUTC ('{'); dump_expr_list (CONSTRUCTOR_ELTS (t)); OB_PUTC ('}'); diff --git a/gcc/cp/lang-options.h b/gcc/cp/lang-options.h index 54c214e..1869aef 100644 --- a/gcc/cp/lang-options.h +++ b/gcc/cp/lang-options.h @@ -101,3 +101,5 @@ Boston, MA 02111-1307, USA. */ "-Wno-reorder", "-Wsynth", "-Wno-synth", + "-Wpmf-conversions", + "-Wno-pmf-conversions", diff --git a/gcc/cp/method.c b/gcc/cp/method.c index f032c9b..c7e3a87 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -2116,7 +2116,9 @@ synthesize_method (fndecl) tree context = hack_decl_function_context (fndecl); tree base = DECL_CLASS_CONTEXT (fndecl); - if (nested) + if (! context) + push_to_top_level (); + else if (nested) push_cp_function_context (context); interface_unknown = 1; @@ -2156,6 +2158,8 @@ synthesize_method (fndecl) } extract_interface_info (); - if (nested) + if (! context) + pop_from_top_level (); + else if (nested) pop_cp_function_context (context); } diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index d29d4a8..cb80c8e 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -2233,7 +2233,10 @@ named_complex_class_head_sans_basetype: { current_aggr = $1; if (TREE_CODE ($3) == TYPE_DECL) - $$ = $3; + { + $$ = $3; + note_debug_info_needed (DECL_CONTEXT ($$)); + } else { cp_error ("`%T' does not have a nested type named `%D'", diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f5f502d..46a8a14 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -198,26 +198,13 @@ end_template_decl () (void) get_pending_sizes (); /* Why? */ } -void -push_template_decl (decl) - tree decl; +/* Generate a valid set of template args from current_template_parms. */ + +tree +current_template_args () { tree header = current_template_parms; - tree tmpl; tree args = NULL_TREE; - tree info; - tree ctx = DECL_CONTEXT (decl) ? DECL_CONTEXT (decl) : current_class_type; - int primary = 0; - - /* Kludge! */ - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl) - && DECL_CLASS_CONTEXT (decl)) - ; - /* Note that this template is a "primary template" */ - else if (! ctx || ! CLASSTYPE_TEMPLATE_INFO (ctx) - /* || (processing_template_decl > CLASSTYPE_TEMPLATE_LEVEL (ctx)) */) - primary = 1; - while (header) { tree a = copy_node (TREE_VALUE (header)); @@ -236,8 +223,32 @@ push_template_decl (decl) header = TREE_CHAIN (header); } args = nreverse (args); + + /* FIXME Remove this when we support member templates. */ args = TREE_VALUE (args); + return args; +} + +void +push_template_decl (decl) + tree decl; +{ + tree tmpl; + tree args = NULL_TREE; + tree info; + tree ctx = DECL_CONTEXT (decl) ? DECL_CONTEXT (decl) : current_class_type; + int primary = 0; + + /* Kludge! */ + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl) + && DECL_CLASS_CONTEXT (decl)) + ; + /* Note that this template is a "primary template" */ + else if (! ctx || ! CLASSTYPE_TEMPLATE_INFO (ctx) + /* || (processing_template_decl > CLASSTYPE_TEMPLATE_LEVEL (ctx)) */) + primary = 1; + /* Partial specialization. */ if (TREE_CODE (decl) == TYPE_DECL && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl))) @@ -262,6 +273,8 @@ push_template_decl (decl) return; } + args = current_template_args (); + if (! ctx || TYPE_BEING_DEFINED (ctx)) { tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE); diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index f51ea64..1ecccd8 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -175,6 +175,12 @@ get_tinfo_fn_dynamic (exp) if (exp == error_mark_node) return error_mark_node; + if (type_unknown_p (exp)) + { + error ("typeid of overloaded function"); + return error_mark_node; + } + type = TREE_TYPE (exp); /* peel back references, so they match. */ @@ -244,6 +250,10 @@ build_x_typeid (exp) } exp = get_tinfo_fn_dynamic (exp); + + if (exp == error_mark_node) + return error_mark_node; + exp = build_call (exp, type, NULL_TREE); if (cond) @@ -316,9 +326,17 @@ tree get_tinfo_fn (type) tree type; { - tree name = build_overload_with_type (tinfo_fn_id, type); + tree name; tree d; + if (TREE_CODE (type) == OFFSET_TYPE) + type = TREE_TYPE (type); + if (TREE_CODE (type) == METHOD_TYPE) + type = build_function_type (TREE_TYPE (type), + TREE_CHAIN (TYPE_ARG_TYPES (type))); + + name = build_overload_with_type (tinfo_fn_id, type); + if (IDENTIFIER_GLOBAL_VALUE (name)) return IDENTIFIER_GLOBAL_VALUE (name); @@ -330,7 +348,7 @@ get_tinfo_fn (type) DECL_ARTIFICIAL (d) = 1; DECL_NOT_REALLY_EXTERN (d) = 1; DECL_MUTABLE_P (d) = 1; - TREE_TYPE (name) = type; + TREE_TYPE (name) = copy_to_permanent (type); pushdecl_top_level (d); make_function_rtl (d); assemble_external (d); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index ebb692d..f2b2a50 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2539,9 +2539,20 @@ dfs_debug_mark (binfo) CLASSTYPE_DEBUG_REQUESTED (t) = 1; - /* If interface info is known, the value of (?@@?) is correct. */ - if (methods == 0 - || CLASSTYPE_INTERFACE_KNOWN (t) + if (methods == 0) + return; + + /* We can't do the TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which + does not support name references between translation units. */ + if (write_symbols == DWARF_DEBUG) + { + rest_of_type_compilation (t, global_bindings_p ()); + return; + } + + /* If interface info is known, either we've already emitted the debug + info or we don't need to. */ + if (CLASSTYPE_INTERFACE_KNOWN (t) || (write_virtuals == 2 && TYPE_VIRTUAL_P (t))) return; @@ -3120,6 +3131,10 @@ note_debug_info_needed (type) tree type; { tree field; + + if (current_template_parms) + return; + dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp); for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 0d0dc05..c391d7a 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1592,6 +1592,16 @@ mapcar (t, func) TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); return t; + break; + + case RTL_EXPR: + t = copy_node (t); + if (RTL_EXPR_SEQUENCE (t)) + RTL_EXPR_SEQUENCE (t) = copy_rtx (RTL_EXPR_SEQUENCE (t)); + if (RTL_EXPR_RTL (t)) + RTL_EXPR_RTL (t) = copy_rtx (RTL_EXPR_RTL (t)); + return t; + break; case CONVERT_EXPR: case ADDR_EXPR: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 4c876f6..60c8f00 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2822,9 +2822,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) } else { - parmval = convert_for_initialization (return_loc, type, val, - flags|INDIRECT_BIND, - "argument passing", fndecl, i); + parmval = convert_for_initialization + (return_loc, type, val, flags, + "argument passing", fndecl, i); #ifdef PROMOTE_PROTOTYPES if ((TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE) @@ -4616,7 +4616,8 @@ mark_addressable (exp) case PARM_DECL: if (x == current_class_ptr) { - error ("address of `this' not available"); + if (! flag_this_is_variable) + error ("address of `this' not available"); TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */ put_var_into_stack (x); return 1; @@ -4649,8 +4650,10 @@ mark_addressable (exp) case CONST_DECL: case RESULT_DECL: - /* For C++, we don't warn about taking the address of a register - variable for CONST_DECLs; ARM p97 explicitly says it's okay. */ + if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) + && !DECL_ARTIFICIAL (x) && extra_warnings) + cp_warning ("address requested for `%D', which is declared `register'", + x); put_var_into_stack (x); TREE_ADDRESSABLE (x) = 1; return 1; @@ -4678,6 +4681,11 @@ mark_addressable (exp) TREE_ADDRESSABLE (x) = 1; return 1; + case TARGET_EXPR: + TREE_ADDRESSABLE (x) = 1; + mark_addressable (TREE_OPERAND (x, 0)); + return 1; + default: return 1; } @@ -6082,7 +6090,7 @@ get_delta_difference (from, to, force) binfo = get_binfo (from, to, 1); if (binfo == error_mark_node) { - error (" in pointer to member function conversion"); + error (" in pointer to member function conversiona"); return delta; } if (binfo == 0) @@ -6096,12 +6104,14 @@ get_delta_difference (from, to, force) binfo = get_binfo (to, from, 1); if (binfo == error_mark_node) { - error (" in pointer to member conversion"); + if (!force) + error (" in pointer to member conversion"); return delta; } if (binfo == 0) { - cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to); + if (!force) + cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to); return delta; } if (TREE_VIA_VIRTUAL (binfo)) @@ -6751,6 +6761,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) } else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs))) return convert (type, rhs); + /* Handle anachronistic conversions from (::*)() to void* or (*)(). */ + else if (TREE_CODE (type) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE + || TREE_TYPE (type) == void_type_node) + && TREE_TYPE (rhs) + && TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs))) + return convert (type, rhs); cp_error ("%s to `%T' from `%T'", errtype, type, rhstype); return error_mark_node; @@ -7180,7 +7197,7 @@ c_expand_return (retval) if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl)) /* It's already done for us. */; - else if (TYPE_MODE (TREE_TYPE (retval)) == VOIDmode) + else if (TREE_TYPE (retval) == void_type_node) { pedwarn ("return of void value in function returning non-void"); expand_expr_stmt (retval); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 9395cc8..1c00297 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -829,7 +829,9 @@ digest_init (type, init, tail) } init = element; } - while (TREE_CODE (init) == CONSTRUCTOR) + while (TREE_CODE (init) == CONSTRUCTOR + && ! (TREE_TYPE (init) + && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))) { cp_pedwarn ("braces around scalar initializer for `%T'", type); init = CONSTRUCTOR_ELTS (init); |