diff options
author | Mike Stump <mrs@gcc.gnu.org> | 1996-02-09 22:43:25 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 1996-02-09 22:43:25 +0000 |
commit | 2ee887f2725c1f074859ae85735f08bffca23dfb (patch) | |
tree | dbdec03f770326fec3f6cb1f409d09b2e0054728 /gcc | |
parent | 258ae59d66b7d11bffebd6917492030f8fbca189 (diff) | |
download | gcc-2ee887f2725c1f074859ae85735f08bffca23dfb.zip gcc-2ee887f2725c1f074859ae85735f08bffca23dfb.tar.gz gcc-2ee887f2725c1f074859ae85735f08bffca23dfb.tar.bz2 |
81st Cygnus<->FSF merge
From-SVN: r11187
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 95 | ||||
-rw-r--r-- | gcc/cp/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/cp/class.c | 106 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 8 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 13 | ||||
-rw-r--r-- | gcc/cp/decl.c | 264 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 8 | ||||
-rw-r--r-- | gcc/cp/error.c | 6 | ||||
-rw-r--r-- | gcc/cp/init.c | 25 | ||||
-rw-r--r-- | gcc/cp/lex.c | 8 | ||||
-rw-r--r-- | gcc/cp/parse.y | 6 | ||||
-rw-r--r-- | gcc/cp/tree.c | 31 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 109 |
14 files changed, 368 insertions, 315 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b745716..72617e0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,92 @@ +Thu Feb 8 15:15:14 1996 Jason Merrill <jason@yorick.cygnus.com> + + * decl.c (grokfndecl): Move code that looks for virtuals in base + classes... + * class.c (fixup_virtual): ... to a new function. + (finish_struct_1): Call it. + + * cp-tree.h: Declare warn_sign_compare. + + * typeck.c (build_binary_op_nodefault): Check warn_sign_compare + rather than extra_warnings to decide whether to warn about + comparison of signed and unsigned. + + * decl2.c (lang_decode_option): Handle warn_sign_compare. -Wall + implies -Wsign-compare. -Wall doesn't imply -W. + +Wed Feb 7 15:27:57 1996 Mike Stump <mrs@cygnus.com> + + * typeck.c (build_component_ref): Fix to handle anon unions in base + classes as well. + +Wed Feb 7 14:29:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * class.c (resolves_to_fixed_type_p): Delete code dealing with + a WITH_CLEANUP_EXPR, since we don't generate them any more. + * cvt.c (build_up_reference): Likewise. + * decl.c (grok_reference_init): Likewise. + (cp_finish_decl): Likewise. + * error.c (dump_expr): Likewise. + * tree.c (real_lvalue_p): Likewise. + (lvalue_p): Likewise. + (build_cplus_new): Likewise. + (unsave_expr_now): Likewise. + * typeck.c (unary_complex_lvalue, build_modify_expr, + c_expand_return): Likewise. + +Tue Feb 6 13:39:22 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + Make the C++ front-end pay attention to attributes for structures. + * class.c (finish_struct): New argument ATTRIBUTES, passed down into + finish_struct_1. + (finish_struct_1): New argument ATTRIBUTES; call cplus_decl_attributes. + Take out old round_up_size use and setting the DECL_ALIGN possibly + using it. Take out setting of TYPE_ALIGN to round_up_size, which + can override what the attribute set. + * cp-tree.h (finish_struct): Update prototype. + * parse.y (template_instantiate_once): Pass a NULL_TREE for the + attributes to finish_struct. + (structsp): For a CLASS decl, add maybe_attribute to rule and pass that + value down into finish_struct. + * Makefile.in (CONFLICTS): Switch to 7 shift/reduce conflicts. + +Tue Feb 6 13:12:15 1996 Per Bothner <bothner@kalessin.cygnus.com> + + * decl.c (poplevel): Re-word dead for local handling. + (pushdecl): Remove useless DECL_DEAD_FOR_LOCAL test. + (cp_finish_decl): If is_for_scope, check for duplicates so + we can disable is_for_scope. Otherwise, preserve_temp_slots. + + * lex.c (do_identifier): Use global binding in preference of + dead for local variable. + +Mon Feb 5 17:46:46 1996 Mike Stump <mrs@cygnus.com> + + * init.c (initializing_context): Handle anon union changes, the + context where fields of anon unions can be initialized now has to be + found by walking up the TYPE_CONTEXT chain. + +Fri Feb 2 14:54:04 1996 Doug Evans <dje@charmed.cygnus.com> + + * decl.c (start_decl): #ifdef out code to set DECL_COMMON + if ASM_OUTPUT{,_ALIGNED}_BSS is defined. + (obscure_complex_init): If bss is supported, always set + DECL_INITIAL to error_mark_node. + +Thu Feb 1 16:19:56 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * init.c (is_friend): Make sure there's a context before we see if + it's an aggr type. + +Thu Feb 1 15:44:53 1996 Mike Stump <mrs@cygnus.com> + + * init.c (is_friend): Classes are not friendly with nested classes. + +Thu Feb 1 15:27:37 1996 Doug Evans <dje@charmed.cygnus.com> + + * lex.c (check_newline): Pass last character read to HANDLE_PRAGMA, + and record its result. + Thu Feb 1 09:27:01 1996 Mike Stump <mrs@cygnus.com> * class.c (finish_struct_anon): Switch around code to not move anon @@ -10187,9 +10276,3 @@ Mon Nov 8 13:50:49 1993 Jason Merrill (jason@deneb.cygnus.com) Tue Sep 7 20:03:33 1993 Jason Merrill (jason@deneb.cygnus.com) * cp-decl.c: Allow references and template type parameters as well - -Local Variables: -eval: (auto-fill-mode) -left-margin: 8 -fill-column: 76 -End: diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index 7ba077e..8bfbb12 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -196,7 +196,7 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \ `echo $(PARSE_C) | sed 's,^\./,,'` -CONFLICTS = expect 5 shift/reduce conflicts and 38 reduce/reduce conflicts. +CONFLICTS = expect 7 shift/reduce conflicts and 38 reduce/reduce conflicts. $(PARSE_H) : $(PARSE_C) $(PARSE_C) : $(srcdir)/parse.y @echo $(CONFLICTS) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 929e5b10..a5c8f38 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2753,6 +2753,77 @@ mark_overriders (fndecl, base_fndecls) } } +/* If this declaration supersedes the declaration of + a method declared virtual in the base class, then + mark this field as being virtual as well. */ + +void +fixup_virtual (decl, ctype) + tree decl, ctype; +{ + tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype)); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + int virtualp = DECL_VIRTUAL_P (decl); + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)) + || flag_all_virtual == 1) + { + tree tmp = get_matching_virtual + (base_binfo, decl, + DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))); + if (tmp) + { + /* If this function overrides some virtual in some base + class, then the function itself is also necessarily + virtual, even if the user didn't explicitly say so. */ + DECL_VIRTUAL_P (decl) = 1; + + /* The TMP we really want is the one from the deepest + baseclass on this path, taking care not to + duplicate if we have already found it (via another + path to its virtual baseclass. */ + if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) + { + cp_error_at ("method `%D' may not be declared static", + decl); + cp_error_at ("(since `%D' declared virtual in base class.)", + tmp); + break; + } + virtualp = 1; + + { + /* The argument types may have changed... */ + tree type = TREE_TYPE (decl); + tree argtypes = TYPE_ARG_TYPES (type); + tree base_variant = TREE_TYPE (TREE_VALUE (argtypes)); + tree raises = TYPE_RAISES_EXCEPTIONS (type); + + argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))), + TREE_CHAIN (argtypes)); + /* But the return type has not. */ + type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes); + if (raises) + type = build_exception_variant (type, raises); + TREE_TYPE (decl) = type; + DECL_VINDEX (decl) + = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl)); + } + break; + } + } + } + if (virtualp) + { + if (DECL_VINDEX (decl) == NULL_TREE) + DECL_VINDEX (decl) = error_mark_node; + IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; + } +} + /* Warn about hidden virtual functions that are not overridden in t. */ void warn_hidden (t) @@ -2889,6 +2960,8 @@ extern int interface_only, interface_unknown; TREE_LIST elements, whose TREE_PURPOSE field tells what access the list has, and the TREE_VALUE slot gives the actual fields. + ATTRIBUTES is the set of decl attributes to be applied, if any. + If flag_all_virtual == 1, then we lay all functions into the virtual function table, as though they were declared virtual. Constructors do not lay down in the virtual function table. @@ -2920,13 +2993,11 @@ extern int interface_only, interface_unknown; or otherwise in a type-consistent manner. */ tree -finish_struct_1 (t, warn_anon) - tree t; +finish_struct_1 (t, attributes, warn_anon) + tree t, attributes; int warn_anon; { int old; - int round_up_size = 1; - tree name = TYPE_IDENTIFIER (t); enum tree_code code = TREE_CODE (t); tree fields = TYPE_FIELDS (t); @@ -2986,6 +3057,8 @@ finish_struct_1 (t, warn_anon) TYPE_SIZE (t) = NULL_TREE; CLASSTYPE_GOT_SEMICOLON (t) = 0; + cplus_decl_attributes (t, attributes, NULL_TREE); + #if 0 /* This is in general too late to do this. I moved the main case up to left_curly, what else needs to move? */ @@ -3104,6 +3177,8 @@ finish_struct_1 (t, warn_anon) DECL_SAVED_INSNS (x) = NULL_RTX; DECL_FIELD_SIZE (x) = 0; + fixup_virtual (x, t); + /* The name of the field is the original field name Save this in auxiliary field for later overloading. */ if (DECL_VINDEX (x) @@ -3329,13 +3404,7 @@ finish_struct_1 (t, warn_anon) if (width == 0) { #ifdef EMPTY_FIELD_BOUNDARY - /* field size 0 => mark following field as "aligned" */ - if (TREE_CHAIN (x)) - DECL_ALIGN (TREE_CHAIN (x)) - = MAX (DECL_ALIGN (TREE_CHAIN (x)), EMPTY_FIELD_BOUNDARY); - /* field of size 0 at the end => round up the size. */ - else - round_up_size = EMPTY_FIELD_BOUNDARY; + DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY); #endif #ifdef PCC_BITFIELD_TYPE_MATTERS DECL_ALIGN (x) = MAX (DECL_ALIGN (x), @@ -3716,10 +3785,6 @@ finish_struct_1 (t, warn_anon) TYPE_FIELDS (t) = fields; - /* If there's a :0 field at the end, round the size to the - EMPTY_FIELD_BOUNDARY. */ - TYPE_ALIGN (t) = round_up_size; - /* Pass layout information about base classes to layout_type, if any. */ if (n_baseclasses) { @@ -4168,9 +4233,8 @@ finish_struct_1 (t, warn_anon) } tree -finish_struct (t, list_of_fieldlists, warn_anon) - tree t; - tree list_of_fieldlists; +finish_struct (t, list_of_fieldlists, attributes, warn_anon) + tree t, list_of_fieldlists, attributes; int warn_anon; { tree fields = NULL_TREE; @@ -4301,7 +4365,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) return t; } else - return finish_struct_1 (t, warn_anon); + return finish_struct_1 (t, attributes, warn_anon); } /* Return non-zero if the effective type of INSTANCE is static. @@ -4374,10 +4438,6 @@ resolves_to_fixed_type_p (instance, nonnull) case COMPONENT_REF: return resolves_to_fixed_type_p (TREE_OPERAND (instance, 1), nonnull); - case WITH_CLEANUP_EXPR: - if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR) - return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull); - /* fall through... */ case VAR_DECL: case FIELD_DECL: if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 82b7954..fabc3e1 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -37,7 +37,7 @@ DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2) /* For a UNSAVE_EXPR, operand 0 is the value to unsave. By unsave, we mean that all _EXPRs such as TARGET_EXPRs, SAVE_EXPRs, - WITH_CLEANUP_EXPRs, CALL_EXPRs and RTL_EXPRs, that are protected + CALL_EXPRs and RTL_EXPRs, that are protected from being evaluated more than once should be reset so that a new expand_expr call of this expr will cause those to be re-evaluated. This is useful when we want to reuse a tree in different places, diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e9b4a28..05f12b9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -219,6 +219,10 @@ extern int warn_redundant_decls; extern int warn_missing_braces; +/* Warn about comparison of signed and unsigned values. */ + +extern int warn_sign_compare; + /* Warn about a subscript that has type char. */ extern int warn_char_subscripts; @@ -1061,7 +1065,7 @@ struct lang_decl #endif /* In a VAR_DECL for a variable declared in a for statement, - this is the shadowed variable. */ + this is the shadowed (local) variable. */ #define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE) /* Points back to the decl which caused this lang_decl to be allocated. */ @@ -1936,7 +1940,7 @@ extern tree build_vfn_ref PROTO((tree *, tree, tree)); extern void add_method PROTO((tree, tree *, tree)); extern tree get_vfield_offset PROTO((tree)); extern void duplicate_tag_error PROTO((tree)); -extern tree finish_struct PROTO((tree, tree, int)); +extern tree finish_struct PROTO((tree, tree, tree, int)); extern int resolves_to_fixed_type_p PROTO((tree, int *)); extern void init_class_processing PROTO((void)); extern void pushclass PROTO((tree, int)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index f793bce..b45823d 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -565,12 +565,6 @@ build_up_reference (type, arg, flags, checkconst) build_up_reference (type, TREE_OPERAND (targ, 1), LOOKUP_PROTECT, checkconst)); - case WITH_CLEANUP_EXPR: - return build (WITH_CLEANUP_EXPR, type, - build_up_reference (type, TREE_OPERAND (targ, 0), - LOOKUP_PROTECT, checkconst), - 0, TREE_OPERAND (targ, 2)); - case BIND_EXPR: arg = TREE_OPERAND (targ, 1); if (arg == NULL_TREE) @@ -593,12 +587,7 @@ build_up_reference (type, arg, flags, checkconst) if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype)) { temp = build_cplus_new (argtype, targ, 1); - if (TREE_CODE (temp) == WITH_CLEANUP_EXPR) - rval = build (WITH_CLEANUP_EXPR, type, - build1 (ADDR_EXPR, type, TREE_OPERAND (temp, 0)), - 0, TREE_OPERAND (temp, 2)); - else - rval = build1 (ADDR_EXPR, type, temp); + rval = build1 (ADDR_EXPR, type, temp); goto done; } else if (flags&INDIRECT_BIND) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 8becd0f..f3f16f8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -580,7 +580,8 @@ struct binding_level /* This is set for a namespace binding level. */ unsigned namespace_p : 1; - /* True if this level is that of a for-statement. */ + /* True if this level is that of a for-statement where we need to + worry about ambiguous (traditional or ANSI) scope rules. */ unsigned is_for_scope : 1; /* One bit left for this word. */ @@ -1086,26 +1087,31 @@ poplevel (keep, reverse, functionbody) /* Clear out the meanings of the local variables of this level. */ - for (link = current_binding_level->dead_vars_from_for; - link != NULL_TREE; link = TREE_CHAIN (link)) - { - if (DECL_DEAD_FOR_LOCAL (link)) - { - tree id = DECL_NAME (link); - if (IDENTIFIER_LOCAL_VALUE (id) == link) - IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link); - } - } - if (current_binding_level->is_for_scope && flag_new_for_scope == 1) { + struct binding_level *outer = current_binding_level->level_chain; for (link = decls; link; link = TREE_CHAIN (link)) { if (TREE_CODE (link) == VAR_DECL) DECL_DEAD_FOR_LOCAL (link) = 1; } + + /* Save declarations made in a 'for' statement so we can support pre-ANSI + 'for' scoping semantics. */ + + for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + { + tree id = TREE_PURPOSE (link); + tree decl = IDENTIFIER_LOCAL_VALUE (id); + + /* In this case keep the dead for-decl visible, + but remember what (if anything) it shadowed. */ + DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link); + TREE_CHAIN (decl) = outer->dead_vars_from_for; + outer->dead_vars_from_for = decl; + } } - else + else /* Not special for scope. */ { for (link = decls; link; link = TREE_CHAIN (link)) { @@ -1123,50 +1129,42 @@ poplevel (keep, reverse, functionbody) IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE; } } - } - /* Restore all name-meanings of the outer levels - that were shadowed by this level. */ + /* Restore all name-meanings of the outer levels + that were shadowed by this level. */ - if (current_binding_level->is_for_scope && flag_new_for_scope == 1) - { - struct binding_level *outer = current_binding_level->level_chain; - for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + for (link = current_binding_level->shadowed; + link; link = TREE_CHAIN (link)) + IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + + /* We first restore the regular decls and *then* the dead_vars_from_for + to handle this case: + + int i; // i#1 + { + for (int i; ; ) { ...} // i#2 + int i; // i#3 + } // we are here + + In this case, we want remove the binding for i#3, restoring + that of i#2. Then we want to remove the binding for i#2, + and restore that of i#1. */ + + link = current_binding_level->dead_vars_from_for; + for (; link != NULL_TREE; link = TREE_CHAIN (link)) { - tree id = TREE_PURPOSE (link); - tree decl = IDENTIFIER_LOCAL_VALUE (id); - if (DECL_DEAD_FOR_LOCAL (decl)) - DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link); - else - IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link); + tree id = DECL_NAME (link); + if (IDENTIFIER_LOCAL_VALUE (id) == link) + IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link); } - /* Save declarations made in a 'for' statement so we can support pre-ANSI - 'for' scoping semantics. */ - - /* We append the current names of for-variables to those from previous - declarations, so that when we get around to do an poplevel - on the OUTER level, we restore the any shadowed readl bindings. - Note that the new names are put first on the combined list, - so they get to be restored first. This is important if there are - two for-loops using the same for-variable in the same block. - The binding we really want restored is whatever binding was shadowed - by the *first* for-variable, not the binding shadowed by the - second for-variable (which would be the first for-variable). */ - outer->dead_vars_from_for - = chainon (current_binding_level->names, outer->dead_vars_from_for); - } - else - { - for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) - IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + for (link = current_binding_level->class_shadowed; + link; link = TREE_CHAIN (link)) + IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + for (link = current_binding_level->type_shadowed; + link; link = TREE_CHAIN (link)) + IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); } - for (link = current_binding_level->class_shadowed; - link; link = TREE_CHAIN (link)) - IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); - for (link = current_binding_level->type_shadowed; - link; link = TREE_CHAIN (link)) - IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); /* If the level being exited is the top level of a function, check over all the labels. */ @@ -3003,9 +3001,7 @@ pushdecl (x) { file = DECL_SOURCE_FILE (t); line = DECL_SOURCE_LINE (t); - if (TREE_CODE (x) == VAR_DECL && DECL_DEAD_FOR_LOCAL (x)) - ; /* This is OK. */ - else if (TREE_CODE (t) == PARM_DECL) + if (TREE_CODE (t) == PARM_DECL) { if (DECL_CONTEXT (t) == NULL_TREE) fatal ("parse errors have confused me too much"); @@ -5821,7 +5817,8 @@ start_decl (declarator, declspecs, initialized, raises) tem = decl; else tem = pushdecl (decl); - + +#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS) /* Tell the back-end to use or not use .common as appropriate. If we say -fconserve-space, we want this to save space, at the expense of wrong semantics. If we say -fno-conserve-space, we want this to produce @@ -5830,6 +5827,7 @@ start_decl (declarator, declspecs, initialized, raises) the linker can't match it with storage from other files, and we may save some disk space. */ DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem); +#endif if (TREE_CODE (decl) == TEMPLATE_DECL) { @@ -5957,23 +5955,15 @@ grok_reference_init (decl, type, init, cleanupp) don't get burned by "aggressive" cleanup policy. */ if (TYPE_NEEDS_DESTRUCTOR (subtype)) { - if (TREE_CODE (init) == WITH_CLEANUP_EXPR) + if (TREE_CODE (tmp) == ADDR_EXPR) + tmp = TREE_OPERAND (tmp, 0); + if (TREE_CODE (tmp) == TARGET_EXPR) { - *cleanupp = TREE_OPERAND (init, 2); - TREE_OPERAND (init, 2) = error_mark_node; - } - else - { - if (TREE_CODE (tmp) == ADDR_EXPR) - tmp = TREE_OPERAND (tmp, 0); - if (TREE_CODE (tmp) == TARGET_EXPR) - { - *cleanupp = build_delete - (build_pointer_type (subtype), - build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0), - integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); - TREE_OPERAND (tmp, 2) = error_mark_node; - } + *cleanupp = build_delete + (build_pointer_type (subtype), + build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0), + integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); + TREE_OPERAND (tmp, 2) = error_mark_node; } } @@ -6024,10 +6014,12 @@ obscure_complex_init (decl, init) return NULL_TREE; } +#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS) if (toplevel_bindings_p () && ! DECL_COMMON (decl)) DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, NULL_TREE); else +#endif DECL_INITIAL (decl) = error_mark_node; return init; @@ -6346,18 +6338,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) if (!DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)) { int yes = suspend_momentary (); - - /* If INIT comes from a functional cast, use the cleanup - we built for that. Otherwise, make our own cleanup. */ - if (init && TREE_CODE (init) == WITH_CLEANUP_EXPR - && comptypes (TREE_TYPE (decl), TREE_TYPE (init), 1)) - { - cleanup = TREE_OPERAND (init, 2); - init = TREE_OPERAND (init, 0); - current_binding_level->have_cleanups = 1; - } - else - cleanup = maybe_build_cleanup (decl); + cleanup = maybe_build_cleanup (decl); resume_momentary (yes); } } @@ -6532,6 +6513,52 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) } } + if (current_binding_level->is_for_scope) + { + struct binding_level *outer = current_binding_level->level_chain; + + /* Check to see if the same name is already bound at + the outer level, either because it was directly declared, + or because a dead for-decl got preserved. In either case, + the code would not have been valid under the traditional + scope rules, so clear is_for_scope for the + current_binding_level. + + Otherwise, we need to preserve the temp slot for decl + to last into the outer binding level. */ + + int handling_dead_for_vars = 0; + tree link = outer->names; + for (; ; link = TREE_CHAIN (link)) + { + if (link == NULL && handling_dead_for_vars == 0) + { + link = outer->dead_vars_from_for; + handling_dead_for_vars = 1; + } + if (link == NULL) + { + if (DECL_RTL (decl) && GET_CODE (DECL_RTL (decl)) == MEM) + preserve_temp_slots (DECL_RTL (decl)); + break; + } + if (DECL_NAME (link) == DECL_NAME (decl)) + { + if (handling_dead_for_vars) + { + tree shadowing + = purpose_member (DECL_NAME (decl), + current_binding_level->shadowed); + if (shadowing && TREE_VALUE (shadowing) == link) + TREE_VALUE (shadowing) + = DECL_SHADOWED_FOR_VAR (link); + } + current_binding_level->is_for_scope = 0; + break; + } + } + } + push_temp_slots (); push_temp_slots (); target_temp_slot_level = temp_slot_level; @@ -7027,81 +7054,12 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, TREE_VALUE (attrlist)); make_decl_rtl (decl, NULL_PTR, 1); } - - /* If this declaration supersedes the declaration of - a method declared virtual in the base class, then - mark this field as being virtual as well. */ - { - tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype)); - int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; - - for (i = 0; i < n_baselinks; i++) - { - tree base_binfo = TREE_VEC_ELT (binfos, i); - if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)) - || flag_all_virtual == 1) - { - tmp = get_matching_virtual (base_binfo, decl, - flags == DTOR_FLAG); - if (tmp) - { - /* If this function overrides some virtual in some base - class, then the function itself is also necessarily - virtual, even if the user didn't explicitly say so. */ - DECL_VIRTUAL_P (decl) = 1; - - /* The TMP we really want is the one from the deepest - baseclass on this path, taking care not to - duplicate if we have already found it (via another - path to its virtual baseclass. */ - if (staticp) - { - cp_error ("method `%D' may not be declared static", - decl); - cp_error_at ("(since `%D' declared virtual in base class.)", - tmp); - break; - } - virtualp = 1; - - { - /* The argument types may have changed... */ - tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); - tree base_variant = TREE_TYPE (TREE_VALUE (argtypes)); - - argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))), - TREE_CHAIN (argtypes)); - /* But the return type has not. */ - type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes); - if (raises) - { - type = build_exception_variant (type, raises); - raises = TYPE_RAISES_EXCEPTIONS (type); - } - TREE_TYPE (decl) = type; - DECL_VINDEX (decl) - = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl)); - } - break; - } - } - } - } if (virtualp) { + DECL_VIRTUAL_P (decl) = 1; if (DECL_VINDEX (decl) == NULL_TREE) DECL_VINDEX (decl) = error_mark_node; IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; - if (ctype && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) - /* If this function is derived from a template, don't - make it public. This shouldn't be here, but there's - no good way to override the interface pragmas for one - function or class only. Bletch. */ - && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (ctype)) == NULL_TREE - && (write_virtuals == 2 - || (write_virtuals == 3 - && CLASSTYPE_INTERFACE_KNOWN (ctype)))) - TREE_PUBLIC (decl) = 1; } } return decl; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 58cdf5c..b7ce4f0 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -196,6 +196,10 @@ int warn_redundant_decls; int warn_missing_braces; +/* Warn about comparison of signed and unsigned values. */ + +int warn_sign_compare; + /* Warn about *printf or *scanf format/argument anomalies. */ int warn_format; @@ -541,6 +545,8 @@ lang_decode_option (p) warn_redundant_decls = setting; else if (!strcmp (p, "missing-braces")) warn_missing_braces = setting; + else if (!strcmp (p, "sign-compare")) + warn_sign_compare = setting; else if (!strcmp (p, "format")) warn_format = setting; else if (!strcmp (p, "conversion")) @@ -565,7 +571,6 @@ lang_decode_option (p) ; /* cpp handles this one. */ else if (!strcmp (p, "all")) { - extra_warnings = setting; warn_return_type = setting; warn_unused = setting; warn_implicit = setting; @@ -574,6 +579,7 @@ lang_decode_option (p) warn_format = setting; warn_parentheses = setting; warn_missing_braces = setting; + warn_sign_compare = setting; warn_extern_inline = setting; warn_nonvdtor = setting; /* We save the value of warn_uninitialized, since if they put diff --git a/gcc/cp/error.c b/gcc/cp/error.c index c6653e7..a2d786c 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1082,12 +1082,6 @@ dump_expr (t, nop) } break; - case WITH_CLEANUP_EXPR: - /* Note that this only works for G++ cleanups. If somebody - builds a general cleanup, there's no way to represent it. */ - dump_expr (TREE_OPERAND (t, 0), 0); - break; - case TARGET_EXPR: /* Note that this only works for G++ target exprs. If somebody builds a general TARGET_EXPR, there's no way to represent that diff --git a/gcc/cp/init.c b/gcc/cp/init.c index bc0dc51..c5ec252 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -865,6 +865,20 @@ do_member_init (s_id, name, init) expand_member_init (build_indirect_ref (base, NULL_PTR), name, init); } +/* Find the context in which this FIELD can be initialized. */ +static tree +initializing_context (field) + tree field; +{ + tree t = DECL_CONTEXT (field); + + /* Anonymous union members can be initialized in the first enclosing + non-anonymous union context. */ + while (t && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) + t = TYPE_CONTEXT (t); + return t; +} + /* Function to give error message if member initialization specification is erroneous. FIELD is the member we decided to initialize. TYPE is the type for which the initialization is being performed. @@ -880,7 +894,7 @@ member_init_ok_or_else (field, type, member_name) { if (field == error_mark_node) return 0; - if (field == NULL_TREE || DECL_CONTEXT (field) != type) + if (field == NULL_TREE || initializing_context (field) != type) { cp_error ("class `%T' does not have any field named `%s'", type, member_name); @@ -2204,7 +2218,14 @@ is_friend (type, supplicant) tree context; if (! declp) - context = DECL_CONTEXT (TYPE_NAME (supplicant)); + { + /* Are we a nested or local class? If so, we aren't friends + with the CONTEXT. */ + if (IS_AGGR_TYPE (supplicant)) + context = NULL_TREE; + else + context = DECL_CONTEXT (TYPE_NAME (supplicant)); + } else if (DECL_FUNCTION_MEMBER_P (supplicant)) context = DECL_CLASS_CONTEXT (supplicant); else diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 8fca04f..7febe10 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -2283,8 +2283,7 @@ check_newline () tricks. */ else { - ungetc (c, finput); - HANDLE_PRAGMA (finput); + c = HANDLE_PRAGMA (finput, c); } #endif #endif @@ -2940,6 +2939,11 @@ do_identifier (token) if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id)) { tree shadowed = DECL_SHADOWED_FOR_VAR (id); + while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL + && DECL_DEAD_FOR_LOCAL (shadowed)) + shadowed = DECL_SHADOWED_FOR_VAR (shadowed); + if (!shadowed) + shadowed = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (id)); if (shadowed) { if (!DECL_ERROR_REPORTED (id)) diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index d40424c..49e7dd2 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -901,7 +901,7 @@ template_instantiate_once: } left_curly opt.component_decl_list '}' { - tree t = finish_struct ($<ttype>3, $5, 0); + tree t = finish_struct ($<ttype>3, $5, NULL_TREE, 0); pop_obstacks (); end_template_instantiation ($1); @@ -2187,7 +2187,7 @@ structsp: | TYPENAME_KEYWORD complex_type_name { $$ = $2; } /* C++ extensions, merged with C to avoid shift/reduce conflicts */ - | class_head left_curly opt.component_decl_list '}' + | class_head left_curly opt.component_decl_list '}' maybe_attribute { int semi; tree id; @@ -2209,7 +2209,7 @@ structsp: /* $$ = $1 from default rule. */; else { - $$ = finish_struct ($$, $3, semi); + $$ = finish_struct ($$, $3, $5, semi); if (semi) note_got_semicolon ($$); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 85f07cc..e34cf5b 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -74,9 +74,6 @@ real_lvalue_p (ref) return 1; break; - case WITH_CLEANUP_EXPR: - return real_lvalue_p (TREE_OPERAND (ref, 0)); - /* A currently unresolved scope ref. */ case SCOPE_REF: my_friendly_abort (103); @@ -147,9 +144,6 @@ lvalue_p (ref) return 1; break; - case WITH_CLEANUP_EXPR: - return lvalue_p (TREE_OPERAND (ref, 0)); - case TARGET_EXPR: return 1; @@ -206,12 +200,7 @@ lvalue_or_else (ref, string) Build an encapsulation of the initialization to perform and return it so that it can be processed by language-independent - and language-specific expression expanders. - - If WITH_CLEANUP_P is nonzero, we build a cleanup for this expression. - Otherwise, cleanups are not built here. For example, when building - an initialization for a stack slot, since the called function handles - the cleanup, we would not want to do it here. */ + and language-specific expression expanders. */ tree build_cplus_new (type, init, with_cleanup_p) tree type; @@ -231,19 +220,6 @@ build_cplus_new (type, init, with_cleanup_p) TREE_SIDE_EFFECTS (rval) = 1; TREE_ADDRESSABLE (rval) = 1; -#if 0 - if (with_cleanup_p && TYPE_NEEDS_DESTRUCTOR (type)) - { - TREE_OPERAND (rval, 2) = error_mark_node; - rval = build (WITH_CLEANUP_EXPR, type, rval, 0, - build_delete (build_pointer_type (type), - build_unary_op (ADDR_EXPR, slot, 0), - integer_two_node, - LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0)); - TREE_SIDE_EFFECTS (rval) = 1; - TREE_ADDRESSABLE (rval) = 1; - } -#endif return rval; } @@ -1808,11 +1784,6 @@ unsave_expr_now (expr) } } break; - - case WITH_CLEANUP_EXPR: - warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR"); - RTL_EXPR_RTL (expr) = NULL_RTX; - break; } switch (TREE_CODE_CLASS (code)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index e182563..0c47de9 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1798,9 +1798,42 @@ build_component_ref (datum, component, basetype_path, protect) } } + /* See if we have to do any conversions so that we pick up the field from the + right context. */ if (DECL_FIELD_CONTEXT (field) != basetype) { tree context = DECL_FIELD_CONTEXT (field); + tree base = context; + while (base != basetype && ANON_AGGRNAME_P (TYPE_IDENTIFIER (base))) + { + base = TYPE_CONTEXT (base); + } + + /* Handle base classes here... */ + if (base != basetype && TYPE_USES_COMPLEX_INHERITANCE (basetype)) + { + tree addr = build_unary_op (ADDR_EXPR, datum, 0); + if (integer_zerop (addr)) + { + error ("invalid reference to NULL ptr, use ptr-to-member instead"); + return error_mark_node; + } + if (VBASE_NAME_P (DECL_NAME (field))) + { + /* It doesn't matter which vbase pointer we grab, just + find one of them. */ + tree binfo = get_binfo (base, + TREE_TYPE (TREE_TYPE (addr)), 0); + addr = convert_pointer_to_real (binfo, addr); + } + else + addr = convert_pointer_to (base, addr); + datum = build_indirect_ref (addr, NULL_PTR); + my_friendly_assert (datum != error_mark_node, 311); + } + basetype = base; + + /* Handle things from anon unions here... */ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (context))) { tree subfield = lookup_anon_field (basetype, context); @@ -1810,28 +1843,6 @@ build_component_ref (datum, component, basetype_path, protect) } } - if (DECL_FIELD_CONTEXT (field) != basetype - && TYPE_USES_COMPLEX_INHERITANCE (basetype)) - { - tree addr = build_unary_op (ADDR_EXPR, datum, 0); - if (integer_zerop (addr)) - { - error ("invalid reference to NULL ptr, use ptr-to-member instead"); - return error_mark_node; - } - if (VBASE_NAME_P (DECL_NAME (field))) - { - /* It doesn't matter which vbase pointer we grab, just - find one of them. */ - tree binfo = get_binfo (DECL_FIELD_CONTEXT (field), - TREE_TYPE (TREE_TYPE (addr)), 0); - addr = convert_pointer_to_real (binfo, addr); - } - else - addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr); - datum = build_indirect_ref (addr, NULL_PTR); - my_friendly_assert (datum != error_mark_node, 311); - } ref = fold (build (COMPONENT_REF, TREE_TYPE (field), break_out_cleanups (datum), field)); @@ -3486,7 +3497,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) resultcode = xresultcode; } - if (short_compare && extra_warnings) + if (short_compare && warn_sign_compare) { int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0)); int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1)); @@ -4308,14 +4319,6 @@ unary_complex_lvalue (code, arg) return build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result); } - if (TREE_CODE (arg) == WITH_CLEANUP_EXPR) - { - tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0); - real_result = build (WITH_CLEANUP_EXPR, TREE_TYPE (real_result), - real_result, 0, TREE_OPERAND (arg, 2)); - return real_result; - } - if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE || TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE) @@ -4402,17 +4405,6 @@ unary_complex_lvalue (code, arg) if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF) return build (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)), TREE_OPERAND (targ, 0), current_function_decl, NULL); - - /* We shouldn't wrap WITH_CLEANUP_EXPRs inside of SAVE_EXPRs, but in case - we do, here's how to handle it. */ - if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == WITH_CLEANUP_EXPR) - { -#if 0 - /* Not really a bug, but something to turn on when testing. */ - compiler_error ("WITH_CLEANUP_EXPR wrapped in SAVE_EXPR"); -#endif - return unary_complex_lvalue (ADDR_EXPR, targ); - } } /* Don't let anything else be handled specially. */ @@ -5661,38 +5653,10 @@ build_modify_expr (lhs, modifycode, rhs) TREE_OPERAND (newrhs, 2)))); } } - else if (modifycode != INIT_EXPR && TREE_CODE (newrhs) == WITH_CLEANUP_EXPR) - { - tree cleanup = TREE_OPERAND (newrhs, 2); - tree slot; - - /* Finish up by running cleanups and having the "value" of the lhs. */ - tree exprlist = tree_cons (NULL_TREE, cleanup, - build_tree_list (NULL_TREE, lhs)); - newrhs = TREE_OPERAND (newrhs, 0); - if (TREE_CODE (newrhs) == TARGET_EXPR) - slot = TREE_OPERAND (newrhs, 0); - else if (TREE_CODE (newrhs) == ADDR_EXPR) - { - /* Bad but valid. */ - slot = newrhs; - warning ("address taken of temporary object"); - } - else - my_friendly_abort (118); - - /* Copy the value computed in SLOT into LHS. */ - exprlist = tree_cons (NULL_TREE, - build_modify_expr (lhs, modifycode, slot), - exprlist); - /* Evaluate the expression that needs CLEANUP. This will - compute the value into SLOT. */ - exprlist = tree_cons (NULL_TREE, newrhs, exprlist); - result = convert (lhstype, build_compound_expr (exprlist)); - } else result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, lhstype, lhs, newrhs); + TREE_SIDE_EFFECTS (result) = 1; /* If we got the LHS in a different type for storing in, @@ -6788,8 +6752,7 @@ c_expand_return (retval) { whats_returned = TREE_OPERAND (whats_returned, 0); while (TREE_CODE (whats_returned) == NEW_EXPR - || TREE_CODE (whats_returned) == TARGET_EXPR - || TREE_CODE (whats_returned) == WITH_CLEANUP_EXPR) + || TREE_CODE (whats_returned) == TARGET_EXPR) { /* Get the target. */ whats_returned = TREE_OPERAND (whats_returned, 0); |