From a4443a085561a653c669edf833f5a1496f246b9b Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Fri, 13 May 1994 02:46:07 +0000 Subject: [PATCH] 37th Cygnus<->FSF merge From-SVN: r7290 --- gcc/cp/ChangeLog | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/cp/call.c | 39 ++++++------ gcc/cp/class.c | 18 +++++- gcc/cp/cp-tree.h | 23 ++++++- gcc/cp/cvt.c | 173 ++++++++++++++++++++++------------------------------ gcc/cp/decl.c | 141 +++++++++++++++++++++++++++---------------- gcc/cp/decl2.c | 7 ++- gcc/cp/except.c | 22 ++++--- gcc/cp/gxx.gperf | 5 +- gcc/cp/hash.h | 170 ++++++++++++++++++++++++++++------------------------ gcc/cp/init.c | 7 +-- gcc/cp/lex.c | 3 + gcc/cp/lex.h | 1 + gcc/cp/parse.y | 115 ++++++++++++++++------------------- gcc/cp/pt.c | 43 ++++++++++--- gcc/cp/search.c | 2 +- gcc/cp/tree.c | 3 - gcc/cp/typeck.c | 94 ++++++++++++++++------------- gcc/cp/typeck2.c | 9 ++- 19 files changed, 670 insertions(+), 385 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4b3b09d..bd2be26 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -2,6 +2,186 @@ Thu May 12 19:13:54 1994 Richard Earnshaw (rwe11@cl.cam.ac.uk) * g++.c: Use #ifdef for __MSDOS__, not #if. +Thu May 12 18:05:18 1994 Mike Stump (mrs@cygnus.com) + + * decl2.c (lang_f_options): Handle -fshort-temps. -fshort-temps + gives old behavior , and destroys temporaries earlier. Default + behavior now conforms to the ANSI working paper. + +Thu May 12 14:45:35 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck.c (build_modify_expr): Understand MODIFY_EXPR as an lvalue. + Use convert_force to convert the result of a recursive call when we + are dealing with a NOP_EXPR. Don't automatically wrap MODIFY_EXPRs + in COMPOUND_EXPRs any more. + (various): Lose pedantic_lvalue_warning. + (unary_complex_lvalue): Understand MODIFY_EXPR. + + * cvt.c (convert_to_reference): Allow DECL to be error_mark_node if + we don't know what we're initializing. + +Wed May 11 01:59:36 1994 Jason Merrill (jason@deneb.cygnus.com) + + * cvt.c (convert_to_reference): Modify to use convtype parameter. + Only create temporaries when initializing a reference, not when + casting. + (cp_convert): New main function. + (convert): Call cp_convert. + * cvt.c, decl.c, typeck.c: Fix calls to convert_to_reference. + * cp-tree.h (CONV_*): New constants used by conversion code for + selecting conversions to perform. + + * tree.c (lvalue_p): MODIFY_EXPRs are no longer lvalues. + + * typeck.c (build_{static,reinterpret,const_cast): Stubs that just + call build_c_cast. + * parse.y: Add {static,reinterpret,const}_cast. + * gxx.gperf: Ditto. + + * typeck.c (common_type): Allow methods with basetypes of different + UPTs. + (comptypes): Deal with UPTs. + (build_modify_expr): Wrap all MODIFY_EXPRs in a COMPOUND_EXPR. + + * pt.c (end_template_decl): Check for multiple definitions of member + templates. + + * call.c (build_method_call): Complain about calling an abstract + virtual from a constructor. + + * typeck.c (pointer_int_sum): Check for the integer operand being 0 + after checking the validity of the pointer operand. + + * typeck2.c (digest_init): Pedwarn about string initializer being + too long. + +Tue May 10 12:10:28 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl.c (push_overloaded_decl): Only throw away a builtin if the + decl in question is the artificial one. + + * parse.y (simple_stmt, switch): Use implicitly_scoped_stmt because + expand_{start,end}_case cannot happen in the middle of a block. + + * cvt.c (build_type_conversion_1): Use convert again. + +Tue May 10 11:52:04 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + + * typeck2.c (digest_init): Make sure we check for signed and + unsigned chars as well when warning about string initializers. + + * init.c (emit_base_init): Check if there's a DECL_NAME on the + member before trying to do an initialization for it. + +Tue May 10 11:34:37 1994 Mike Stump (mrs@cygnus.com) + + * except.c: Don't do anything useful when cross compiling. + +Tue May 10 03:04:13 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl.c (duplicate_decls): Fix up handling of builtins yet again. + (push_overloaded_decl): Ditto. + + * cvt.c (convert): Don't look for void type conversion. + +Mon May 9 18:05:41 1994 Jason Merrill (jason@deneb.cygnus.com) + + * init.c (do_friend): Only do a pushdecl for friends, not + pushdecl_top_level. + +Mon May 9 13:36:34 1994 Jim Wilson (wilson@sphagnum.cygnus.com) + + * decl.c (lookup_name_current_level): Put empty statement after + the label OUT to make the code valid C. + +Mon May 9 12:20:57 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck.c (build_binary_op_nodefault): Only complain about + comparing void * and a function pointer if void * is smaller. + +Sun May 8 01:29:13 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl.c (lookup_name_current_level): Move through temporary binding + levels. + + * parse.y (already_scoped_stmt): Revive. + (simple_stmt): Use it again. + + * decl.c (poplevel): Always call poplevel recursively if we're + dealing with a temporary binding level. + +Sat May 7 10:52:28 1994 Mike Stump (mrs@cygnus.com) + + * decl.c (finish_decl): Make sure we run cleanups for initial values + of decls. Cures memory leak. + * decl.c (expand_static_init): Ditto for static variables. + * decl2.c (finish_file): Ditto for globals. + +Sat May 7 03:57:44 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck.c (commonparms): Don't complain about redefining default + args. + + * decl.c (duplicate_decls): Don't complain twice about conflicting + function decls. + (decls_match): Don't look at default args. + (redeclaration_error_message): Complain about redefining default + args. + + * call.c (build_overload_call_real): Also deal with guiding + declarations coming BEFORE the template decl. + + * pt.c (unify): Allow different parms to have different + cv-qualifiers. + (unify): Allow trivial conversions on non-template parms. + +Fri May 6 03:53:23 1994 Jason Merrill (jason@deneb.cygnus.com) + + * pt.c (tsubst): Support OFFSET_TYPEs. + (unify): Ditto. + + * decl2.c (finish_decl_parsing): Call push_nested_class with a type. + + * init.c (build_offset_ref): Fix error message. + * search.c (lookup_field): Ditto. + + * call.c (build_scoped_method_call): Pass binfo to + build_method_call. + * typeck.c (build_object_ref): Ditto. + + * typeck2.c (binfo_or_else): Don't return a _TYPE. + + * class.c (finish_struct): Don't complain about re-use of inherited + names or shadowing of type decls. + * decl.c (pushdecl_class_level): Ditto. + + * decl.c (finish_enum): Set the type of all the enums. + + * class.c (finish_struct): Don't get confused by access decls. + + * cp-tree.h (TYPE_MAIN_DECL): New macro to get the _DECL for a + _TYPE. You can stop using TYPE_NAME for that now. + + * parse.y: Lose doing_explicit (check $0 instead). + * gxx.gperf: 'template' now has a RID. + * lex.h (rid): Ditto. + * lex.c (init_lex): Set up the RID for 'template'. + + * parse.y (type_specifier_seq): typed_typespecs or + nonempty_type_quals. Use it. + (handler_args): Fix bogus syntax. + (raise_identifier{,s}, optional_identifier): Lose. + * except.c (expand_start_catch_block): Use grokdeclarator to parse + the catch variable. + (init_exception_processing): The second argument to + __throw_type_match is ptr_type_node. + + Fri May 6 07:18:54 1994 Chip Salzenberg (chip@fin) + + [ change propagated from c-decl.c of snapshot 940429 ] + * cp/decl.c (finish_decl): Setting asmspec_tree should not + zero out the old RTL. + Fri May 6 01:25:38 1994 Mike Stump (mrs@cygnus.com) Add alpha exception handling support to the compiler. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 8f8bac2..6700f87 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2672,7 +2672,7 @@ build_scoped_method_call (exp, scopes, name, parms) } /* Call to a method. */ - return build_method_call (decl, name, parms, NULL_TREE, + return build_method_call (decl, name, parms, binfo, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); } return error_mark_node; @@ -3597,6 +3597,13 @@ build_method_call (instance, name, parms, basetype_path, flags) /* From here on down, BASETYPE is the type that INSTANCE_PTR's type (if it exists) is a pointer to. */ + if (DECL_ABSTRACT_VIRTUAL_P (function) + && instance == C_C_D + && DECL_CONSTRUCTOR_P (current_function_decl) + && ! (flags & LOOKUP_NONVIRTUAL) + && value_member (function, get_abstract_virtuals (basetype))) + cp_error ("abstract virtual `%#D' called from constructor", function); + if (IS_SIGNATURE (basetype) && static_call_context) { cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference", @@ -4046,22 +4053,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) TYPE_ARG_TYPES (TREE_TYPE (function)), parms, &template_cost, 0); if (i == 0) - { - struct candidate *cp2; - - function = instantiate_template (function, targs); - /* Now check that the template instantiated for this is not - the same as a function that's in the list due to some - previous instantiation. */ - cp2 = candidates; - while (cp2 != cp) - if (cp2->function == function) - break; - else - cp2 += 1; - if (cp2->function == function) - continue; - } + function = instantiate_template (function, targs); } if (TREE_CODE (function) == TEMPLATE_DECL) @@ -4076,6 +4068,19 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) } else { + struct candidate *cp2; + + /* Check that this decl is not the same as a function that's in + the list due to some template instantiation. */ + cp2 = candidates; + while (cp2 != cp) + if (cp2->function == function) + break; + else + cp2 += 1; + if (cp2->function == function) + continue; + function = DECL_MAIN_VARIANT (function); /* Can't use alloca here, since result might be diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 730d0ca..27e9a4b 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2734,10 +2734,22 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL) { tree name = DECL_NAME (x); - tree icv = name ? IDENTIFIER_CLASS_VALUE (name) : NULL_TREE; + tree icv; - /* Don't complain about constructors. */ - if (icv && name != constructor_name (current_class_type)) + /* Don't get confused by access decls. */ + if (name && TREE_CODE (name) == IDENTIFIER_NODE) + icv = IDENTIFIER_CLASS_VALUE (name); + else + icv = NULL_TREE; + + if (icv + /* Don't complain about constructors. */ + && name != constructor_name (current_class_type) + /* Or inherited names. */ + && id_in_current_class (name) + /* Or shadowed tags. */ + && !(TREE_CODE (icv) == TYPE_DECL + && DECL_CONTEXT (icv) == t)) { cp_error_at ("declaration of identifier `%D' as `%+#D'", name, x); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 54dc2b2..5d7cfa7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -321,6 +321,9 @@ enum languages { lang_c, lang_cplusplus }; #define TYPE_ASSEMBLER_NAME_STRING(NODE) (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE)))) #define TYPE_ASSEMBLER_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE)))) +/* The _DECL for this _TYPE. */ +#define TYPE_MAIN_DECL(NODE) (TYPE_NAME (NODE)) + #define IS_AGGR_TYPE(t) (TYPE_LANG_FLAG_5 (t)) #define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE || t == UNINSTANTIATED_P_TYPE) #define IS_AGGR_TYPE_2(TYPE1,TYPE2) \ @@ -1723,6 +1726,24 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ #define LOOKUP_NO_CONVERSION (512) #define LOOKUP_DESTRUCTOR (512) +/* These flags are used by the conversion code. + CONV_IMPLICIT : Perform implicit conversions (standard and user-defined). + CONV_STATIC : Perform the explicit conversions for static_cast. + CONV_CONST : Perform the explicit conversions for const_cast. + CONV_REINTERPRET: Perform the explicit conversions for reinterpret_cast. + CONV_PRIVATE : Perform upcasts to private bases. */ + +#define CONV_IMPLICIT 1 +#define CONV_STATIC 2 +#define CONV_CONST 4 +#define CONV_REINTERPRET 8 +#define CONV_PRIVATE 16 +#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC) +#define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ + | CONV_REINTERPRET) +#define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ + | CONV_REINTERPRET | CONV_PRIVATE) + /* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST): purpose = friend name (IDENTIFIER_NODE); value = TREE_LIST of FUNCTION_DECLS; @@ -1790,7 +1811,7 @@ extern void print_class_statistics PROTO((void)); extern void maybe_push_cache_obstack PROTO((void)); /* in cvt.c */ -extern tree convert_to_reference PROTO((tree, tree, tree, tree, int, char *, int, int)); +extern tree convert_to_reference PROTO((tree, tree, int, int, tree)); extern tree convert_from_reference PROTO((tree)); extern tree convert_to_aggr PROTO((tree, tree, char **, int)); extern tree convert_pointer_to PROTO((tree, tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index b160412..d614c70 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -594,40 +594,29 @@ build_up_reference (type, arg, flags, checkconst) /* For C++: Only need to do one-level references, but cannot get tripped up on signed/unsigned differences. - If DECL is NULL_TREE it means convert as though casting (by force). - If it is ERROR_MARK_NODE, it means the conversion is implicit, - and that temporaries may be created. - Make sure the use of user-defined conversion operators is un-ambiguous. - Otherwise, DECL is a _DECL node which can be used in error reporting. + DECL is either NULL_TREE or the _DECL node for a reference that is being + initialized. It can be error_mark_node if we don't know the _DECL but + we know it's an initialization. */ - FNDECL, PARMNUM, and ERRTYPE are only used when checking for use of - volatile or const references where they aren't desired. */ +tree cp_convert PROTO((tree, tree, int, int)); tree -convert_to_reference (decl, reftype, expr, fndecl, parmnum, - errtype, strict, flags) - tree decl; +convert_to_reference (reftype, expr, convtype, flags, decl) tree reftype, expr; - tree fndecl; - int parmnum; - char *errtype; - int strict, flags; + int convtype, flags; + tree decl; { register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); register tree intype = TREE_TYPE (expr); register enum tree_code form = TREE_CODE (intype); tree rval = NULL_TREE; -#if 0 - if (TREE_CODE (type) == ARRAY_TYPE) - type = build_pointer_type (TREE_TYPE (type)); -#endif - if (form == REFERENCE_TYPE) intype = TREE_TYPE (intype); intype = TYPE_MAIN_VARIANT (intype); if (IS_AGGR_TYPE (intype) + && ! (flags & LOOKUP_NO_CONVERSION) && (rval = build_type_conversion (CONVERT_EXPR, reftype, expr, 1))) { if (rval == error_mark_node) @@ -636,16 +625,11 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, return rval; } - if (comptypes (type, intype, strict)) + if (((convtype & CONV_STATIC) && comptypes (type, intype, -1)) + || ((convtype & CONV_IMPLICIT) && comptypes (type, intype, 0))) { - /* Section 13. */ if (flags & LOOKUP_COMPLAIN) { - /* Since convert_for_initialization didn't call - convert_for_assignment, we have to do this checking here. - FIXME: We should have a common routine between here and - convert_for_assignment. */ - tree ttl = TREE_TYPE (reftype); tree ttr; @@ -654,37 +638,25 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, else ttr = TREE_TYPE (expr); - if (! TYPE_READONLY (ttl)) + if (! lvalue_p (expr) && + (decl == NULL_TREE || ! TYPE_READONLY (ttl))) { - if (TYPE_READONLY (ttr) && decl != NULL_TREE) - { - if (fndecl) - cp_pedwarn ("passing `%T' as argument %P of `%D' discards const", - TREE_TYPE (expr), parmnum, fndecl); - else - cp_pedwarn ("%s to `%T' from `%T' discards const", - errtype, reftype, TREE_TYPE (expr)); - } - else if (! lvalue_p (expr)) - { - /* Ensure semantics of 8.4.3 */ - if (fndecl) - cp_pedwarn ("ANSI C++ forbids passing non-lvalue `%T' as argument %P of `%D' into non-const &", - TREE_TYPE (expr), parmnum, fndecl); - else - cp_pedwarn ("ANSI C++ forbids %s to `%T' from non-lvalue `%T'", - errtype, reftype, TREE_TYPE (expr)); - } + if (decl) + /* Ensure semantics of [dcl.init.ref] */ + cp_pedwarn ("initialization of non-const `%T' from rvalue `%T'", + reftype, intype); + else + cp_pedwarn ("conversion to `%T' from rvalue `%T'", + reftype, intype); } - else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr) - && decl != NULL_TREE) + else if (! (convtype & CONV_CONST)) { - if (fndecl) - cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile", - TREE_TYPE (expr), parmnum, fndecl); - else - cp_pedwarn ("%s to `%T' from `%T' discards volatile", - errtype, reftype, TREE_TYPE (expr)); + if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr)) + cp_pedwarn ("conversion from `%T' to `%T' discards const", + TREE_TYPE (expr), reftype); + else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) + cp_pedwarn ("conversion from `%T' to `%T' discards volatile", + TREE_TYPE (expr), reftype); } } @@ -718,15 +690,17 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, rval = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (expr))), expr); - rval = convert (build_pointer_type (TREE_TYPE (reftype)), rval); + rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), rval, + convtype, flags); rval = build1 (NOP_EXPR, reftype, rval); return rval; } - return build_up_reference (reftype, expr, flags, decl!=NULL_TREE); + return build_up_reference (reftype, expr, flags, + ! (convtype & CONV_CONST)); } - if (decl == NULL_TREE && lvalue_p (expr)) + if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { /* When casting an lvalue to a reference type, just convert into a pointer to the new type and deference it. This is allowed @@ -736,7 +710,7 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, /* B* bp; A& ar = (A&)bp; is legal, but it's probably not what they meant. */ if (form == POINTER_TYPE - && (comptypes (TREE_TYPE (intype), type, strict))) + && (comptypes (TREE_TYPE (intype), type, -1))) cp_warning ("casting `%T' to `%T' does not dereference pointer", intype, reftype); @@ -746,7 +720,7 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } - else if (decl == error_mark_node || decl == NULL_TREE) + else if (decl) { tree rval_as_conversion = NULL_TREE; tree rval_as_ctor = NULL_TREE; @@ -773,23 +747,25 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, if (global_bindings_p ()) { extern tree static_aggregates; - decl = get_temp_name (type, global_bindings_p ()); - init = build_method_call (decl, constructor_name_full (type), + tree t = get_temp_name (type, global_bindings_p ()); + init = build_method_call (t, constructor_name_full (type), build_tree_list (NULL_TREE, expr), - TYPE_BINFO (type), LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); + TYPE_BINFO (type), + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); if (init == error_mark_node) return error_mark_node; - make_decl_rtl (decl, NULL_PTR, 1); - static_aggregates = perm_tree_cons (expr, decl, static_aggregates); - rval = build_unary_op (ADDR_EXPR, decl, 0); + make_decl_rtl (t, NULL_PTR, 1); + static_aggregates = perm_tree_cons (expr, t, static_aggregates); + rval = build_unary_op (ADDR_EXPR, t, 0); } else { init = build_method_call (NULL_TREE, constructor_name_full (type), build_tree_list (NULL_TREE, expr), - TYPE_BINFO (type), LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); + TYPE_BINFO (type), + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); if (init == error_mark_node) return error_mark_node; @@ -820,8 +796,8 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, } if (rval && ! TYPE_READONLY (TREE_TYPE (reftype))) - cp_pedwarn ("converting `%T' to non-const `%T' will use a temporary", - intype, reftype); + cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary", + reftype, intype); } if (rval) @@ -1219,15 +1195,10 @@ convert_pointer_to_vbase (binfo, expr) return NULL_TREE; } -/* Create an expression whose value is that of EXPR, - converted to type TYPE. The TREE_TYPE of the value - is always TYPE. This function implements all reasonable - conversions; callers should filter out those that are - not permitted by the language being compiled. */ - tree -convert (type, expr) +cp_convert (type, expr, convtype, flags) tree type, expr; + int convtype, flags; { register tree e = expr; register enum tree_code code = TREE_CODE (type); @@ -1235,25 +1206,16 @@ convert (type, expr) if (type == TREE_TYPE (expr) || TREE_CODE (expr) == ERROR_MARK) return expr; - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) - return fold (build1 (NOP_EXPR, type, expr)); if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) return error_mark_node; - if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE) - { - error ("void value not ignored as it ought to be"); - return error_mark_node; - } - if (code == VOID_TYPE) - { - /* We're converting to a void type; see if they have an - `operator void'. */ - tree rval = build_type_conversion (NOP_EXPR, type, e, 0); - /* If we can convert to void type via a type conversion, do so. */ - if (rval) - return rval; - return build1 (CONVERT_EXPR, type, e); - } + + /* Trivial conversion: cv-qualifiers do not matter on rvalues. */ + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) + return fold (build1 (NOP_EXPR, type, expr)); + + if (code == VOID_TYPE && (convtype & CONV_STATIC)) + return build1 (CONVERT_EXPR, type, e); + #if 0 /* This is incorrect. A truncation can't be stripped this way. Extensions will be stripped by the use of get_unwidened. */ @@ -1268,10 +1230,8 @@ convert (type, expr) code = TREE_CODE (type); } - /* C++ */ if (code == REFERENCE_TYPE) - return fold (convert_to_reference (error_mark_node, type, e, NULL_TREE, - -1, "conversion", -1, LOOKUP_NORMAL)); + return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE)); else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) e = convert_from_reference (e); @@ -1455,6 +1415,19 @@ convert (type, expr) return error_mark_node; } +/* Create an expression whose value is that of EXPR, + converted to type TYPE. The TREE_TYPE of the value + is always TYPE. This function implements all reasonable + conversions; callers should filter out those that are + not permitted by the language being compiled. */ + +tree +convert (type, expr) + tree type, expr; +{ + return cp_convert (type, expr, CONV_OLD_CONVERT, 0); +} + /* Like convert, except permit conversions to take place which are not normally allowed due to access restrictions (such as conversion from sub-type to private super-type). */ @@ -1467,8 +1440,8 @@ convert_force (type, expr) register enum tree_code code = TREE_CODE (type); if (code == REFERENCE_TYPE) - return fold (convert_to_reference (0, type, e, NULL_TREE, -1, - "casting", -1, LOOKUP_COMPLAIN)); + return fold (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN, + NULL_TREE)); else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) e = convert_from_reference (e); @@ -1539,11 +1512,7 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure) && (TREE_READONLY (TREE_TYPE (TREE_TYPE (rval))) > TREE_READONLY (TREE_TYPE (xtype)))) warning ("user-defined conversion casting away `const'"); - rval = convert_for_initialization (NULL_TREE, xtype, rval, flags, - "conversion", NULL_TREE, 0); - if (rval == error_mark_node) - return NULL_TREE; - return rval; + return convert (xtype, rval); } /* Convert an aggregate EXPR to type XTYPE. If a conversion diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e33db79..1c9905f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -47,6 +47,8 @@ extern struct obstack permanent_obstack; extern int current_class_depth; +extern tree cleanups_this_call; + /* Stack of places to restore the search obstack back to. */ /* Obstack used for remembering local class declarations (like @@ -1077,7 +1079,7 @@ poplevel (keep, reverse, functionbody) } /* Take care of compiler's internal binding structures. */ - if (tmp == 2 && class_binding_level) + if (tmp == 2) { #if 0 /* We did not call push_momentary for this @@ -1976,7 +1978,7 @@ decls_match (newdecl, olddecl) TREE_TYPE (newdecl) = TREE_TYPE (olddecl); } else - types_match = compparms (p1, p2, 1); + types_match = compparms (p1, p2, 3); } else types_match = 0; @@ -2114,31 +2116,44 @@ duplicate_decls (newdecl, olddecl) after implicit decl. */ ; 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. */ + && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl))) { /* If you declare a built-in or predefined function name as static, - the old definition is overridden, - but optionally warn this was a bad choice of name. */ - if (! TREE_PUBLIC (newdecl)) - 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 + the old definition is overridden, but optionally warn this was a + bad choice of name. Ditto for overloads. */ + if (! TREE_PUBLIC (newdecl) + || (TREE_CODE (newdecl) == FUNCTION_DECL + && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))) + { + if (warn_shadow) + cp_warning ("shadowing %s function `%#D'", + DECL_BUILT_IN (olddecl) ? "built-in" : "library", + olddecl); + /* Discard the old built-in function. */ + return 0; + } + else if (! types_match) { + if (TREE_CODE (newdecl) != FUNCTION_DECL) + { + /* If the built-in is not ansi, then programs can override + it even globally without an error. */ + if (! DECL_BUILT_IN (olddecl)) + cp_warning ("library function `%#D' redeclared as non-function `%#D'", + olddecl, newdecl); + else + { + cp_error ("declaration of `%#D'", newdecl); + cp_error ("conflicts with built-in declaration `%#D'", + olddecl); + } + return 0; + } + cp_warning ("declaration of `%#D'", newdecl); cp_warning ("conflicts with built-in declaration `%#D'", olddecl); } - return 0; } else if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) { @@ -2185,7 +2200,7 @@ duplicate_decls (newdecl, olddecl) } /* Already complained about this, so don't do so again. */ - if (current_class_type == NULL_TREE + else if (current_class_type == NULL_TREE || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type) { /* Since we're doing this before finish_struct can set the @@ -3082,7 +3097,12 @@ pushdecl_class_level (x) members are checked in finish_struct. */ tree icv = IDENTIFIER_CLASS_VALUE (name); - if (icv) + if (icv + /* Don't complain about inherited names. */ + && id_in_current_class (name) + /* Or shadowed tags. */ + && !(TREE_CODE (icv) == TYPE_DECL + && DECL_CONTEXT (icv) == current_class_type)) { cp_error ("declaration of identifier `%D' as `%#D'", name, x); cp_error_at ("conflicts with previous use in class as `%#D'", @@ -3186,23 +3206,18 @@ push_overloaded_decl (decl, forgettable) { old = IDENTIFIER_GLOBAL_VALUE (orig_name); if (old && TREE_CODE (old) == FUNCTION_DECL + && DECL_ARTIFICIAL (old) && (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); - } + if (duplicate_decls (decl, old)) + return old; old = NULL_TREE; } } else { old = IDENTIFIER_LOCAL_VALUE (orig_name); - + if (! purpose_member (orig_name, current_binding_level->shadowed)) { current_binding_level->shadowed @@ -3355,6 +3370,18 @@ redeclaration_error_message (newdecl, olddecl) else return "redefinition of `%#D'"; } + + { + tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); + tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); + + if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE) + t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2); + + for (; t1; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) + if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) + return "duplicate default arguments given for `%#D'"; + } return 0; } else if (TREE_CODE (newdecl) == TEMPLATE_DECL) @@ -3990,9 +4017,19 @@ lookup_name_current_level (name) } else if (IDENTIFIER_LOCAL_VALUE (name) != NULL_TREE) { - for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) - if (DECL_NAME (t) == name) - break; + struct binding_level *b = current_binding_level; + while (1) + { + for (t = b->names; t; t = TREE_CHAIN (t)) + if (DECL_NAME (t) == name) + goto out; + if (b->keep == 2) + b = b->level_chain; + else + break; + } + out: + ; } return t; @@ -5559,25 +5596,14 @@ grok_reference_init (decl, type, init, cleanupp) } /* OK, can we generate a reference then? */ else if ((actual_init = convert_to_reference - (decl, type, init, 0, 0, "initialization", 0, - LOOKUP_SPECULATIVELY|LOOKUP_NORMAL))) + (type, init, CONV_IMPLICIT, + LOOKUP_SPECULATIVELY|LOOKUP_NORMAL, decl))) { if (actual_init == error_mark_node) goto fail; init = actual_init; is_reference = 1; - } - /* OK, try going through a temporary. */ - else if ((actual_init = convert_to_reference - (error_mark_node, type, init, 0, 0, "initialization", - 0, LOOKUP_NORMAL))) - { - if (actual_init == error_mark_node) - goto fail; - - init = actual_init; - is_reference = 1; if (TREE_CODE (init) == WITH_CLEANUP_EXPR) { @@ -5705,12 +5731,9 @@ finish_decl (decl, init, asmspec_tree, need_pop) return; } + /* If a name was specified, get the string. */ if (asmspec_tree) - { asmspec = TREE_STRING_POINTER (asmspec_tree); - /* Zero out old RTL, since we will rewrite it. */ - DECL_RTL (decl) = NULL_RTX; - } /* If the type of the thing we are declaring either has a constructor, or has a virtual function table pointer, @@ -6276,6 +6299,7 @@ finish_decl (decl, init, asmspec_tree, need_pop) } else if (! toplev) { + tree old_cleanups = cleanups_this_call; /* This is a declared decl which must live until the end of the binding contour. It may need a cleanup. */ @@ -6335,6 +6359,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) decl); } } + /* Cleanup any temporaries needed for the initial value. */ + expand_cleanups_to (old_cleanups); } finish_end0: @@ -6404,6 +6430,8 @@ expand_static_init (decl, init) tree init; { tree oldstatic = value_member (decl, static_aggregates); + tree old_cleanups; + if (oldstatic) { if (TREE_PURPOSE (oldstatic) && init != NULL_TREE) @@ -6422,6 +6450,7 @@ expand_static_init (decl, init) rest_of_decl_compilation (temp, NULL_PTR, 0, 0); expand_start_cond (build_binary_op (EQ_EXPR, temp, integer_zero_node, 1), 0); + old_cleanups = cleanups_this_call; expand_assignment (temp, integer_one_node, 0, 0); if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) { @@ -6430,6 +6459,8 @@ expand_static_init (decl, init) } else expand_assignment (decl, init, 0, 0); + /* Cleanup any temporaries needed for the initial value. */ + expand_cleanups_to (old_cleanups); expand_end_cond (); if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl))) { @@ -10235,6 +10266,7 @@ finish_enum (enumtype, values) else if (value < minvalue) minvalue = value; TREE_TYPE (TREE_VALUE (pair)) = enumtype; + TREE_TYPE (DECL_INITIAL (TREE_VALUE (pair))) = enumtype; } } @@ -11968,3 +12000,10 @@ revert_static_member_fn (decl, fn, argtypes) if (argtypes) *argtypes = args; } + +int +id_in_current_class (id) + tree id; +{ + return !!purpose_member (id, class_binding_level->class_shadowed); +} diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index d6eb5d9..c5ab8db 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -37,6 +37,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ extern tree grokdeclarator (); extern tree get_file_function_name (); +extern tree cleanups_this_call; static void grok_function_init (); /* A list of virtual function tables we must make sure to write out. */ @@ -362,6 +363,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = {"huge-objects", &flag_huge_objects, 1}, {"conserve-space", &flag_conserve_space, 1}, {"vtable-thunks", &flag_vtable_thunks, 1}, + {"short-temps", &flag_short_temps, 1}, }; /* Decode the string P as a language-specific option. @@ -2595,6 +2597,7 @@ finish_file () { tree decl = TREE_VALUE (vars); tree init = TREE_PURPOSE (vars); + tree old_cleanups = cleanups_this_call; /* If this was a static attribute within some function's scope, then don't initialize it here. Also, don't bother @@ -2684,6 +2687,8 @@ finish_file () ; else my_friendly_abort (22); vars = TREE_CHAIN (vars); + /* Cleanup any temporaries needed for the initial value. */ + expand_cleanups_to (old_cleanups); } expand_end_bindings (getdecls(), 1, 0); @@ -2936,7 +2941,7 @@ finish_decl_parsing (decl) TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0)); return decl; case SCOPE_REF: - push_nested_class (TREE_OPERAND (decl, 0), 3); + push_nested_class (TREE_TYPE (TREE_OPERAND (decl, 0)), 3); TREE_COMPLEXITY (decl) = current_class_depth; return decl; case ARRAY_REF: diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 60fd392..160a10b 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -35,11 +35,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ tree builtin_return_address_fndecl; /* Define at your own risk! */ +#ifndef CROSS_COMPILE #ifdef sun #ifdef sparc #define TRY_NEW_EH #endif #endif +#endif #ifndef TRY_NEW_EH @@ -97,8 +99,8 @@ expand_end_all_catch () } void -expand_start_catch_block (typename, identifier) - tree typename, identifier; +expand_start_catch_block (declspecs, declarator) + tree declspecs, declarator; { } @@ -409,7 +411,6 @@ exception_section () extern rtx emit_insn PROTO((rtx)); extern rtx gen_nop PROTO(()); -extern void do_unwind PROTO((rtx)); /* local globals for function calls ====================================================================== */ @@ -808,7 +809,7 @@ init_exception_processing () catch_match_fndecl = define_function ("__throw_type_match", build_function_type (integer_type_node, - tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, string_type_node, void_list_node))), + tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node))), NOT_BUILT_IN, pushdecl, 0); @@ -1088,24 +1089,27 @@ expand_leftover_cleanups () } } - /* call this to start a catch block. Typename is the typename, and identifier is the variable to place the object in or NULL if the variable doesn't matter. If typename is NULL, that means its a "catch (...)" or catch everything. In that case we don't need to do any type checking. (ie: it ends up as the "else" clause rather than an "else if" clause) */ void -expand_start_catch_block (typename, identifier) - tree typename, identifier; +expand_start_catch_block (declspecs, declarator) + tree declspecs, declarator; { rtx false_label_rtx; tree type; + tree decl; if (! doing_eh (1)) return; - if (typename) - type = groktypename (typename); + if (declspecs) + { + decl = grokdeclarator (declarator, declspecs, PARM, 0, NULL_TREE); + type = TREE_TYPE (decl); + } else type = NULL_TREE; diff --git a/gcc/cp/gxx.gperf b/gcc/cp/gxx.gperf index 33f1d23..a358534 100644 --- a/gcc/cp/gxx.gperf +++ b/gcc/cp/gxx.gperf @@ -35,6 +35,7 @@ char, TYPESPEC, RID_CHAR, class, AGGR, RID_CLASS, classof, CLASSOF, NORID, const, TYPE_QUAL, RID_CONST, +const_cast, CONST_CAST, NORID, continue, CONTINUE, NORID, default, DEFAULT, NORID, delete, DELETE, NORID, @@ -61,6 +62,7 @@ private, VISSPEC, RID_PRIVATE, protected, VISSPEC, RID_PROTECTED, public, VISSPEC, RID_PUBLIC, register, SCSPEC, RID_REGISTER, +reinterpret_cast, REINTERPRET_CAST, NORID, return, RETURN, NORID, short, TYPESPEC, RID_SHORT, signature, AGGR, RID_SIGNATURE /* Extension */, @@ -68,11 +70,12 @@ signed, TYPESPEC, RID_SIGNED, sigof, SIGOF, NORID /* Extension */, sizeof, SIZEOF, NORID, static, SCSPEC, RID_STATIC, +static_cast, STATIC_CAST, NORID, struct, AGGR, RID_RECORD, switch, SWITCH, NORID, this, THIS, NORID, throw, THROW, NORID, -template, TEMPLATE, NORID, +template, TEMPLATE, RID_TEMPLATE, try, TRY, NORID, typedef, SCSPEC, RID_TYPEDEF, typeof, TYPEOF, NORID, diff --git a/gcc/cp/hash.h b/gcc/cp/hash.h index 86bc4ca..0780d02 100644 --- a/gcc/cp/hash.h +++ b/gcc/cp/hash.h @@ -1,14 +1,14 @@ /* C code produced by gperf version 2.5 (GNU C++ version) */ -/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,7,$ ../../../devo/gcc/cp/gxx.gperf */ +/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,7,$ /deneb/blob/jason/g++/small/devo/gcc/cp/gxx.gperf */ /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */ struct resword { char *name; short token; enum rid rid;}; -#define TOTAL_KEYWORDS 80 +#define TOTAL_KEYWORDS 83 #define MIN_WORD_LENGTH 2 -#define MAX_WORD_LENGTH 13 +#define MAX_WORD_LENGTH 16 #define MIN_HASH_VALUE 4 -#define MAX_HASH_VALUE 166 -/* maximum key range = 163, duplicates = 0 */ +#define MAX_HASH_VALUE 170 +/* maximum key range = 167, duplicates = 0 */ #ifdef __GNUC__ inline @@ -20,19 +20,19 @@ hash (str, len) { static unsigned char asso_values[] = { - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 0, 167, 36, 6, 60, - 17, 0, 16, 5, 41, 38, 167, 11, 22, 7, - 26, 0, 4, 167, 22, 0, 4, 44, 19, 8, - 5, 18, 167, 167, 167, 167, 167, 167, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 0, 171, 62, 5, 65, + 27, 0, 18, 7, 10, 48, 171, 1, 30, 7, + 79, 0, 33, 171, 18, 0, 4, 26, 13, 0, + 1, 24, 171, 171, 171, 171, 171, 171, }; register int hval = len; @@ -68,103 +68,117 @@ is_reserved_word (str, len) {"",}, {"",}, {"__asm__", GCC_ASM_KEYWORD, NORID}, {"this", THIS, NORID,}, - {"goto", GOTO, NORID,}, + {"throw", THROW, NORID,}, {"__headof__", HEADOF, NORID}, - {"",}, + {"goto", GOTO, NORID,}, {"__asm", GCC_ASM_KEYWORD, NORID}, {"__const__", TYPE_QUAL, RID_CONST}, {"__volatile", TYPE_QUAL, RID_VOLATILE}, {"__const", TYPE_QUAL, RID_CONST}, {"__volatile__", TYPE_QUAL, RID_VOLATILE}, - {"throw", THROW, NORID,}, + {"",}, {"enum", ENUM, NORID,}, - {"do", DO, NORID,}, - {"template", TEMPLATE, NORID,}, + {"static_cast", STATIC_CAST, NORID,}, + {"switch", SWITCH, NORID,}, + {"",}, {"",}, {"sigof", SIGOF, NORID /* Extension */,}, {"sizeof", SIZEOF, NORID,}, - {"delete", DELETE, NORID,}, + {"",}, {"__headof", HEADOF, NORID}, - {"try", TRY, NORID,}, + {"short", TYPESPEC, RID_SHORT,}, {"typeof", TYPEOF, NORID,}, - {"typeid", TYPEID, NORID,}, + {"do", DO, NORID,}, + {"",}, + {"try", TRY, NORID,}, + {"",}, + {"delete", DELETE, NORID,}, {"__typeof__", TYPEOF, NORID}, + {"while", WHILE, NORID,}, + {"struct", AGGR, RID_RECORD,}, + {"typeid", TYPEID, NORID,}, {"double", TYPESPEC, RID_DOUBLE,}, - {"private", VISSPEC, RID_PRIVATE,}, - {"short", TYPESPEC, RID_SHORT,}, - {"extern", SCSPEC, RID_EXTERN,}, - {"__classof__", CLASSOF, NORID}, + {"for", FOR, NORID,}, {"",}, - {"while", WHILE, NORID,}, + {"__classof__", CLASSOF, NORID}, + {"",}, {"",}, + {"operator", OPERATOR, NORID,}, + {"",}, {"",}, + {"typedef", SCSPEC, RID_TYPEDEF,}, {"long", TYPESPEC, RID_LONG,}, - {"new", NEW, NORID,}, - {"protected", VISSPEC, RID_PROTECTED,}, - {"friend", SCSPEC, RID_FRIEND,}, - {"auto", SCSPEC, RID_AUTO,}, - {"for", FOR, NORID,}, + {"template", TEMPLATE, RID_TEMPLATE,}, {"__typeof", TYPEOF, NORID}, - {"typedef", SCSPEC, RID_TYPEDEF,}, - {"__extension__", EXTENSION, NORID}, + {"friend", SCSPEC, RID_FRIEND,}, + {"",}, + {"private", VISSPEC, RID_PRIVATE,}, + {"",}, {"int", TYPESPEC, RID_INT,}, - {"asm", ASM_KEYWORD, NORID,}, + {"",}, {"__classof", CLASSOF, NORID}, {"__signed__", TYPESPEC, RID_SIGNED}, - {"signed", TYPESPEC, RID_SIGNED,}, - {"mutable", SCSPEC, RID_MUTABLE,}, - {"switch", SWITCH, NORID,}, - {"operator", OPERATOR, NORID,}, + {"",}, {"",}, + {"headof", HEADOF, NORID,}, + {"",}, {"__attribute", ATTRIBUTE, NORID}, - {"struct", AGGR, RID_RECORD,}, + {"",}, {"__attribute__", ATTRIBUTE, NORID}, + {"auto", SCSPEC, RID_AUTO,}, + {"",}, {"if", IF, NORID,}, - {"void", TYPESPEC, RID_VOID,}, - {"break", BREAK, NORID,}, - {"__alignof__", ALIGNOF, NORID}, - {"__inline", SCSPEC, RID_INLINE}, - {"float", TYPESPEC, RID_FLOAT,}, - {"__inline__", SCSPEC, RID_INLINE}, - {"__signed", TYPESPEC, RID_SIGNED}, {"case", CASE, NORID,}, {"class", AGGR, RID_CLASS,}, - {"",}, - {"__label__", LABEL, NORID}, - {"default", DEFAULT, NORID,}, + {"void", TYPESPEC, RID_VOID,}, + {"asm", ASM_KEYWORD, NORID,}, + {"break", BREAK, NORID,}, {"const", TYPE_QUAL, RID_CONST,}, {"static", SCSPEC, RID_STATIC,}, - {"",}, {"",}, - {"__alignof", ALIGNOF, NORID}, + {"mutable", SCSPEC, RID_MUTABLE,}, + {"protected", VISSPEC, RID_PROTECTED,}, + {"",}, {"",}, {"",}, {"",}, + {"new", NEW, NORID,}, + {"__signed", TYPESPEC, RID_SIGNED}, {"virtual", SCSPEC, RID_VIRTUAL,}, - {"union", AGGR, RID_UNION,}, + {"extern", SCSPEC, RID_EXTERN,}, {"",}, {"",}, {"",}, - {"signature", AGGR, RID_SIGNATURE /* Extension */,}, - {"headof", HEADOF, NORID,}, - {"",}, - {"inline", SCSPEC, RID_INLINE,}, - {"overload", OVERLOAD, NORID,}, - {"",}, - {"volatile", TYPE_QUAL, RID_VOLATILE,}, - {"",}, {"",}, {"",}, {"",}, + {"float", TYPESPEC, RID_FLOAT,}, + {"",}, {"",}, {"register", SCSPEC, RID_REGISTER,}, - {"",}, - {"public", VISSPEC, RID_PUBLIC,}, + {"__extension__", EXTENSION, NORID}, {"",}, {"",}, {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,}, + {"",}, {"",}, {"",}, {"",}, + {"__label__", LABEL, NORID}, + {"inline", SCSPEC, RID_INLINE,}, + {"continue", CONTINUE, NORID,}, + {"default", DEFAULT, NORID,}, + {"char", TYPESPEC, RID_CHAR,}, {"",}, {"",}, - {"return", RETURN, NORID,}, {"classof", CLASSOF, NORID,}, - {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"unsigned", TYPESPEC, RID_UNSIGNED,}, - {"char", TYPESPEC, RID_CHAR,}, + {"union", AGGR, RID_UNION,}, + {"",}, + {"signed", TYPESPEC, RID_SIGNED,}, + {"volatile", TYPE_QUAL, RID_VOLATILE,}, + {"signature", AGGR, RID_SIGNATURE /* Extension */,}, + {"overload", OVERLOAD, NORID,}, + {"",}, {"",}, {"",}, {"",}, + {"__alignof__", ALIGNOF, NORID}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"return", RETURN, NORID,}, + {"",}, {"",}, {"",}, {"",}, + {"public", VISSPEC, RID_PUBLIC,}, + {"reinterpret_cast", REINTERPRET_CAST, NORID,}, + {"__alignof", ALIGNOF, NORID}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, - {"continue", CONTINUE, NORID,}, - {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, - {"",}, {"",}, {"",}, - {"dynamic_cast", DYNAMIC_CAST, NORID,}, - {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, - {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"const_cast", CONST_CAST, NORID,}, + {"catch", CATCH, NORID,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, - - {"catch", CATCH, NORID,}, + {"",}, {"",}, + {"__inline", SCSPEC, RID_INLINE}, + {"",}, + {"__inline__", SCSPEC, RID_INLINE}, + {"",}, + {"dynamic_cast", DYNAMIC_CAST, NORID,}, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 8e70143..6ce92a3 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -643,7 +643,7 @@ emit_base_init (t, immediately) /* member could be, for example, a CONST_DECL for an enumerated tag; we don't want to try to initialize that, since it already has a value. */ - if (TREE_CODE (member) != FIELD_DECL) + if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member)) continue; name = DECL_NAME (member); @@ -2087,8 +2087,7 @@ build_offset_ref (cname, name) if (t == NULL_TREE) { - cp_error ("`%D' is not a member of type `%T'", name, - IDENTIFIER_TYPE_VALUE (cname)); + cp_error ("`%D' is not a member of type `%T'", name, type); return error_mark_node; } @@ -2748,7 +2747,7 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals) /* We can call pushdecl here, because the TREE_CHAIN of this FUNCTION_DECL is not needed for other purposes. */ - decl = pushdecl_top_level (decl); + decl = pushdecl (decl); make_decl_rtl (decl, NULL_PTR, 1); add_friend (current_class_type, decl); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 7c88ba5..22cf0a5 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -662,6 +662,9 @@ init_lex () ridpointers[(int) RID_PROTECTED] = get_identifier ("protected"); SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PROTECTED], build_tree_list (NULL_TREE, ridpointers[(int) RID_PROTECTED])); + ridpointers[(int) RID_TEMPLATE] = get_identifier ("template"); + SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TEMPLATE], + build_tree_list (NULL_TREE, ridpointers[(int) RID_TEMPLATE])); /* This is for ANSI C++. */ ridpointers[(int) RID_MUTABLE] = get_identifier ("mutable"); SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_MUTABLE], diff --git a/gcc/cp/lex.h b/gcc/cp/lex.h index 5288a02..f9bf3f1 100644 --- a/gcc/cp/lex.h +++ b/gcc/cp/lex.h @@ -65,6 +65,7 @@ enum rid RID_RAISES, RID_AUTO, RID_MUTABLE, + RID_TEMPLATE, RID_SIGNATURE, /* Before adding enough to get up to 64, the RIDBIT_* macros will have to be changed a little. */ diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index f46f70a..dd8a96a 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -80,8 +80,6 @@ void yyerror (); 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; @@ -153,7 +151,7 @@ empty_parms () %token VISSPEC %token DELETE NEW OVERLOAD THIS OPERATOR %token LEFT_RIGHT TEMPLATE -%token TYPEID DYNAMIC_CAST +%token TYPEID DYNAMIC_CAST STATIC_CAST REINTERPRET_CAST CONST_CAST %token SCOPE /* Define the operator tokens and their precedences. @@ -197,7 +195,7 @@ empty_parms () %type unop %type identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist -%type optional_identifier paren_expr_or_null nontrivial_exprlist +%type paren_expr_or_null nontrivial_exprlist %type expr_no_commas cast_expr unary_expr primary string STRING %type typed_declspecs reserved_declspecs %type typed_typespecs reserved_typespecquals @@ -242,7 +240,7 @@ empty_parms () %type class_head base_class_list %type base_class_access_list %type base_class maybe_base_class_list base_class.1 -%type maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers +%type maybe_raises ansi_raise_identifier ansi_raise_identifiers %type component_declarator0 %type forhead.1 operator_name %type object aggr @@ -261,7 +259,7 @@ empty_parms () %type qualified_type_name complete_type_name notype_identifier %type complex_type_name nested_name_specifier_1 %type nomods_initdecls nomods_initdcl0 -%type new_initializer new_placement specialization +%type new_initializer new_placement specialization type_specifier_seq /* in order to recognize aggr tags as defining and thus shadowing. */ %token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN @@ -538,7 +536,6 @@ datadef: | declmods ';' { pedwarn ("empty declaration"); } | explicit_instantiation ';' - { doing_explicit = 0; } | typed_declspecs ';' { tree t = $$; @@ -775,16 +772,11 @@ identifier_defn: | PTYPENAME_DEFN ; -do_explicit: TEMPLATE %prec EMPTY - { doing_explicit = 1; } - ; - explicit_instantiation: - do_explicit specialization template_instantiation + TEMPLATE specialization template_instantiation { do_type_instantiation ($3 ? $3 : $2); } - | do_explicit typed_declspecs declarator + | TEMPLATE typed_declspecs declarator { do_function_instantiation ($2, $3); } - | do_explicit error ; template_type: @@ -925,7 +917,7 @@ xcond: ; condition: - typed_typespecs declarator maybe_raises maybeasm maybe_attribute '=' + type_specifier_seq declarator maybe_raises maybeasm maybe_attribute '=' { { tree d; for (d = getdecls (); d; d = TREE_CHAIN (d)) @@ -953,6 +945,17 @@ condition: | expr ; +already_scoped_stmt: + '{' '}' + { finish_stmt (); } + | '{' maybe_label_decls stmts '}' + { finish_stmt (); } + | '{' maybe_label_decls error '}' + { finish_stmt (); } + | simple_stmt + ; + + nontrivial_exprlist: expr_no_commas ',' expr_no_commas { $$ = tree_cons (NULL_TREE, $$, @@ -1414,10 +1417,18 @@ primary: } } | functional_cast - /* Stroustrup RTTI */ | DYNAMIC_CAST '<' type_id '>' '(' expr ')' { tree type = groktypename ($3); $$ = build_dynamic_cast (type, $6); } + | STATIC_CAST '<' type_id '>' '(' expr ')' + { tree type = groktypename ($3); + $$ = build_static_cast (type, $6); } + | REINTERPRET_CAST '<' type_id '>' '(' expr ')' + { tree type = groktypename ($3); + $$ = build_reinterpret_cast (type, $6); } + | CONST_CAST '<' type_id '>' '(' expr ')' + { tree type = groktypename ($3); + $$ = build_const_cast (type, $6); } | TYPEID '(' expr ')' { $$ = build_typeid ($3); } | TYPEID '(' type_id ')' @@ -2168,8 +2179,8 @@ specialization: aggr template_type_name ';' { yyungetc (';', 1); current_aggr = $$; $$ = $2; - if (doing_explicit) - instantiate_class_template ($$, 1); + if ($0 == ridpointers[(int) RID_TEMPLATE]) + instantiate_class_template ($$, 2); } ; @@ -2644,13 +2655,9 @@ enumerator: /* ANSI new-type-id (5.3.4) */ new_type_id: - typed_typespecs new_declarator - { $$ = build_decl_list ($$, $2); } - | nonempty_type_quals new_declarator + type_specifier_seq new_declarator { $$ = build_decl_list ($$, $2); } - | typed_typespecs %prec EMPTY - { $$ = build_decl_list ($$, NULL_TREE); } - | nonempty_type_quals %prec EMPTY + | type_specifier_seq %prec EMPTY { $$ = build_decl_list ($$, NULL_TREE); } /* GNU extension to allow arrays of arbitrary types with non-constant dimension. */ @@ -3100,7 +3107,7 @@ simple_stmt: cond_stmt_keyword = "while"; } .pushlevel paren_cond_or_null { expand_exit_loop_if_false (0, truthvalue_conversion ($4)); } - implicitly_scoped_stmt + already_scoped_stmt { expand_end_bindings (getdecls (), kept_level_p (), 1); poplevel (kept_level_p (), 1, 0); pop_momentary (); @@ -3131,14 +3138,14 @@ simple_stmt: /* Don't let the tree nodes for $7 be discarded by clear_momentary during the parsing of the next stmt. */ { push_momentary (); } - implicitly_scoped_stmt + already_scoped_stmt { emit_line_note (input_filename, lineno); - expand_loop_continue_here (); - if ($7) cplus_expand_expr_stmt ($7); - pop_momentary (); expand_end_bindings (getdecls (), kept_level_p (), 1); poplevel (kept_level_p (), 1, 0); pop_momentary (); + expand_loop_continue_here (); + if ($7) cplus_expand_expr_stmt ($7); + pop_momentary (); expand_end_loop (); finish_stmt (); } | forhead.2 @@ -3153,14 +3160,14 @@ simple_stmt: by clear_momentary during the parsing of the next stmt. */ { push_momentary (); $8 = lineno; } - implicitly_scoped_stmt + already_scoped_stmt { emit_line_note (input_filename, (int) $8); - expand_loop_continue_here (); - if ($7) cplus_expand_expr_stmt ($7); - pop_momentary (); expand_end_bindings (getdecls (), kept_level_p (), 1); poplevel (kept_level_p (), 1, 0); pop_momentary (); + expand_loop_continue_here (); + if ($7) cplus_expand_expr_stmt ($7); + pop_momentary (); expand_end_loop (); finish_stmt (); } @@ -3422,11 +3429,6 @@ ansi_try_stmts: } ; -optional_identifier: - /* empty */ - { $$ = NULL_TREE; } - | identifier ; - handler_seq: /* empty */ | handler_seq CATCH @@ -3435,10 +3437,21 @@ handler_seq: { expand_end_catch_block (); } ; +type_specifier_seq: + typed_typespecs %prec EMPTY + | nonempty_type_quals %prec EMPTY + ; + handler_args: '(' ELLIPSIS ')' { expand_start_catch_block (NULL_TREE, NULL_TREE); } - | '(' type_id optional_identifier ')' + | '(' type_specifier_seq absdcl ')' + { expand_start_catch_block ($2, $3); } + | '(' type_specifier_seq ')' + { expand_start_catch_block ($2, NULL_TREE); } + | '(' type_specifier_seq notype_declarator ')' + { expand_start_catch_block ($2, $3); } + | '(' typed_typespecs after_type_declarator ')' { expand_start_catch_block ($2, $3); } ; @@ -3704,33 +3717,11 @@ maybe_raises: { $$ = $3; } ; -raise_identifier: -/* ALL - { $$ = void_list_node; } */ - IDENTIFIER - { $$ = build_decl_list (NULL_TREE, $$); } - | TYPENAME - { $$ = build_decl_list (NULL_TREE, $$); } - | global_scope IDENTIFIER - { $$ = build_decl_list (NULL_TREE, $2); } - | global_scope TYPENAME - { $$ = build_decl_list (NULL_TREE, $2); } - ; - ansi_raise_identifier: type_id { $$ = build_decl_list (NULL_TREE, $$); } ; -raise_identifiers: - raise_identifier - | raise_identifiers ',' raise_identifier - { - TREE_CHAIN ($3) = $$; - $$ = $3; - } - ; - ansi_raise_identifiers: ansi_raise_identifier | ansi_raise_identifiers ',' ansi_raise_identifier @@ -3825,7 +3816,7 @@ operator_name: | operator DELETE '[' ']' { $$ = ansi_opname[VEC_DELETE_EXPR]; } /* Names here should be looked up in class scope ALSO. */ - | operator typed_typespecs conversion_declarator + | operator type_specifier_seq conversion_declarator { $$ = grokoptypename ($2, $3); } | operator error { $$ = ansi_opname[ERROR_MARK]; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 377d4a7..528bbdd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -265,12 +265,16 @@ end_template_decl (d1, d2, is_class, defn) && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE) { tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)); - tree tmpl; + tree tmpl, t; my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266); tmpl = UPT_TEMPLATE (ctx); + for (t = DECL_TEMPLATE_MEMBERS (tmpl); t; t = TREE_CHAIN (t)) + if (TREE_PURPOSE (t) == DECL_NAME (decl) + && duplicate_decls (decl, TREE_VALUE (t))) + goto already_there; DECL_TEMPLATE_MEMBERS (tmpl) = - perm_tree_cons (DECL_NAME (decl), decl, - DECL_TEMPLATE_MEMBERS (tmpl)); + perm_tree_cons (DECL_NAME (decl), decl, DECL_TEMPLATE_MEMBERS (tmpl)); + already_there: poplevel (0, 0, 0); poplevel (0, 0, 0); } @@ -1459,6 +1463,9 @@ tsubst (t, args, nargs, in_decl) layout_type (r); return r; } + case OFFSET_TYPE: + return build_offset_type + (tsubst (TYPE_OFFSET_BASETYPE (t), args, nargs, in_decl), type); case FUNCTION_TYPE: case METHOD_TYPE: { @@ -2008,10 +2015,19 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) if (targs[idx] == arg) return 0; else if (targs[idx]) - return 1; + { + if (TYPE_MAIN_VARIANT (targs[idx]) == TYPE_MAIN_VARIANT (arg)) + /* allow different parms to have different cv-qualifiers */; + else + return 1; + } /* Check for mixed types and values. */ if (TREE_CODE (TREE_VEC_ELT (tparms, idx)) != IDENTIFIER_NODE) return 1; + /* Allow trivial conversions. */ + if (TYPE_READONLY (parm) < TYPE_READONLY (arg) + || TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg)) + return 1; targs[idx] = arg; return 0; case TEMPLATE_CONST_PARM: @@ -2136,8 +2152,12 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm), arg, nsubsts); - /* Unification of something that is not a template fails. (mrs) */ - return 1; + /* Allow trivial conversions. */ + if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg) + || TYPE_READONLY (parm) < TYPE_READONLY (arg) + || TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg)) + return 1; + return 0; case METHOD_TYPE: if (TREE_CODE (arg) != METHOD_TYPE) @@ -2150,7 +2170,16 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) check_args: return type_unification (tparms, targs, TYPE_ARG_TYPES (parm), TYPE_ARG_TYPES (arg), nsubsts, 1); - + + case OFFSET_TYPE: + if (TREE_CODE (arg) != OFFSET_TYPE) + return 1; + if (unify (tparms, targs, ntparms, TYPE_OFFSET_BASETYPE (parm), + TYPE_OFFSET_BASETYPE (arg), nsubsts)) + return 1; + return unify (tparms, targs, ntparms, TREE_TYPE (parm), + TREE_TYPE (arg), nsubsts); + default: sorry ("use of `%s' in template type unification", tree_code_name [(int) TREE_CODE (parm)]); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 946763c..c81f1e1 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1134,7 +1134,7 @@ lookup_field (xbasetype, name, protect, want_type) if (errstr && protect) { - error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type)); + cp_error (errstr, name, type); return error_mark_node; } return rval; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index edb0b78a..d8df8e4 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -94,9 +94,6 @@ lvalue_p (ref) return (lvalue_p (TREE_OPERAND (ref, 1)) && lvalue_p (TREE_OPERAND (ref, 2))); - case MODIFY_EXPR: - return 1; - case COMPOUND_EXPR: return lvalue_p (TREE_OPERAND (ref, 1)); } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 03ca722..490d998 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -47,7 +47,6 @@ static tree pointer_int_sum (); static tree pointer_diff (); static tree convert_sequence (); /* static */ tree unary_complex_lvalue (); -static void pedantic_lvalue_warning (); tree truthvalue_conversion (); extern rtx original_result_rtx; @@ -223,10 +222,7 @@ commonparms (p1, p2) if (cmp < 0) my_friendly_abort (111); if (cmp == 0) - { - error ("redeclaration of default argument %d", i+1); - any_change = 1; - } + any_change = 1; TREE_PURPOSE (n) = TREE_PURPOSE (p2); } if (TREE_VALUE (p1) != TREE_VALUE (p2)) @@ -411,7 +407,7 @@ common_type (t1, t2) return t1; case METHOD_TYPE: - if (TYPE_METHOD_BASETYPE (t1) == TYPE_METHOD_BASETYPE (t2) + if (comptypes (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2), 1) && TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))) { /* Get this value the long way, since TYPE_METHOD_BASETYPE @@ -642,6 +638,9 @@ comptypes (type1, type2, strict) case TEMPLATE_TYPE_PARM: return 1; + + case UNINSTANTIATED_P_TYPE: + return UPT_TEMPLATE (t1) == UPT_TEMPLATE (t2); } return 0; } @@ -1340,9 +1339,10 @@ build_object_ref (datum, basetype, field) else if (is_aggr_typedef (basetype, 1)) { tree real_basetype = IDENTIFIER_TYPE_VALUE (basetype); - if (binfo_or_else (real_basetype, TREE_TYPE (datum))) + tree binfo = binfo_or_else (real_basetype, TREE_TYPE (datum)); + if (binfo) return build_component_ref (build_scoped_ref (datum, basetype), - field, NULL_TREE, 1); + field, binfo, 1); } return error_mark_node; } @@ -3006,12 +3006,14 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ; else if (tt0 == void_type_node) { - if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE) + if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE + && tree_int_cst_lt (TYPE_SIZE (type0), TYPE_SIZE (type1))) pedwarn ("ANSI C++ forbids comparison of `void *' with function pointer"); } else if (tt1 == void_type_node) { - if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE) + if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE + && tree_int_cst_lt (TYPE_SIZE (type1), TYPE_SIZE (type0))) pedwarn ("ANSI C++ forbids comparison of `void *' with function pointer"); } else if ((TYPE_SIZE (tt0) != 0) != (TYPE_SIZE (tt1) != 0)) @@ -3457,13 +3459,6 @@ pointer_int_sum (resultcode, ptrop, intop) register tree result_type = TREE_TYPE (ptrop); - /* Needed to make OOPS V2R3 work. */ - intop = folded; - if (TREE_CODE (intop) == INTEGER_CST - && TREE_INT_CST_LOW (intop) == 0 - && TREE_INT_CST_HIGH (intop) == 0) - return ptrop; - if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE) { if (pedantic || warn_pointer_arith) @@ -3491,6 +3486,13 @@ pointer_int_sum (resultcode, ptrop, intop) else size_exp = size_in_bytes (TREE_TYPE (result_type)); + /* Needed to make OOPS V2R3 work. */ + intop = folded; + if (TREE_CODE (intop) == INTEGER_CST + && TREE_INT_CST_LOW (intop) == 0 + && TREE_INT_CST_HIGH (intop) == 0) + return ptrop; + /* If what we are about to multiply by the size of the elements contains a constant term, apply distributive law and multiply that constant term separately. @@ -3882,7 +3884,6 @@ build_unary_op (code, xarg, noconvert) case FIX_CEIL_EXPR: { tree incremented, modify, value; - pedantic_lvalue_warning (CONVERT_EXPR); arg = stabilize_reference (arg); if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR) value = arg; @@ -4158,17 +4159,18 @@ unary_complex_lvalue (code, arg) if (TREE_CODE (arg) == COMPOUND_EXPR) { tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0); - pedantic_lvalue_warning (COMPOUND_EXPR); return build (COMPOUND_EXPR, TREE_TYPE (real_result), TREE_OPERAND (arg, 0), real_result); } /* Handle (a ? b : c) used as an "lvalue". */ if (TREE_CODE (arg) == COND_EXPR) - { - pedantic_lvalue_warning (COND_EXPR); - return rationalize_conditional_expr (code, arg); - } + return rationalize_conditional_expr (code, arg); + + if (TREE_CODE (arg) == MODIFY_EXPR) + return unary_complex_lvalue + (code, build (COMPOUND_EXPR, TREE_TYPE (TREE_OPERAND (arg, 0)), + arg, TREE_OPERAND (arg, 0))); if (code != ADDR_EXPR) return 0; @@ -4295,19 +4297,6 @@ unary_complex_lvalue (code, arg) /* Don't let anything else be handled specially. */ return 0; } - -/* If pedantic, warn about improper lvalue. CODE is either COND_EXPR - COMPOUND_EXPR, or CONVERT_EXPR (for casts). */ - -static void -pedantic_lvalue_warning (code) - enum tree_code code; -{ - if (pedantic) - pedwarn ("ANSI C++ forbids use of %s expressions as lvalues", - code == COND_EXPR ? "conditional" - : code == COMPOUND_EXPR ? "compound" : "cast"); -} /* Mark EXP saying that we need to be able to take the address of it; it should not be allocated in a register. @@ -4785,6 +4774,24 @@ build_compound_expr (list) break_out_cleanups (TREE_VALUE (list)), rest); } +tree build_static_cast (type, expr) + tree type, expr; +{ + return build_c_cast (type, expr); +} + +tree build_reinterpret_cast (type, expr) + tree type, expr; +{ + return build_c_cast (type, expr); +} + +tree build_const_cast (type, expr) + tree type, expr; +{ + return build_c_cast (type, expr); +} + /* Build an expression representing a cast to type TYPE of expression EXPR. */ tree @@ -5294,7 +5301,6 @@ build_modify_expr (lhs, modifycode, rhs) /* Handle (a, b) used as an "lvalue". */ case COMPOUND_EXPR: - pedantic_lvalue_warning (COMPOUND_EXPR); newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs); if (TREE_CODE (newrhs) == ERROR_MARK) @@ -5302,9 +5308,14 @@ build_modify_expr (lhs, modifycode, rhs) return build (COMPOUND_EXPR, lhstype, TREE_OPERAND (lhs, 0), newrhs); + case MODIFY_EXPR: + newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs); + if (TREE_CODE (newrhs) == ERROR_MARK) + return error_mark_node; + return build (COMPOUND_EXPR, lhstype, lhs, newrhs); + /* Handle (a ? b : c) used as an "lvalue". */ case COND_EXPR: - pedantic_lvalue_warning (COND_EXPR); rhs = save_expr (rhs); { /* Produce (a ? (b = rhs) : (c = rhs)) @@ -5450,7 +5461,7 @@ build_modify_expr (lhs, modifycode, rhs) convert (lhstype, newrhs))); if (TREE_CODE (result) == ERROR_MARK) return result; - return convert (TREE_TYPE (lhs), result); + return convert_force (TREE_TYPE (lhs), result); } } @@ -6559,9 +6570,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) return here before checking if RHS is of complete type. */ if (codel == REFERENCE_TYPE) - return convert_to_reference ((exp ? exp : error_mark_node), - type, rhs, fndecl, parmnum, errtype, - 0, flags); + return convert_to_reference (type, rhs, CONV_IMPLICIT, flags, + exp ? exp : error_mark_node); rhs = require_complete_type (rhs); if (rhs == error_mark_node) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 53106b2..858896a 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -59,7 +59,7 @@ binfo_or_else (parent_or_type, type) { tree binfo; if (TYPE_MAIN_VARIANT (parent_or_type) == TYPE_MAIN_VARIANT (type)) - return parent_or_type; + return TYPE_BINFO (parent_or_type); if ((binfo = get_binfo (parent_or_type, TYPE_MAIN_VARIANT (type), 0))) { if (binfo == error_mark_node) @@ -738,7 +738,10 @@ digest_init (type, init, tail) return error_mark_node; } - if (pedantic && typ1 != char_type_node) + if (pedantic + && typ1 != char_type_node + && typ1 != signed_char_type_node + && typ1 != unsigned_char_type_node) pedwarn ("ANSI C++ forbids string initializer except for `char' elements"); TREE_TYPE (string) = type; if (TYPE_DOMAIN (type) != 0 @@ -752,7 +755,7 @@ digest_init (type, init, tail) counted in the length of the constant, but in C++ this would be invalid. */ if (size < TREE_STRING_LENGTH (string)) - warning ("initializer-string for array of chars is too long"); + pedwarn ("initializer-string for array of chars is too long"); } return string; } -- 2.7.4