diff options
56 files changed, 1176 insertions, 556 deletions
diff --git a/ChangeLog.melt b/ChangeLog.melt index 54bb20389e2..3eb2d615e84 100644 --- a/ChangeLog.melt +++ b/ChangeLog.melt @@ -1,3 +1,6 @@ +2008-10-18 Basile Starynkevitch <basile@starynkevitch.net> + MELT branch merged with trunk r141209 + 2008-10-15 Basile Starynkevitch <basile@starynkevitch.net> MELT branch merged with trunk r141146 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7983e984915..80b318f288a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,106 @@ +2008-10-17 Andreas Krebbel <krebbel1@de.ibm.com> + + * c-parser.c (c_parser_binary_expression): Silence the + uninitialized variable warning emitted for binary_loc. + +2008-10-16 Daniel Berlin <dberlin@dberlin.org> + + * tree-ssa-pre.c (phi_translate_set): Add constants to phi + translation cache. + +2008-10-16 Joseph Myers <joseph@codesourcery.com> + + PR c/33192 + * c-typeck.c (build_unary_op): Use omit_one_operand for + IMAGPART_EXPR of real argument. + +2008-10-16 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/37664 + * fold-const.c (fold_binary): When optimizing comparison with + highest or lowest type's value, don't consider TREE_OVERFLOW. + +2008-10-16 David Edelsohn <edelsohn@gnu.org> + + PR target/35483 + * Makefile.in (coverage.o): Depend on $(TM_P_H). + * coverage.c: Include tm_p.h. + * config/rs6000/x-aix (jc1): Override LDFLAGS. + * config/rs6000/xcoff.h (ASM_GENERATE_INTERNAL_LABEL): Strip + dollar signs from PREFIX. + * config/rs6000/rs6000.c (output_toc): Use RS6000_OUTPUT_BASENAME + instead of manual strip_name_encoding. + +2008-10-16 Richard Guenther <rguenther@suse.de> + + PR middle-end/37418 + * tree-ssa.c (useless_type_conversion_p_1): Do not treat + volatile qualified functions or methods as relevant. + +2008-10-16 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/37525 + * tree.c (int_fits_type_p): Rewrite using double_int. Zero extend + sizetype unsigned constants, both in the case of C and bounds. + +2008-10-15 Jan Hubicka <jh@suse.cz> + + * ira-emit.c (change_regs): Return false when replacing reg by + itself. + +2008-10-14 Vladimir Makarov <vmakarov@redhat.com> + + PR target/37633 + * ira-costs.c (ira_tune_allocno_costs_and_cover_classes): Check + HARD_REGNO_CALL_PART_CLOBBERED. + +2008-10-15 Vladimir Makarov <vmakarov@redhat.com> + + PR middle-end/37535 + * ira-lives.c (mark_early_clobbers): Remove. + (make_pseudo_conflict, check_and_make_def_use_conflicts, + check_and_make_def_conflicts, + make_early_clobber_and_input_conflicts, + mark_hard_reg_early_clobbers): New functions. + (process_bb_node_lives): Call + make_early_clobber_and_input_conflicts and + mark_hard_reg_early_clobbers. Make hard register inputs live + again. + + * doc/rtl.texi (clobber): Change descriotion of RA behaviour for + early clobbers of pseudo-registers. + +2008-10-15 Vladimir Makarov <vmakarov@redhat.com> + + PR middle-end/37674 + * ira-build.c (ira_flattening): Recalculate + ALLOCNO_TOTAL_NO_STACK_REG_P and ALLOCNO_TOTAL_CONFLICT_HARD_REGS + from the scratch instead of the propagation. + +2008-10-15 Richard Sandiford <rdsandiford@googlemail.com> + + * doc/rtl.texi (const_double): Remove the "addr" operand. + Describe CONST_DOUBLE_* macros under const_double rather + than const_vector. + (const_fixed): Fix the operand description. + (const): Add an @findex directive. + (CONST0_RTX, CONST1_RTX, CONST2_RTX): Move description + after the constant rtl table. + (fix): Combine floating-point and fixed-point descriptions. + Fix hyphenation. + * sched-deps.c (sched_analyze_2): Remove reference to + CONST_DOUBLE_CHAIN. + +2008-10-15 Richard Sandiford <rdsandiford@googlemail.com> + + * config/mn10300/mn10300.h (OUTPUT_ADDR_CONST_EXTRA): Handle + UNSPEC_GOTSYM_OFFs. + * config/mn10300/mn10300.c (legitimate_pic_operand_p): Return true + for UNSPEC_GOTSYM_OFFs. + * config/mn10300/mn10300.md (UNSPEC_GOTSYM_OFF): New unspec. + (add_GOT_to_pic_reg): Use it. + * config/mn10300/constraints.md (S): Allow UNSPEC_GOTSYM_OFF. + 2008-10-15 Jan Sjodin <jan.sjodin@amd.com> Harsha Jagasia <harsha.jagasia@amd.com> @@ -64,6 +167,23 @@ already implies hard float. Also fix several insn condition with TARGET_DFP which shall require TARGET_HARD_DFP instead. +2008-10-15 David Edelsohn <edelsohn@gnu.org> + + PR target/35483 + Based on patches by Laurent Vivier. + * xcoffout.h (DBX_FINISH_STABS): Translate dollar sign to underscore. + * config/rs6000/rs6000-protos.h (rs6000_xcoff_strip_dollar): Declare. + * config/rs6000/xcoff.h (ASM_DECLARE_FUNCTION_NAME): Translate + dollar sign to underscore. + (ASM_OUTPUT_EXTERNAL): Same. + (ASM_OUTPUT_LABELREF): New. + * config/rs6000/rs6000.c (rs6000_xcoff_strip_dollar): New. + + * config/rs6000/aix51.h (TARGET_USE_JCR_SECTION): Define. + * config/rs6000/aix52.h (TARGET_USE_JCR_SECTION): Define. + * config/rs6000/aix53.h (TARGET_USE_JCR_SECTION): Define. + * config/rs6000/aix61.h (TARGET_USE_JCR_SECTION): Define. + 2008-10-15 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/36881 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 8f9cc3472a0..081aad70ac4 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20081015 +20081018 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 594f4b98ff9..167f1f5d253 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2717,7 +2717,7 @@ ipa-struct-reorg.o: ipa-struct-reorg.c ipa-struct-reorg.h $(CONFIG_H) $(SYSTEM_H coverage.o : coverage.c $(GCOV_IO_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) \ $(FUNCTION_H) $(TOPLEV_H) $(GGC_H) langhooks.h $(COVERAGE_H) gt-coverage.h \ - $(HASHTAB_H) tree-iterator.h $(CGRAPH_H) tree-pass.h gcov-io.c + $(HASHTAB_H) tree-iterator.h $(CGRAPH_H) tree-pass.h gcov-io.c $(TM_P_H) cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(RECOG_H) \ $(EMIT_RTL_H) $(TOPLEV_H) output.h $(FUNCTION_H) cselib.h $(GGC_H) $(TM_P_H) \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7cbfc1b6d99..caee7260244 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2008-10-17 Geert Bosch <bosch@adacore.com> + + * gcc-interface/trans.c (gnat_to_gnu) <N_Slice>: Simplify expansion + to use only a single check instead of three, and avoid unnecessary + COMPOUND_EXPR. + (emit_check): Avoid useless COMPOUND_EXPRs and SAVE_EXPRs, sometimes + creating more opportunities for optimizations. + 2008-10-13 Jakub Jelinek <jakub@redhat.com> PR middle-end/37601 diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index e4c86225fac..6ade56869d9 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -3563,32 +3563,40 @@ gnat_to_gnu (Node_Id gnat_node) /* Get the permitted bounds. */ tree gnu_base_index_type = TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)); - tree gnu_base_min_expr = TYPE_MIN_VALUE (gnu_base_index_type); - tree gnu_base_max_expr = TYPE_MAX_VALUE (gnu_base_index_type); + tree gnu_base_min_expr = SUBSTITUTE_PLACEHOLDER_IN_EXPR + (TYPE_MIN_VALUE (gnu_base_index_type), gnu_result); + tree gnu_base_max_expr = SUBSTITUTE_PLACEHOLDER_IN_EXPR + (TYPE_MAX_VALUE (gnu_base_index_type), gnu_result); tree gnu_expr_l, gnu_expr_h, gnu_expr_type; - /* Check to see that the minimum slice value is in range. */ - gnu_expr_l = emit_index_check (gnu_result, - gnu_min_expr, - gnu_base_min_expr, - gnu_base_max_expr); - - /* Check to see that the maximum slice value is in range. */ - gnu_expr_h = emit_index_check (gnu_result, - gnu_max_expr, - gnu_base_min_expr, - gnu_base_max_expr); + gnu_min_expr = protect_multiple_eval (gnu_min_expr); + gnu_max_expr = protect_multiple_eval (gnu_max_expr); /* Derive a good type to convert everything to. */ - gnu_expr_type = get_base_type (TREE_TYPE (gnu_expr_l)); - - /* Build a compound expression that does the range checks and - returns the low bound. */ - gnu_expr = build_binary_op (COMPOUND_EXPR, gnu_expr_type, - convert (gnu_expr_type, gnu_expr_h), - convert (gnu_expr_type, gnu_expr_l)); - - /* Build a conditional expression that does the range check and + gnu_expr_type = get_base_type (TREE_TYPE (gnu_index_type)); + + /* Test whether the minimum slice value is too small. */ + gnu_expr_l = build_binary_op (LT_EXPR, integer_type_node, + convert (gnu_expr_type, + gnu_min_expr), + convert (gnu_expr_type, + gnu_base_min_expr)); + + /* Test whether the maximum slice value is too large. */ + gnu_expr_h = build_binary_op (GT_EXPR, integer_type_node, + convert (gnu_expr_type, + gnu_max_expr), + convert (gnu_expr_type, + gnu_base_max_expr)); + + /* Build a slice index check that returns the low bound, + assuming the slice is not empty. */ + gnu_expr = emit_check + (build_binary_op (TRUTH_ORIF_EXPR, integer_type_node, + gnu_expr_l, gnu_expr_h), + gnu_min_expr, CE_Index_Check_Failed); + + /* Build a conditional expression that does the index checks and returns the low bound if the slice is not empty (max >= min), and returns the naked low bound otherwise (max < min), unless it is non-constant and the high bound is; this prevents VRP @@ -6186,33 +6194,18 @@ emit_index_check (tree gnu_array_object, static tree emit_check (tree gnu_cond, tree gnu_expr, int reason) { - tree gnu_call; - tree gnu_result; + tree gnu_call = build_call_raise (reason, Empty, N_Raise_Constraint_Error); + tree gnu_result + = fold_build3 (COND_EXPR, TREE_TYPE (gnu_expr), gnu_cond, + build2 (COMPOUND_EXPR, TREE_TYPE (gnu_expr), gnu_call, + convert (TREE_TYPE (gnu_expr), integer_zero_node)), + gnu_expr); - gnu_call = build_call_raise (reason, Empty, N_Raise_Constraint_Error); - - /* Use an outer COMPOUND_EXPR to make sure that GNU_EXPR will get evaluated - in front of the comparison in case it ends up being a SAVE_EXPR. Put the - whole thing inside its own SAVE_EXPR so the inner SAVE_EXPR doesn't leak - out. */ - gnu_result = fold_build3 (COND_EXPR, TREE_TYPE (gnu_expr), gnu_cond, - build2 (COMPOUND_EXPR, TREE_TYPE (gnu_expr), - gnu_call, gnu_expr), - gnu_expr); - - /* If GNU_EXPR has side effects, make the outer COMPOUND_EXPR and - protect it. Otherwise, show GNU_RESULT has no side effects: we - don't need to evaluate it just for the check. */ - if (TREE_SIDE_EFFECTS (gnu_expr)) - gnu_result - = build2 (COMPOUND_EXPR, TREE_TYPE (gnu_expr), gnu_expr, gnu_result); - else - TREE_SIDE_EFFECTS (gnu_result) = 0; + /* GNU_RESULT has side effects if and only if GNU_EXPR has: + we don't need to evaluate it just for the check. */ + TREE_SIDE_EFFECTS (gnu_result) = TREE_SIDE_EFFECTS (gnu_expr); - /* ??? Unfortunately, if we don't put a SAVE_EXPR around this whole thing, - we will repeatedly do the test. It would be nice if GCC was able - to optimize this and only do it once. */ - return save_expr (gnu_result); + return gnu_result; } /* Return an expression that converts GNU_EXPR to GNAT_TYPE, doing diff --git a/gcc/c-parser.c b/gcc/c-parser.c index f08b2813010..0fc579b3e98 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -4583,7 +4583,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) } stack[NUM_PRECS]; int sp; /* Location of the binary operator. */ - location_t binary_loc; + location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */ #define POP \ do { \ switch (stack[sp].op) \ diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index ab8df375448..da98c43c4bf 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -3038,7 +3038,7 @@ build_unary_op (location_t location, else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) ret = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); else - ret = convert (TREE_TYPE (arg), integer_zero_node); + ret = omit_one_operand (TREE_TYPE (arg), integer_zero_node, arg); goto return_build_unary_op; case PREINCREMENT_EXPR: diff --git a/gcc/config/mn10300/constraints.md b/gcc/config/mn10300/constraints.md index 53f128750c7..8dbf63a75ba 100644 --- a/gcc/config/mn10300/constraints.md +++ b/gcc/config/mn10300/constraints.md @@ -68,7 +68,8 @@ (if_then_else (match_test "flag_pic") (and (match_test "GET_CODE (op) == UNSPEC") (ior (match_test "XINT (op, 1) == UNSPEC_PLT") - (match_test "XINT (op, 1) == UNSPEC_PIC"))) + (match_test "XINT (op, 1) == UNSPEC_PIC") + (match_test "XINT (op, 1) == UNSPEC_GOTSYM_OFF"))) (match_test "GET_CODE (op) == SYMBOL_REF"))) ;; Integer constraints diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index f89e0751c4c..eed82997244 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -1869,7 +1869,8 @@ legitimate_pic_operand_p (rtx x) && (XINT (x, 1) == UNSPEC_PIC || XINT (x, 1) == UNSPEC_GOT || XINT (x, 1) == UNSPEC_GOTOFF - || XINT (x, 1) == UNSPEC_PLT)) + || XINT (x, 1) == UNSPEC_PLT + || XINT (x, 1) == UNSPEC_GOTSYM_OFF)) return 1; fmt = GET_RTX_FORMAT (GET_CODE (x)); diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h index c1c80579427..d83eedfb08a 100644 --- a/gcc/config/mn10300/mn10300.h +++ b/gcc/config/mn10300/mn10300.h @@ -738,7 +738,7 @@ while (0) constants. Used for PIC-specific UNSPECs. */ #define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \ do \ - if (GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1) \ + if (GET_CODE (X) == UNSPEC) \ { \ switch (XINT ((X), 1)) \ { \ @@ -762,6 +762,12 @@ while (0) output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \ fputs ("@PLT", (STREAM)); \ break; \ + case UNSPEC_GOTSYM_OFF: \ + assemble_name (STREAM, GOT_SYMBOL_NAME); \ + fputs ("-(", STREAM); \ + output_addr_const (STREAM, XVECEXP (X, 0, 0)); \ + fputs ("-.)", STREAM); \ + break; \ default: \ goto FAIL; \ } \ diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md index 8fbbdc87df5..38aa37645ac 100644 --- a/gcc/config/mn10300/mn10300.md +++ b/gcc/config/mn10300/mn10300.md @@ -45,6 +45,7 @@ (UNSPEC_GOT 2) (UNSPEC_GOTOFF 3) (UNSPEC_PLT 4) + (UNSPEC_GOTSYM_OFF 5) ]) (include "predicates.md") @@ -2619,18 +2620,9 @@ [(set (reg:SI PIC_REG) (plus:SI (reg:SI PIC_REG) - (const - (unspec [(minus:SI - (match_dup 1) - (const (minus:SI - (const (match_operand:SI 0 "" "")) - (pc)))) - ] UNSPEC_PIC))))] - "" - " -{ - operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME); -}") + (const:SI + (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_GOTSYM_OFF))))] + "") (define_expand "symGOT2reg" [(match_operand:SI 0 "" "") diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 612c7d45d67..6df7aa79732 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -18097,7 +18097,6 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode) { char buf[256]; const char *name = buf; - const char *real_name; rtx base = x; HOST_WIDE_INT offset = 0; @@ -18371,12 +18370,12 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode) gcc_unreachable (); } - real_name = (*targetm.strip_name_encoding) (name); if (TARGET_MINIMAL_TOC) fputs (TARGET_32BIT ? "\t.long " : DOUBLE_INT_ASM_OP, file); else { - fprintf (file, "\t.tc %s", real_name); + fputs ("\t.tc ", file); + RS6000_OUTPUT_BASENAME (file, name); if (offset < 0) fprintf (file, ".N" HOST_WIDE_INT_PRINT_UNSIGNED, - offset); diff --git a/gcc/config/rs6000/x-aix b/gcc/config/rs6000/x-aix index 32e7357f329..11ccb932d4b 100644 --- a/gcc/config/rs6000/x-aix +++ b/gcc/config/rs6000/x-aix @@ -1,3 +1,6 @@ # genautomata requires more than 256MB of data build/genautomata : override LDFLAGS += -Wl,-bmaxdata:0x20000000 +# jc1 requires more than 256MB of data +jc1 : override LDFLAGS += -Wl,-bmaxdata:0x20000000 + diff --git a/gcc/config/rs6000/xcoff.h b/gcc/config/rs6000/xcoff.h index 08e06b4a757..c8193908a97 100644 --- a/gcc/config/rs6000/xcoff.h +++ b/gcc/config/rs6000/xcoff.h @@ -257,7 +257,7 @@ This is suitable for output with `assemble_name'. */ #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*%s..%u", (PREFIX), (unsigned) (NUM)) + sprintf (LABEL, "*%s..%u", rs6000_xcoff_strip_dollar (PREFIX), (unsigned) (NUM)) /* This is how to output an assembler line to define N characters starting at P to FILE. */ diff --git a/gcc/coverage.c b/gcc/coverage.c index 2d4f791bc58..b2ac87651d3 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "function.h" #include "toplev.h" +#include "tm_p.h" #include "ggc.h" #include "coverage.h" #include "langhooks.h" diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index a12de2152bb..1411f24e5d9 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -1507,21 +1507,33 @@ Similarly, there is only one object for the integer whose value is @code{constm1_rtx} will point to the same object. @findex const_double -@item (const_double:@var{m} @var{addr} @var{i0} @var{i1} @dots{}) +@item (const_double:@var{m} @var{i0} @var{i1} @dots{}) Represents either a floating-point constant of mode @var{m} or an integer constant too large to fit into @code{HOST_BITS_PER_WIDE_INT} bits but small enough to fit within twice that number of bits (GCC does not provide a mechanism to represent even larger constants). In the latter case, @var{m} will be @code{VOIDmode}. +@findex CONST_DOUBLE_LOW +If @var{m} is @code{VOIDmode}, the bits of the value are stored in +@var{i0} and @var{i1}. @var{i0} is customarily accessed with the macro +@code{CONST_DOUBLE_LOW} and @var{i1} with @code{CONST_DOUBLE_HIGH}. + +If the constant is floating point (regardless of its precision), then +the number of integers used to store the value depends on the size of +@code{REAL_VALUE_TYPE} (@pxref{Floating Point}). The integers +represent a floating point number, but not precisely in the target +machine's or host machine's floating point format. To convert them to +the precise bit pattern used by the target machine, use the macro +@code{REAL_VALUE_TO_TARGET_DOUBLE} and friends (@pxref{Data Output}). + @findex const_fixed -@item (const_fixed:@var{m} @var{addr}) +@item (const_fixed:@var{m} @dots{}) Represents a fixed-point constant of mode @var{m}. -The data structure, which contains data with the size of two -@code{HOST_BITS_PER_WIDE_INT} and the associated fixed-point mode, -is access with the macro @code{CONST_FIXED_VALUE}. The high part of data -is accessed with @code{CONST_FIXED_VALUE_HIGH}; the low part is accessed -with @code{CONST_FIXED_VALUE_LOW}. +The operand is a data structure of type @code{struct fixed_value} and +is accessed with the macro @code{CONST_FIXED_VALUE}. The high part of +data is accessed with @code{CONST_FIXED_VALUE_HIGH}; the low part is +accessed with @code{CONST_FIXED_VALUE_LOW}. @findex const_vector @item (const_vector:@var{m} [@var{x0} @var{x1} @dots{}]) @@ -1537,44 +1549,6 @@ Individual elements in a vector constant are accessed with the macro where @var{v} is the vector constant and @var{n} is the element desired. -@findex CONST_DOUBLE_MEM -@findex CONST_DOUBLE_CHAIN -@var{addr} is used to contain the @code{mem} expression that corresponds -to the location in memory that at which the constant can be found. If -it has not been allocated a memory location, but is on the chain of all -@code{const_double} expressions in this compilation (maintained using an -undisplayed field), @var{addr} contains @code{const0_rtx}. If it is not -on the chain, @var{addr} contains @code{cc0_rtx}. @var{addr} is -customarily accessed with the macro @code{CONST_DOUBLE_MEM} and the -chain field via @code{CONST_DOUBLE_CHAIN}. - -@findex CONST_DOUBLE_LOW -If @var{m} is @code{VOIDmode}, the bits of the value are stored in -@var{i0} and @var{i1}. @var{i0} is customarily accessed with the macro -@code{CONST_DOUBLE_LOW} and @var{i1} with @code{CONST_DOUBLE_HIGH}. - -If the constant is floating point (regardless of its precision), then -the number of integers used to store the value depends on the size of -@code{REAL_VALUE_TYPE} (@pxref{Floating Point}). The integers -represent a floating point number, but not precisely in the target -machine's or host machine's floating point format. To convert them to -the precise bit pattern used by the target machine, use the macro -@code{REAL_VALUE_TO_TARGET_DOUBLE} and friends (@pxref{Data Output}). - -@findex CONST0_RTX -@findex CONST1_RTX -@findex CONST2_RTX -The macro @code{CONST0_RTX (@var{mode})} refers to an expression with -value 0 in mode @var{mode}. If mode @var{mode} is of mode class -@code{MODE_INT}, it returns @code{const0_rtx}. If mode @var{mode} is of -mode class @code{MODE_FLOAT}, it returns a @code{CONST_DOUBLE} -expression in mode @var{mode}. Otherwise, it returns a -@code{CONST_VECTOR} expression in mode @var{mode}. Similarly, the macro -@code{CONST1_RTX (@var{mode})} refers to an expression with value 1 in -mode @var{mode} and similarly for @code{CONST2_RTX}. The -@code{CONST1_RTX} and @code{CONST2_RTX} macros are undefined -for vector modes. - @findex const_string @item (const_string @var{str}) Represents a constant string with value @var{str}. Currently this is @@ -1605,6 +1579,7 @@ references is so that jump optimization can distinguish them. The @code{label_ref} contains a mode, which is usually @code{Pmode}. Usually that is the only mode for which a label is directly valid. +@findex const @item (const:@var{m} @var{exp}) Represents a constant that is the result of an assembly-time arithmetic computation. The operand, @var{exp}, is an expression that @@ -1627,6 +1602,20 @@ reference a global memory location. @var{m} should be @code{Pmode}. @end table +@findex CONST0_RTX +@findex CONST1_RTX +@findex CONST2_RTX +The macro @code{CONST0_RTX (@var{mode})} refers to an expression with +value 0 in mode @var{mode}. If mode @var{mode} is of mode class +@code{MODE_INT}, it returns @code{const0_rtx}. If mode @var{mode} is of +mode class @code{MODE_FLOAT}, it returns a @code{CONST_DOUBLE} +expression in mode @var{mode}. Otherwise, it returns a +@code{CONST_VECTOR} expression in mode @var{mode}. Similarly, the macro +@code{CONST1_RTX (@var{mode})} refers to an expression with value 1 in +mode @var{mode} and similarly for @code{CONST2_RTX}. The +@code{CONST1_RTX} and @code{CONST2_RTX} macros are undefined +for vector modes. + @node Regs and Memory @section Registers and Memory @cindex RTL register expressions @@ -2707,7 +2696,12 @@ regarded as unsigned, to floating point mode @var{m}. @findex fix @item (fix:@var{m} @var{x}) -When @var{m} is a fixed point mode, represents the result of +When @var{m} is a floating-point mode, represents the result of +converting floating point value @var{x} (valid for mode @var{m}) to an +integer, still represented in floating point mode @var{m}, by rounding +towards zero. + +When @var{m} is a fixed-point mode, represents the result of converting floating point value @var{x} to mode @var{m}, regarded as signed. How rounding is done is not specified, so this operation may be used validly in compiling C code only for integer-valued operands. @@ -2718,13 +2712,6 @@ Represents the result of converting floating point value @var{x} to fixed point mode @var{m}, regarded as unsigned. How rounding is done is not specified. -@findex fix -@item (fix:@var{m} @var{x}) -When @var{m} is a floating point mode, represents the result of -converting floating point value @var{x} (valid for mode @var{m}) to an -integer, still represented in floating point mode @var{m}, by rounding -towards zero. - @findex fract_convert @item (fract_convert:@var{m} @var{x}) Represents the result of converting fixed-point value @var{x} to @@ -2930,11 +2917,12 @@ constituent instructions might not. When a @code{clobber} expression for a register appears inside a @code{parallel} with other side effects, the register allocator guarantees that the register is unoccupied both before and after that -insn if it is a hard register clobber or the @samp{&} constraint -is specified for at least one alternative (@pxref{Modifiers}) of the -clobber. However, the reload phase may allocate a register used for -one of the inputs unless the @samp{&} constraint is specified for the -selected alternative. You can clobber either a specific hard +insn if it is a hard register clobber. For pseudo-register clobber, +the register allocator and the reload pass do not assign the same hard +register to the clobber and the input operands if there is an insn +alternative containing the @samp{&} constraint (@pxref{Modifiers}) for +the clobber and the hard register is in register classes of the +clobber in the alternative. You can clobber either a specific hard register, a pseudo register, or a @code{scratch} expression; in the latter two cases, GCC will allocate a hard register that is available there for use as a temporary. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0ce122a1554..605caa812e0 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -12447,7 +12447,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) unsigned int width = TYPE_PRECISION (arg1_type); if (TREE_CODE (arg1) == INTEGER_CST - && !TREE_OVERFLOW (arg1) && width <= 2 * HOST_BITS_PER_WIDE_INT && (INTEGRAL_TYPE_P (arg1_type) || POINTER_TYPE_P (arg1_type))) { diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 1d26c1f2c97..d4ff6b34c30 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,8 @@ +2008-10-16 Daniel Kraft <d@domob.eu> + + * resolve.c (resolve_elemental_actual): Handle calls to intrinsic + subroutines correctly. + 2008-10-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> * simplify.c: Remove MPFR_VERSION_NUM(2,3,0) conditionals. diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 70d3ad5df99..1816907c3ec 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -1352,10 +1352,18 @@ resolve_elemental_actual (gfc_expr *expr, gfc_code *c) else return SUCCESS; } - else if (c && c->ext.actual != NULL && c->symtree->n.sym->attr.elemental) + else if (c && c->ext.actual != NULL) { arg0 = c->ext.actual; - esym = c->symtree->n.sym; + + if (c->resolved_sym) + esym = c->resolved_sym; + else + esym = c->symtree->n.sym; + gcc_assert (esym); + + if (!esym->attr.elemental) + return SUCCESS; } else return SUCCESS; diff --git a/gcc/ira-build.c b/gcc/ira-build.c index 55a3beb71bd..3d58e5521ad 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -2102,7 +2102,7 @@ void ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) { int i, j, num; - bool propagate_p, stop_p, keep_p; + bool stop_p, keep_p; int hard_regs_num; bool new_pseudos_p, merged_p, mem_dest_p; unsigned int n; @@ -2114,20 +2114,29 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) ira_allocno_iterator ai; ira_copy_iterator ci; sparseset allocnos_live; - bool *allocno_propagated_p; regno_top_level_allocno_map = (ira_allocno_t *) ira_allocate (max_reg_num () * sizeof (ira_allocno_t)); memset (regno_top_level_allocno_map, 0, max_reg_num () * sizeof (ira_allocno_t)); - allocno_propagated_p - = (bool *) ira_allocate (ira_allocnos_num * sizeof (bool)); - memset (allocno_propagated_p, 0, ira_allocnos_num * sizeof (bool)); new_pseudos_p = merged_p = false; + FOR_EACH_ALLOCNO (a, ai) + { + if (ALLOCNO_CAP_MEMBER (a) != NULL) + /* Caps are not in the regno allocno maps and they are never + will be transformed into allocnos existing after IR + flattening. */ + continue; + COPY_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), + ALLOCNO_CONFLICT_HARD_REGS (a)); +#ifdef STACK_REGS + ALLOCNO_TOTAL_NO_STACK_REG_P (a) = ALLOCNO_NO_STACK_REG_P (a); +#endif + } /* Fix final allocno attributes. */ for (i = max_regno_before_emit - 1; i >= FIRST_PSEUDO_REGISTER; i--) { - mem_dest_p = propagate_p = false; + mem_dest_p = false; for (a = ira_regno_allocno_map[i]; a != NULL; a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) @@ -2145,27 +2154,17 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) continue; } ira_assert (ALLOCNO_CAP_MEMBER (parent_a) == NULL); + if (ALLOCNO_MEM_OPTIMIZED_DEST (a) != NULL) mem_dest_p = true; - if (propagate_p) + if (REGNO (ALLOCNO_REG (a)) == REGNO (ALLOCNO_REG (parent_a))) { - if (!allocno_propagated_p [ALLOCNO_NUM (parent_a)]) - COPY_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a), - ALLOCNO_CONFLICT_HARD_REGS (parent_a)); IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a), ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a)); #ifdef STACK_REGS - if (!allocno_propagated_p [ALLOCNO_NUM (parent_a)]) - ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) - = ALLOCNO_NO_STACK_REG_P (parent_a); - ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) - = (ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) - || ALLOCNO_TOTAL_NO_STACK_REG_P (a)); + if (ALLOCNO_TOTAL_NO_STACK_REG_P (a)) + ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true; #endif - allocno_propagated_p [ALLOCNO_NUM (parent_a)] = true; - } - if (REGNO (ALLOCNO_REG (a)) == REGNO (ALLOCNO_REG (parent_a))) - { if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL) { fprintf (ira_dump_file, @@ -2188,7 +2187,6 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) continue; } new_pseudos_p = true; - propagate_p = true; first = ALLOCNO_MEM_OPTIMIZED_DEST (a) == NULL ? NULL : a; stop_p = false; for (;;) @@ -2240,7 +2238,6 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) if (mem_dest_p && copy_live_ranges_to_removed_store_destinations (i)) merged_p = true; } - ira_free (allocno_propagated_p); ira_assert (new_pseudos_p || ira_max_point_before_emit == ira_max_point); if (merged_p || ira_max_point_before_emit != ira_max_point) ira_rebuild_start_finish_chains (); diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 774902035e1..64b2e7995d6 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -1572,8 +1572,8 @@ ira_tune_allocno_costs_and_cover_classes (void) regno = ira_class_hard_regs[cover_class][j]; rclass = REGNO_REG_CLASS (regno); cost = 0; - /* ??? If only part is call clobbered. */ - if (! ira_hard_reg_not_in_set_p (regno, mode, call_used_reg_set)) + if (! ira_hard_reg_not_in_set_p (regno, mode, call_used_reg_set) + || HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) cost += (ALLOCNO_CALL_FREQ (a) * (ira_memory_move_cost[mode][rclass][0] + ira_memory_move_cost[mode][rclass][1])); diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c index 7fdaefb52e5..a6a7582f519 100644 --- a/gcc/ira-emit.c +++ b/gcc/ira-emit.c @@ -137,6 +137,7 @@ change_regs (rtx *loc) int i, regno, result = false; const char *fmt; enum rtx_code code; + rtx reg; if (*loc == NULL_RTX) return false; @@ -151,7 +152,10 @@ change_regs (rtx *loc) return false; if (ira_curr_regno_allocno_map[regno] == NULL) return false; - *loc = ALLOCNO_REG (ira_curr_regno_allocno_map[regno]); + reg = ALLOCNO_REG (ira_curr_regno_allocno_map[regno]); + if (reg == *loc) + return false; + *loc = reg; return true; } diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index 89343fe30f3..f4b2d6de42b 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -349,39 +349,169 @@ mark_ref_dead (df_ref def) mark_reg_dead (reg); } -/* Mark early clobber registers of the current INSN as live (if - LIVE_P) or dead. Return true if there are such registers. */ +/* Make pseudo REG conflicting with pseudo DREG, if the 1st pseudo + class is intersected with class CL. Advance the current program + point before making the conflict if ADVANCE_P. Return TRUE if we + will need to advance the current program point. */ static bool -mark_early_clobbers (rtx insn, bool live_p) +make_pseudo_conflict (rtx reg, enum reg_class cl, rtx dreg, bool advance_p) { - int alt; - int def; - df_ref *def_rec; - bool set_p = false; + ira_allocno_t a; - for (def = 0; def < recog_data.n_operands; def++) - { - rtx dreg = recog_data.operand[def]; - - if (GET_CODE (dreg) == SUBREG) - dreg = SUBREG_REG (dreg); - if (! REG_P (dreg)) - continue; + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + + if (! REG_P (reg) || REGNO (reg) < FIRST_PSEUDO_REGISTER) + return advance_p; + + a = ira_curr_regno_allocno_map[REGNO (reg)]; + if (! reg_classes_intersect_p (cl, ALLOCNO_COVER_CLASS (a))) + return advance_p; - for (alt = 0; alt < recog_data.n_alternatives; alt++) - if ((recog_op_alt[def][alt].earlyclobber) - && (recog_op_alt[def][alt].cl != NO_REGS)) - break; + if (advance_p) + curr_point++; - if (alt >= recog_data.n_alternatives) - continue; + mark_reg_live (reg); + mark_reg_live (dreg); + mark_reg_dead (reg); + mark_reg_dead (dreg); + + return false; +} - if (live_p) - mark_reg_live (dreg); +/* Check and make if necessary conflicts for pseudo DREG of class + DEF_CL of the current insn with input operand USE of class USE_CL. + Advance the current program point before making the conflict if + ADVANCE_P. Return TRUE if we will need to advance the current + program point. */ +static bool +check_and_make_def_use_conflict (rtx dreg, enum reg_class def_cl, + int use, enum reg_class use_cl, + bool advance_p) +{ + if (! reg_classes_intersect_p (def_cl, use_cl)) + return advance_p; + + advance_p = make_pseudo_conflict (recog_data.operand[use], + use_cl, dreg, advance_p); + /* Reload may end up swapping commutative operands, so you + have to take both orderings into account. The + constraints for the two operands can be completely + different. (Indeed, if the constraints for the two + operands are the same for all alternatives, there's no + point marking them as commutative.) */ + if (use < recog_data.n_operands + 1 + && recog_data.constraints[use][0] == '%') + advance_p + = make_pseudo_conflict (recog_data.operand[use + 1], + use_cl, dreg, advance_p); + if (use >= 1 + && recog_data.constraints[use - 1][0] == '%') + advance_p + = make_pseudo_conflict (recog_data.operand[use - 1], + use_cl, dreg, advance_p); + return advance_p; +} + +/* Check and make if necessary conflicts for definition DEF of class + DEF_CL of the current insn with input operands. Process only + constraints of alternative ALT. */ +static void +check_and_make_def_conflict (int alt, int def, enum reg_class def_cl) +{ + int use, use_match; + ira_allocno_t a; + enum reg_class use_cl, acl; + bool advance_p; + rtx dreg = recog_data.operand[def]; + + if (def_cl == NO_REGS) + return; + + if (GET_CODE (dreg) == SUBREG) + dreg = SUBREG_REG (dreg); + + if (! REG_P (dreg) || REGNO (dreg) < FIRST_PSEUDO_REGISTER) + return; + + a = ira_curr_regno_allocno_map[REGNO (dreg)]; + acl = ALLOCNO_COVER_CLASS (a); + if (! reg_classes_intersect_p (acl, def_cl)) + return; + + advance_p = true; + + for (use = 0; use < recog_data.n_operands; use++) + { + if (use == def || recog_data.operand_type[use] == OP_OUT) + return; + + if (recog_op_alt[use][alt].anything_ok) + use_cl = ALL_REGS; else - mark_reg_dead (dreg); - set_p = true; + use_cl = recog_op_alt[use][alt].cl; + + advance_p = check_and_make_def_use_conflict (dreg, def_cl, use, + use_cl, advance_p); + + if ((use_match = recog_op_alt[use][alt].matches) >= 0) + { + if (use_match == def) + return; + + if (recog_op_alt[use_match][alt].anything_ok) + use_cl = ALL_REGS; + else + use_cl = recog_op_alt[use_match][alt].cl; + advance_p = check_and_make_def_use_conflict (dreg, def_cl, use, + use_cl, advance_p); + } } +} + +/* Make conflicts of early clobber pseudo registers of the current + insn with its inputs. Avoid introducing unnecessary conflicts by + checking classes of the constraints and pseudos because otherwise + significant code degradation is possible for some targets. */ +static void +make_early_clobber_and_input_conflicts (void) +{ + int alt; + int def, def_match; + enum reg_class def_cl; + + for (alt = 0; alt < recog_data.n_alternatives; alt++) + for (def = 0; def < recog_data.n_operands; def++) + { + def_cl = NO_REGS; + if (recog_op_alt[def][alt].earlyclobber) + { + if (recog_op_alt[def][alt].anything_ok) + def_cl = ALL_REGS; + else + def_cl = recog_op_alt[def][alt].cl; + check_and_make_def_conflict (alt, def, def_cl); + } + if ((def_match = recog_op_alt[def][alt].matches) >= 0 + && (recog_op_alt[def_match][alt].earlyclobber + || recog_op_alt[def][alt].earlyclobber)) + { + if (recog_op_alt[def_match][alt].anything_ok) + def_cl = ALL_REGS; + else + def_cl = recog_op_alt[def_match][alt].cl; + check_and_make_def_conflict (alt, def, def_cl); + } + } +} + +/* Mark early clobber hard registers of the current INSN as live (if + LIVE_P) or dead. Return true if there are such registers. */ +static bool +mark_hard_reg_early_clobbers (rtx insn, bool live_p) +{ + df_ref *def_rec; + bool set_p = false; for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) if (DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MUST_CLOBBER)) @@ -792,25 +922,36 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) } } + make_early_clobber_and_input_conflicts (); + curr_point++; /* Mark each used value as live. */ for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) mark_ref_live (*use_rec); - set_p = mark_early_clobbers (insn, true); - process_single_reg_class_operands (true, freq); + set_p = mark_hard_reg_early_clobbers (insn, true); + if (set_p) { - mark_early_clobbers (insn, false); + mark_hard_reg_early_clobbers (insn, false); - /* Mark each used value as live again. For example, a + /* Mark each hard reg as live again. For example, a hard register can be in clobber and in an insn input. */ for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) - mark_ref_live (*use_rec); + { + rtx ureg = DF_REF_REG (*use_rec); + + if (GET_CODE (ureg) == SUBREG) + ureg = SUBREG_REG (ureg); + if (! REG_P (ureg) || REGNO (ureg) >= FIRST_PSEUDO_REGISTER) + continue; + + mark_ref_live (*use_rec); + } } curr_point++; diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index d987bbe71b7..40454a0f5dd 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,11 @@ +2008-10-16 David Edelsohn <edelsohn@gnu.org> + + PR target/35483 + * Make-lang.in (class.o): Depend on $(TM_P_H). + (expr.o): Same. + * class.c: Include tm_p.h. + * expr.c: Include tm_p.h. + 2008-10-14 Andrew Haley <aph@redhat.com> * constants.c (build_constant_data_ref): Make sure we only build diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index f188c7d788d..2db3065f629 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -256,7 +256,7 @@ java/builtins.o: java/builtins.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ gt-java-builtins.h java/class.o: java/class.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(JAVA_TREE_H) $(RTL_H) java/jcf.h java/parse.h toplev.h output.h $(GGC_H) \ - $(TARGET_H) $(FUNCTION_H) gt-java-class.h $(CGRAPH_H) + $(TARGET_H) $(FUNCTION_H) gt-java-class.h $(CGRAPH_H) $(TM_P_H) java/constants.o: java/constants.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \ toplev.h $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) gt-java-constants.h java/decl.o: java/decl.c $(CONFIG_H) $(JAVA_TREE_H) $(RTL_H) java/jcf.h \ @@ -270,7 +270,7 @@ java/expr.o: java/expr.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h $(REAL_H) \ $(RTL_H) $(EXPR_H) java/javaop.h java/java-opcodes.h except.h \ java/java-except.h java/java-except.h java/parse.h toplev.h \ $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) gt-java-expr.h $(TARGET_H) \ - tree-iterator.h + tree-iterator.h $(TM_P_H) java/jcf-depend.o: java/jcf-depend.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) java/jcf.h java/jcf-parse.o: java/jcf-parse.c $(CONFIG_H) $(JAVA_TREE_H) $(FLAGS_H) \ diff --git a/gcc/java/class.c b/gcc/java/class.c index 13cc54e024d..edd16f0ad61 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -38,6 +38,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "output.h" #include "parse.h" #include "function.h" +#include "tm_p.h" #include "ggc.h" #include "stdio.h" #include "target.h" diff --git a/gcc/java/expr.c b/gcc/java/expr.c index e1c00824248..858bc937d93 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -41,6 +41,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "parse.h" #include "toplev.h" #include "except.h" +#include "tm_p.h" #include "ggc.h" #include "tree-iterator.h" #include "gimple.h" diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index 784f84ff63d..81fcb806228 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -2008,10 +2008,7 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn) case SYMBOL_REF: case CONST: case LABEL_REF: - /* Ignore constants. Note that we must handle CONST_DOUBLE here - because it may have a cc0_rtx in its CONST_DOUBLE_CHAIN field, but - this does not mean that this insn is using cc0. */ - + /* Ignore constants. */ if (cslr_p && sched_deps_info->finish_rhs) sched_deps_info->finish_rhs (); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8cee6d05feb..5c14eceddbf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,36 @@ +2008-10-18 Danny Smith <dannysmith@users.sourceforge.net> + + * gcc.dg/dll-2.c: Revert 2008-08-09 change (R138893): Change + "dg-message" back to "dg-warning". + * gcc.dg/dll-3.c: Likewise. + +2008-10-16 Alexander Monakov <amonakov@ispras.ru> + + PR target/37381 + * gcc.c-torture/compile/pr37381.c: New test. + +2008-10-16 Joseph Myers <joseph@codesourcery.com> + + PR c/33192 + * gcc.dg/imag-1.c: New test. + +2008-10-16 Daniel Kraft <d@domob.eu> + + * gfortran.dg/elemental_intrinsic_1.f03: New test. + +2008-10-16 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/37664 + * gcc.c-torture/compile/pr37664.c: New test. + +2008-10-16 Joseph Myers <joseph@codesourcery.com> + + PR middle-end/37418 + * gcc.c-torture/compile/pr37418-1.c, + gcc.c-torture/compile/pr37418-2.c, + gcc.c-torture/compile/pr37418-3.c, + gcc.c-torture/compile/pr37418-4.c: New tests. + 2008-10-15 Thomas Koenig <tkoenig@gcc.gnu.org> PR libfortran/34670 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37381.c b/gcc/testsuite/gcc.c-torture/compile/pr37381.c new file mode 100644 index 00000000000..a2fed66c4ee --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr37381.c @@ -0,0 +1,97 @@ +extern unsigned int __invalid_size_argument_for_IOC; +typedef unsigned int __u32; +struct video_window +{ + __u32 x, y; + __u32 width, height; +}; +typedef unsigned long XID; +typedef XID Window; +typedef struct _XExtData +{ + Window root; +} +Screen; +typedef struct +{ + int border_width; +} +XWindowAttributes; +typedef struct _XDisplay Display; +typedef struct +{ + int default_screen; + Screen *screens; +} + *_XPrivDisplay; +typedef struct +{ + int x, y; +} +XSizeHints; +typedef struct +{ + unsigned short hdisplay; + unsigned short vdisplay; +} +XF86VidModeModeInfo; +Display *display; +int tfd; +int ccapt; +int tml; +int fswidth = 0; +int fsheight = 0; +Window fmwin; +XF86VidModeModeInfo **modelines, *fullscreenmode = ((void *) 0); +struct video_window vswin; +DoFullScreen (void) +{ + int i; + int rx, ry; + Window junkwin; + XSizeHints fmsizehints; + XWindowAttributes fmwinattr; + if (ioctl + (tfd, + (((1U) << (((0 + 8) + 8) + 14)) | ((('v')) << (0 + 8)) | (((8)) << 0) | + (((((sizeof (int) == sizeof (int[1]) + && sizeof (int) < + (1 << 14)) ? sizeof (int) : __invalid_size_argument_for_IOC))) << + ((0 + 8) + 8))), &ccapt) < 0) + { + perror ("ioctl VIDIOCCAPTURE"); + } + if (!XTranslateCoordinates + (display, fmwin, + ((&((_XPrivDisplay) display)-> + screens[(((_XPrivDisplay) display)->default_screen)])->root), + -fmwinattr.border_width, -fmwinattr.border_width, &rx, &ry, &junkwin)) + { + } + vswin.width = fswidth; + vswin.height = fsheight; + vswin.x = fmsizehints.x + rx; + vswin.y = fmsizehints.y + ry; + if (ioctl + (tfd, + (((1U) << (((0 + 8) + 8) + 14)) | ((('v')) << (0 + 8)) | (((8)) << 0) | + (((((sizeof (int) == sizeof (int[1]) + && sizeof (int) < + (1 << 14)) ? sizeof (int) : __invalid_size_argument_for_IOC))) << + ((0 + 8) + 8))), &ccapt) < 0) + { + XF86VidModeGetAllModeLines (display, XDefaultScreen (display), &tml, + &modelines); + { + if ((modelines[i]->hdisplay == fswidth) + && (modelines[i]->vdisplay == fsheight)) + { + fullscreenmode = modelines[i]; + } + } + { + XF86VidModeSetViewPort (display, XDefaultScreen (display), vswin.x, + vswin.y); + } + } +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37418-1.c b/gcc/testsuite/gcc.c-torture/compile/pr37418-1.c new file mode 100644 index 00000000000..dbb1a651ddb --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr37418-1.c @@ -0,0 +1,6 @@ +typedef void ft(int); +void f(int args)__attribute__((noreturn)); +void f2(ft *p __attribute__((noreturn))) +{ + p = f; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37418-2.c b/gcc/testsuite/gcc.c-torture/compile/pr37418-2.c new file mode 100644 index 00000000000..dcc003984ac --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr37418-2.c @@ -0,0 +1,6 @@ +typedef void ft(int); +volatile ft f; +void f2(ft *p __attribute__((noreturn))) +{ + p = f; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37418-3.c b/gcc/testsuite/gcc.c-torture/compile/pr37418-3.c new file mode 100644 index 00000000000..5a2c2e81ead --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr37418-3.c @@ -0,0 +1,6 @@ +typedef void ft(int); +void f(int args)__attribute__((const)); +void f2(ft *p __attribute__((const))) +{ + p = f; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37418-4.c b/gcc/testsuite/gcc.c-torture/compile/pr37418-4.c new file mode 100644 index 00000000000..bc872789004 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr37418-4.c @@ -0,0 +1,6 @@ +typedef void ft(int); +const ft f; +void f2(ft *p __attribute__((const))) +{ + p = f; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37664.c b/gcc/testsuite/gcc.c-torture/compile/pr37664.c new file mode 100644 index 00000000000..cf5c83d7b2d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr37664.c @@ -0,0 +1,14 @@ +/* PR tree-optimization/37664 */ + +int v; + +int +foo () +{ + int a = 0x8899A862; + int b = 0x8E * a; + int c = (b % b); + if (v > (4294967295U >> c)) + return v; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/dll-2.c b/gcc/testsuite/gcc.dg/dll-2.c index 334299f3a27..3b8b60eee41 100644 --- a/gcc/testsuite/gcc.dg/dll-2.c +++ b/gcc/testsuite/gcc.dg/dll-2.c @@ -11,12 +11,12 @@ /* { dg-require-dll "" } */ __declspec (dllimport) int foo1 (); -__declspec (dllexport) int foo1 (); /* { dg-message "note: previous dllimport ignored" } */ +__declspec (dllexport) int foo1 (); /* { dg-warning "previous dllimport ignored" } */ __declspec (dllexport) int foo2 (); __declspec (dllimport) int foo2 (); /* { dg-warning "dllimport ignored" } */ __declspec (dllimport) int bar1; -__declspec (dllexport) int bar1; /* { dg-message "note: previous dllimport ignored" } */ +__declspec (dllexport) int bar1; /* { dg-warning "previous dllimport ignored" } */ __declspec (dllexport) int bar2; __declspec (dllimport) int bar2; /* { dg-warning "dllimport ignored" } */ diff --git a/gcc/testsuite/gcc.dg/dll-3.c b/gcc/testsuite/gcc.dg/dll-3.c index 4272891a848..0a3f7df0988 100644 --- a/gcc/testsuite/gcc.dg/dll-3.c +++ b/gcc/testsuite/gcc.dg/dll-3.c @@ -5,7 +5,7 @@ /* { dg-do compile { target i?86-pc-mingw* } } */ __declspec (dllimport) int foo1 (); -__declspec (dllexport) int foo1 (); /* { dg-message "note: previous dllimport ignored" } */ +__declspec (dllexport) int foo1 (); /* { dg-warning "previous dllimport ignored" } */ __declspec (dllexport) int foo2 (); __declspec (dllimport) int foo2 (); /* { dg-warning "dllimport ignored" } */ diff --git a/gcc/testsuite/gcc.dg/imag-1.c b/gcc/testsuite/gcc.dg/imag-1.c new file mode 100644 index 00000000000..e07ef72e43c --- /dev/null +++ b/gcc/testsuite/gcc.dg/imag-1.c @@ -0,0 +1,18 @@ +/* Test for __imag__ side effects; see PR 33192. */ +/* Origin: Joseph Myers <joseph@codesourcery.com> */ +/* { dg-do run } */ +/* { dg-options "-std=gnu99" } */ + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + int i, j; + i = 1; + j = __imag__ ++i; + if (i != 2 || j != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gfortran.dg/elemental_intrinsic_1.f03 b/gcc/testsuite/gfortran.dg/elemental_intrinsic_1.f03 new file mode 100644 index 00000000000..8fdaa0fe9e5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/elemental_intrinsic_1.f03 @@ -0,0 +1,11 @@ +! { dg-do compile } + +! Conformance-checking of arguments was not done for intrinsic elemental +! subroutines, check this works now. + +! This is the test from PR fortran/35681, comment #1 (second program). + + integer, dimension(10) :: ILA1 = (/1,2,3,4,5,6,7,8,9,10/) + call mvbits ((ILA1((/9/))), 2, 4, ILA1, 3) ! { dg-error "Different shape" } + write (*,'(10(I3))') ila1 + end diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 84c884b060c..f57500e62ac 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -1745,9 +1745,8 @@ phi_translate_set (bitmap_set_t dest, bitmap_set_t set, basic_block pred, pre_expr translated; translated = phi_translate (expr, set, NULL, pred, phiblock); - /* Don't add constants or empty translations to the cache, since - we won't look them up that way, or use the result, anyway. */ - if (translated && !value_id_constant_p (get_expr_value_id (translated))) + /* Don't add empty translations to the cache */ + if (translated) phi_trans_add (expr, translated, pred); if (translated != NULL) diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index c53c5287453..8f238a33da6 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -1125,9 +1125,14 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type) { /* Don't lose casts between pointers to volatile and non-volatile qualified types. Doing so would result in changing the semantics - of later accesses. */ - if ((TYPE_VOLATILE (TREE_TYPE (outer_type)) - != TYPE_VOLATILE (TREE_TYPE (inner_type))) + of later accesses. For function types the volatile qualifier + is used to indicate noreturn functions. */ + if (TREE_CODE (TREE_TYPE (outer_type)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (outer_type)) != METHOD_TYPE + && TREE_CODE (TREE_TYPE (inner_type)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (inner_type)) != METHOD_TYPE + && (TYPE_VOLATILE (TREE_TYPE (outer_type)) + != TYPE_VOLATILE (TREE_TYPE (inner_type))) && TYPE_VOLATILE (TREE_TYPE (outer_type))) return false; diff --git a/gcc/tree.c b/gcc/tree.c index b131a20875c..7064e06bcec 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6406,11 +6406,28 @@ get_narrower (tree op, int *unsignedp_ptr) int int_fits_type_p (const_tree c, const_tree type) { - tree type_low_bound = TYPE_MIN_VALUE (type); - tree type_high_bound = TYPE_MAX_VALUE (type); - bool ok_for_low_bound, ok_for_high_bound; - unsigned HOST_WIDE_INT low; - HOST_WIDE_INT high; + tree type_low_bound, type_high_bound; + bool ok_for_low_bound, ok_for_high_bound, unsc; + double_int dc, dd; + + dc = tree_to_double_int (c); + unsc = TYPE_UNSIGNED (TREE_TYPE (c)); + + if (TREE_CODE (TREE_TYPE (c)) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (TREE_TYPE (c)) + && unsc) + /* So c is an unsigned integer whose type is sizetype and type is not. + sizetype'd integers are sign extended even though they are + unsigned. If the integer value fits in the lower end word of c, + and if the higher end word has all its bits set to 1, that + means the higher end bits are set to 1 only for sign extension. + So let's convert c into an equivalent zero extended unsigned + integer. */ + dc = double_int_zext (dc, TYPE_PRECISION (TREE_TYPE (c))); + +retry: + type_low_bound = TYPE_MIN_VALUE (type); + type_high_bound = TYPE_MAX_VALUE (type); /* If at least one bound of the type is a constant integer, we can check ourselves and maybe make a decision. If no such decision is possible, but @@ -6422,25 +6439,25 @@ int_fits_type_p (const_tree c, const_tree type) for "unknown if constant fits", 0 for "constant known *not* to fit" and 1 for "constant known to fit". */ - if (TREE_TYPE (c) == sizetype - && TYPE_UNSIGNED (TREE_TYPE (c)) - && TREE_INT_CST_HIGH (c) == -1 - && !TREE_OVERFLOW (c)) - /* So c is an unsigned integer which type is sizetype. - sizetype'd integers are sign extended even though they are - unsigned. If the integer value fits in the lower end word of c, - and if the higher end word has all its bits set to 1, that - means the higher end bits are set to 1 only for sign extension. - So let's convert c into an equivalent zero extended unsigned - integer. */ - c = force_fit_type_double (size_type_node, - TREE_INT_CST_LOW (c), - TREE_INT_CST_HIGH (c), - false, false); - /* Check if C >= type_low_bound. */ + /* Check if c >= type_low_bound. */ if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST) { - if (tree_int_cst_lt (c, type_low_bound)) + dd = tree_to_double_int (type_low_bound); + if (TREE_CODE (type) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (type) + && TYPE_UNSIGNED (type)) + dd = double_int_zext (dd, TYPE_PRECISION (type)); + if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_low_bound))) + { + int c_neg = (!unsc && double_int_negative_p (dc)); + int t_neg = (unsc && double_int_negative_p (dd)); + + if (c_neg && !t_neg) + return 0; + if ((c_neg || !t_neg) && double_int_ucmp (dc, dd) < 0) + return 0; + } + else if (double_int_cmp (dc, dd, unsc) < 0) return 0; ok_for_low_bound = true; } @@ -6450,7 +6467,22 @@ int_fits_type_p (const_tree c, const_tree type) /* Check if c <= type_high_bound. */ if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST) { - if (tree_int_cst_lt (type_high_bound, c)) + dd = tree_to_double_int (type_high_bound); + if (TREE_CODE (type) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (type) + && TYPE_UNSIGNED (type)) + dd = double_int_zext (dd, TYPE_PRECISION (type)); + if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_high_bound))) + { + int c_neg = (!unsc && double_int_negative_p (dc)); + int t_neg = (unsc && double_int_negative_p (dd)); + + if (t_neg && !c_neg) + return 0; + if ((t_neg || !c_neg) && double_int_ucmp (dc, dd) > 0) + return 0; + } + else if (double_int_cmp (dc, dd, unsc) > 0) return 0; ok_for_high_bound = true; } @@ -6464,7 +6496,7 @@ int_fits_type_p (const_tree c, const_tree type) /* Perform some generic filtering which may allow making a decision even if the bounds are not constant. First, negative integers never fit in unsigned types, */ - if (TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0) + if (TYPE_UNSIGNED (type) && !unsc && double_int_negative_p (dc)) return 0; /* Second, narrower types always fit in wider ones. */ @@ -6472,10 +6504,18 @@ int_fits_type_p (const_tree c, const_tree type) return 1; /* Third, unsigned integers with top bit set never fit signed types. */ - if (! TYPE_UNSIGNED (type) - && TYPE_UNSIGNED (TREE_TYPE (c)) - && tree_int_cst_msb (c)) - return 0; + if (! TYPE_UNSIGNED (type) && unsc) + { + int prec = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (c))) - 1; + if (prec < HOST_BITS_PER_WIDE_INT) + { + if (((((unsigned HOST_WIDE_INT) 1) << prec) & dc.low) != 0) + return 0; + } + else if (((((unsigned HOST_WIDE_INT) 1) + << (prec - HOST_BITS_PER_WIDE_INT)) & dc.high) != 0) + return 0; + } /* If we haven't been able to decide at this point, there nothing more we can check ourselves here. Look at the base type if we have one and it @@ -6483,12 +6523,13 @@ int_fits_type_p (const_tree c, const_tree type) if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0 && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type))) - return int_fits_type_p (c, TREE_TYPE (type)); + { + type = TREE_TYPE (type); + goto retry; + } /* Or to fit_double_type, if nothing else. */ - low = TREE_INT_CST_LOW (c); - high = TREE_INT_CST_HIGH (c); - return !fit_double_type (low, high, &low, &high, type); + return !fit_double_type (dc.low, dc.high, &dc.low, &dc.high, type); } /* Stores bounds of an integer TYPE in MIN and MAX. If TYPE has non-constant diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index ae4e64e071a..cf3d9302673 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,28 @@ +2008-10-17 Jerry DeLisle <jvdelisle@gcc.gnu.org + + PR libfortran/37863 + * io/write_float.def (WRITE_FLOAT): Round to 1.0 correctly. + * io/io.h (st_parameter_44): Fix id type declaration. + +2008-10-16 Thomas Koenig <tkoenig@gcc.gnu.org> + + * io/file_pos.c (unformatted_backspace): Normal case is + GFC_CONVERT_NATIVE. + * io/transfer.c (read_sf): Mark paths leading to generate_error() + as unlikely. + (readl_block_form): Likewise. + (read_block_direct): Likewise. + (write_block): Likewise. + (write_buf): Likewise. + (us_read): Likewise. Normal case is GFC_CONVERT_NATIVE. + (next_record_w_unf): Mark paths leading to generate_error() + as unlikely. + +2008-10-16 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR libfortran/34670 + * generated/spread_r4.c: Regenerated. + 2008-10-15 Thomas Koenig <tkoenig@gcc.gnu.org> PR libfortran/34670 diff --git a/libgfortran/generated/spread_r4.c b/libgfortran/generated/spread_r4.c index a9357afdc61..c151df3122a 100644 --- a/libgfortran/generated/spread_r4.c +++ b/libgfortran/generated/spread_r4.c @@ -131,8 +131,7 @@ spread_r4 (gfc_array_r4 *ret, const gfc_array_r4 *source, if (n == along - 1) { rdelta = ret->dim[n].stride; - printf("ret_extent = %ld, ncopies = %ld\n", - (long int) ret_extent, (long int) ncopies); + if (ret_extent != ncopies) runtime_error("Incorrect extent in return value of SPREAD" " intrinsic in dimension %ld: is %ld," diff --git a/libgfortran/io/file_pos.c b/libgfortran/io/file_pos.c index 6dafbe59028..25b0108eef4 100644 --- a/libgfortran/io/file_pos.c +++ b/libgfortran/io/file_pos.c @@ -120,7 +120,7 @@ unformatted_backspace (st_parameter_filepos *fpp, gfc_unit *u) goto io_error; /* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */ - if (u->flags.convert == GFC_CONVERT_NATIVE) + if (likely (u->flags.convert == GFC_CONVERT_NATIVE)) { switch (length) { diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h index 710224de21d..ec37be37a81 100644 --- a/libgfortran/io/io.h +++ b/libgfortran/io/io.h @@ -458,7 +458,7 @@ typedef struct st_parameter_43 typedef struct st_parameter_44 { - GFC_IO_INT *id; + GFC_INTEGER_4 *id; GFC_IO_INT pos; CHARACTER1 (asynchronous); CHARACTER2 (blank); diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c index acc7cbe9b94..8d4f785e49a 100644 --- a/libgfortran/io/transfer.c +++ b/libgfortran/io/transfer.c @@ -205,7 +205,8 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error) if (is_internal_unit (dtp)) { readlen = *length; - if (sread (dtp->u.p.current_unit->s, p, &readlen) != 0 || readlen < (size_t) *length) + if (unlikely (sread (dtp->u.p.current_unit->s, p, &readlen) != 0 + || readlen < (size_t) *length)) { generate_error (&dtp->common, LIBERROR_END, NULL); return NULL; @@ -219,7 +220,7 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error) do { - if (sread (dtp->u.p.current_unit->s, &q, &readlen) != 0) + if (unlikely (sread (dtp->u.p.current_unit->s, &q, &readlen) != 0)) { generate_error (&dtp->common, LIBERROR_END, NULL); return NULL; @@ -229,7 +230,7 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error) EOR below. */ if (readlen < 1 && n == 0) { - if (no_error) + if (likely (no_error)) break; generate_error (&dtp->common, LIBERROR_END, NULL); return NULL; @@ -250,7 +251,8 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error) { readlen = 1; pos = stream_offset (dtp->u.p.current_unit->s); - if (sread (dtp->u.p.current_unit->s, &q, &readlen) != 0) + if (unlikely (sread (dtp->u.p.current_unit->s, &q, &readlen) + != 0)) { generate_error (&dtp->common, LIBERROR_END, NULL); return NULL; @@ -266,7 +268,7 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error) so we can just continue with a short read. */ if (dtp->u.p.current_unit->pad_status == PAD_NO) { - if (no_error) + if (likely (no_error)) break; generate_error (&dtp->common, LIBERROR_EOR, NULL); return NULL; @@ -332,7 +334,7 @@ read_block_form (st_parameter_dt *dtp, void *buf, size_t *nbytes) dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl; else { - if (dtp->u.p.current_unit->pad_status == PAD_NO) + if (unlikely (dtp->u.p.current_unit->pad_status == PAD_NO)) { /* Not enough data left. */ generate_error (&dtp->common, LIBERROR_EOR, NULL); @@ -340,7 +342,7 @@ read_block_form (st_parameter_dt *dtp, void *buf, size_t *nbytes) } } - if (dtp->u.p.current_unit->bytes_left == 0) + if (unlikely (dtp->u.p.current_unit->bytes_left == 0)) { dtp->u.p.current_unit->endfile = AT_ENDFILE; generate_error (&dtp->common, LIBERROR_END, NULL); @@ -368,7 +370,7 @@ read_block_form (st_parameter_dt *dtp, void *buf, size_t *nbytes) dtp->u.p.current_unit->bytes_left -= (gfc_offset) *nbytes; nread = *nbytes; - if (sread (dtp->u.p.current_unit->s, buf, &nread) != 0) + if (unlikely (sread (dtp->u.p.current_unit->s, buf, &nread) != 0)) { generate_error (&dtp->common, LIBERROR_OS, NULL); return FAILURE; @@ -379,7 +381,7 @@ read_block_form (st_parameter_dt *dtp, void *buf, size_t *nbytes) if (nread != *nbytes) { /* Short read, this shouldn't happen. */ - if (dtp->u.p.current_unit->pad_status == PAD_YES) + if (likely (dtp->u.p.current_unit->pad_status == PAD_YES)) *nbytes = nread; else { @@ -410,7 +412,8 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes) { to_read_record = *nbytes; have_read_record = to_read_record; - if (sread (dtp->u.p.current_unit->s, buf, &have_read_record) != 0) + if (unlikely (sread (dtp->u.p.current_unit->s, buf, &have_read_record) + != 0)) { generate_error (&dtp->common, LIBERROR_OS, NULL); return; @@ -418,7 +421,7 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes) dtp->u.p.current_unit->strm_pos += (gfc_offset) have_read_record; - if (to_read_record != have_read_record) + if (unlikely (to_read_record != have_read_record)) { /* Short read, e.g. if we hit EOF. For stream files, we have to set the end-of-file condition. */ @@ -445,7 +448,8 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes) dtp->u.p.current_unit->bytes_left -= to_read_record; - if (sread (dtp->u.p.current_unit->s, buf, &to_read_record) != 0) + if (unlikely (sread (dtp->u.p.current_unit->s, buf, &to_read_record) + != 0)) { generate_error (&dtp->common, LIBERROR_OS, NULL); return; @@ -459,7 +463,7 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes) return; } - if (short_record) + if (unlikely (short_record)) { generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL); return; @@ -471,7 +475,7 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes) until the request has been fulfilled or the record has run out of continuation subrecords. */ - if (dtp->u.p.current_unit->endfile == AT_ENDFILE) + if (unlikely (dtp->u.p.current_unit->endfile == AT_ENDFILE)) { generate_error (&dtp->common, LIBERROR_END, NULL); return; @@ -509,8 +513,8 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes) dtp->u.p.current_unit->bytes_left_subrecord -= to_read_subrecord; have_read_subrecord = to_read_subrecord; - if (sread (dtp->u.p.current_unit->s, buf + have_read_record, - &have_read_subrecord) != 0) + if (unlikely (sread (dtp->u.p.current_unit->s, buf + have_read_record, + &have_read_subrecord) != 0)) { generate_error (&dtp->common, LIBERROR_OS, NULL); return; @@ -518,7 +522,7 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes) have_read_record += have_read_subrecord; - if (to_read_subrecord != have_read_subrecord) + if (unlikely (to_read_subrecord != have_read_subrecord)) { /* Short read, e.g. if we hit EOF. This means the record @@ -532,7 +536,7 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes) if (to_read_record > 0) { - if (dtp->u.p.current_unit->continued) + if (likely (dtp->u.p.current_unit->continued)) { next_record_r_unf (dtp, 0); us_read (dtp, 1); @@ -556,7 +560,7 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes) } dtp->u.p.current_unit->bytes_left -= have_read_record; - if (short_record) + if (unlikely (short_record)) { generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL); return; @@ -581,9 +585,11 @@ write_block (st_parameter_dt *dtp, int length) { /* For preconnected units with default record length, set bytes left to unit record length and proceed, otherwise error. */ - if ((dtp->u.p.current_unit->unit_number == options.stdout_unit - || dtp->u.p.current_unit->unit_number == options.stderr_unit) - && dtp->u.p.current_unit->recl == DEFAULT_RECL) + if (likely ((dtp->u.p.current_unit->unit_number + == options.stdout_unit + || dtp->u.p.current_unit->unit_number + == options.stderr_unit) + && dtp->u.p.current_unit->recl == DEFAULT_RECL)) dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl; else { @@ -605,7 +611,7 @@ write_block (st_parameter_dt *dtp, int length) return NULL; } - if (dtp->u.p.current_unit->endfile == AT_ENDFILE) + if (unlikely (dtp->u.p.current_unit->endfile == AT_ENDFILE)) generate_error (&dtp->common, LIBERROR_END, NULL); } else @@ -642,7 +648,7 @@ write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes) if (is_stream_io (dtp)) { - if (swrite (dtp->u.p.current_unit->s, buf, &nbytes) != 0) + if (unlikely (swrite (dtp->u.p.current_unit->s, buf, &nbytes) != 0)) { generate_error (&dtp->common, LIBERROR_OS, NULL); return FAILURE; @@ -657,7 +663,7 @@ write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes) if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT) { - if (dtp->u.p.current_unit->bytes_left < (gfc_offset) nbytes) + if (unlikely (dtp->u.p.current_unit->bytes_left < (gfc_offset) nbytes)) { generate_error (&dtp->common, LIBERROR_DIRECT_EOR, NULL); return FAILURE; @@ -666,7 +672,7 @@ write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes) if (buf == NULL && nbytes == 0) return SUCCESS; - if (swrite (dtp->u.p.current_unit->s, buf, &nbytes) != 0) + if (unlikely (swrite (dtp->u.p.current_unit->s, buf, &nbytes) != 0)) { generate_error (&dtp->common, LIBERROR_OS, NULL); return FAILURE; @@ -703,8 +709,8 @@ write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes) dtp->u.p.current_unit->bytes_left_subrecord -= (gfc_offset) to_write_subrecord; - if (swrite (dtp->u.p.current_unit->s, buf + have_written, - &to_write_subrecord) != 0) + if (unlikely (swrite (dtp->u.p.current_unit->s, buf + have_written, + &to_write_subrecord) != 0)) { generate_error (&dtp->common, LIBERROR_OS, NULL); return FAILURE; @@ -721,7 +727,7 @@ write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes) us_write (dtp, 1); } dtp->u.p.current_unit->bytes_left -= have_written; - if (short_record) + if (unlikely (short_record)) { generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL); return FAILURE; @@ -973,7 +979,7 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind, if (f == NULL) { /* No data descriptors left. */ - if (n > 0) + if (unlikely (n > 0)) generate_error (&dtp->common, LIBERROR_FORMAT, "Insufficient data descriptors in format after reversion"); return; @@ -1671,7 +1677,7 @@ us_read (st_parameter_dt *dtp, int continued) nr = n; - if (sread (dtp->u.p.current_unit->s, &i, &n) != 0) + if (unlikely (sread (dtp->u.p.current_unit->s, &i, &n) != 0)) { generate_error (&dtp->common, LIBERROR_BAD_US, NULL); return; @@ -1683,14 +1689,14 @@ us_read (st_parameter_dt *dtp, int continued) return; /* end of file */ } - if (n != nr) + if (unlikely (n != nr)) { generate_error (&dtp->common, LIBERROR_BAD_US, NULL); return; } /* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */ - if (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE) + if (likely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE)) { switch (nr) { @@ -2535,7 +2541,7 @@ write_us_marker (st_parameter_dt *dtp, const gfc_offset buf) len = compile_options.record_marker; /* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */ - if (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE) + if (likely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE)) { switch (len) { @@ -2600,7 +2606,7 @@ next_record_w_unf (st_parameter_dt *dtp, int next_subrecord) else m_write = m; - if (write_us_marker (dtp, m_write) != 0) + if (unlikely (write_us_marker (dtp, m_write) != 0)) goto io_error; if (compile_options.record_marker == 0) @@ -2611,8 +2617,8 @@ next_record_w_unf (st_parameter_dt *dtp, int next_subrecord) /* Seek to the head and overwrite the bogus length with the real length. */ - if (sseek (dtp->u.p.current_unit->s, c - m - record_marker) - == FAILURE) + if (unlikely (sseek (dtp->u.p.current_unit->s, c - m - record_marker) + == FAILURE)) goto io_error; if (next_subrecord) @@ -2620,12 +2626,13 @@ next_record_w_unf (st_parameter_dt *dtp, int next_subrecord) else m_write = m; - if (write_us_marker (dtp, m_write) != 0) + if (unlikely (write_us_marker (dtp, m_write) != 0)) goto io_error; /* Seek past the end of the current record. */ - if (sseek (dtp->u.p.current_unit->s, c + record_marker) == FAILURE) + if (unlikely (sseek (dtp->u.p.current_unit->s, c + record_marker) + == FAILURE)) goto io_error; return; diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def index 0ee8f3560c4..73a6ed14a1b 100644 --- a/libgfortran/io/write_float.def +++ b/libgfortran/io/write_float.def @@ -746,7 +746,7 @@ sprintf (buffer, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \ if (tmp < 0.5)\ tmp = 0.0;\ else if (tmp < 1.0)\ - tmp = tmp + 0.5;\ + tmp = 1.0;\ }\ zero_flag = (tmp == 0.0);\ \ diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7d653fec328..18aa1778d5e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,67 @@ +2008-10-17 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/forward_list.tcc (forward_list<>:: + _M_initialize_dispatch(_InputIterator, _InputIterator, __false_type)): + Simplify. + +2008-10-17 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/forward_list.h (forward_list<>:: + forward_list(size_type)): Tweak, use _Base default constructor. + +2008-10-17 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/forward_list.h (forward_list<>::insert_after): Minor + cosmetic changes. + +2008-10-16 Edward Smith-Rowland <3dw4rd@verizon.net> + + * include/bits/forward_list.h: Factor list construction to dispatch + routines. + * include/bits/forward_list.tcc: Likewise. + * testsuite/23_containers/forward_list/modifiers/2.cc: + +2008-10-16 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/forward_list.tcc (operator==): Use auto. + +2008-10-16 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/forward_list.h (_Fwd_list_base<>::_M_insert_after): + Move out of line, tweak to return _Fwd_list_node_base*. + (forward_list<>::insert_after(const_iterator, const _Tp&), + forward_list<>::insert_after(const_iterator, _Tp&&)): Use it. + * include/bits/forward_list.tcc (_Fwd_list_base<>::_M_insert_after): + Define. + + * include/bits/forward_list.h (forward_list<>): Consistently qualify + calls of base class functions with this->. + * include/bits/forward_list.tcc (forward_list<>): Likewise. + + * include/bits/forward_list.h: Move some functions out of line... + * include/bits/forward_list.tcc: ... here. + + * include/bits/forward_list.h (forward_list<>::resize(size_type)): Fix. + +2008-10-15 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/forward_list.h: Remove pointless const qualifiers in + const_casts. + * include/bits/forward_list.tcc: Likewise. + + * include/bits/forward_list.h (forward_list<>::pointer, + const_pointer, reference, const_reference): Fix, use _Tp_alloc_type. + * testsuite/23_containers/forward_list/requirements/ + explicit_instantiation/1.cc: New. + * testsuite/23_containers/forward_list/requirements/ + explicit_instantiation/1.cc: Likewise. + +2008-10-15 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/forward_list.h (forward_list<>::max_size): Use + Node_allocator; minor cosmetic changes. + * testsuite/23_containers/forward_list/capacity/1.cc: Adjust. + 2008-10-15 Edward Smith-Rowland <3dw4rd@verizon.net> * include/std/forward_list: New. diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index 8e5a6b0a72c..60b187fb483 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -31,8 +31,8 @@ * This is a Standard C++ Library header. */ -#ifndef _GLIBCXX_FORWARD_LIST_H -#define _GLIBCXX_FORWARD_LIST_H 1 +#ifndef _FORWARD_LIST_H +#define _FORWARD_LIST_H 1 #pragma GCC system_header @@ -88,7 +88,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_reverse_after() { _Fwd_list_node_base* __tail = this->_M_next; - if (! __tail) + if (!__tail) return; while (_Fwd_list_node_base* __temp = __tail->_M_next) { @@ -282,6 +282,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) typedef typename _Alloc::template rebind<_Fwd_list_node<_Tp>>::other _Node_alloc_type; + typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type; + struct _Fwd_list_impl : public _Node_alloc_type { @@ -291,7 +293,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) : _Node_alloc_type(), _M_head() { } - explicit _Fwd_list_impl(const _Node_alloc_type& __a) : _Node_alloc_type(__a), _M_head() { } @@ -300,7 +301,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _Fwd_list_impl _M_impl; public: - typedef _Alloc allocator_type; typedef _Fwd_list_iterator<_Tp> iterator; typedef _Fwd_list_const_iterator<_Tp> const_iterator; @@ -314,15 +314,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _M_get_Node_allocator() const { return *static_cast<const _Node_alloc_type*>(&this->_M_impl); } - allocator_type - get_allocator() const - { return this->_M_get_Node_allocator(); } - _Fwd_list_base() : _M_impl() { this->_M_impl._M_head._M_next = 0; } - _Fwd_list_base(const allocator_type& __a) + _Fwd_list_base(const _Alloc& __a) : _M_impl(__a) { this->_M_impl._M_head._M_next = 0; } @@ -350,32 +346,25 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<typename... _Args> _Node* _M_create_node(_Args&&... __args) - { - _Node* __node = this->_M_get_node(); - try - { - _M_get_Node_allocator().construct(__node, - std::forward<_Args>(__args)...); - __node->_M_next = 0; - } - catch(...) - { - this->_M_put_node(__node); - __throw_exception_again; - } - return __node; - } + { + _Node* __node = this->_M_get_node(); + try + { + _M_get_Node_allocator().construct(__node, + std::forward<_Args>(__args)...); + __node->_M_next = 0; + } + catch(...) + { + this->_M_put_node(__node); + __throw_exception_again; + } + return __node; + } template<typename... _Args> - void - _M_insert_after(const_iterator __pos, _Args&&... __args) - { - _Fwd_list_node_base* __to - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); - _Node* __thing = _M_create_node(std::forward<_Args>(__args)...); - __thing->_M_next = __to->_M_next; - __to->_M_next = __thing; - } + _Fwd_list_node_base* + _M_insert_after(const_iterator __pos, _Args&&... __args); void _M_put_node(_Node* __p) @@ -425,21 +414,22 @@ _GLIBCXX_BEGIN_NAMESPACE(std) class forward_list : private _Fwd_list_base<_Tp, _Alloc> { private: - typedef _Fwd_list_base<_Tp, _Alloc> _Base; - typedef _Fwd_list_node<_Tp> _Node; + typedef _Fwd_list_base<_Tp, _Alloc> _Base; + typedef _Fwd_list_node<_Tp> _Node; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; public: // types: - typedef typename _Alloc::reference reference; - typedef typename _Alloc::const_reference const_reference; - typedef _Fwd_list_iterator<_Tp> iterator; - typedef _Fwd_list_const_iterator<_Tp> const_iterator; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef _Tp value_type; - typedef typename _Base::allocator_type allocator_type; - typedef typename _Alloc::pointer pointer; - typedef typename _Alloc::const_pointer const_pointer; + typedef _Tp value_type; + typedef typename _Tp_alloc_type::pointer pointer; + typedef typename _Tp_alloc_type::const_pointer const_pointer; + typedef typename _Tp_alloc_type::reference reference; + typedef typename _Tp_alloc_type::const_reference const_reference; + typedef _Fwd_list_iterator<_Tp> iterator; + typedef _Fwd_list_const_iterator<_Tp> const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef _Alloc allocator_type; // 23.2.3.1 construct/copy/destroy: @@ -479,7 +469,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * the default value. */ explicit - forward_list(size_type __n); + forward_list(size_type __n) + : _Base() + { _M_fill_initialize(__n, value_type()); } /** * @brief Creates a %forward_list with copies of an exemplar element. @@ -491,7 +483,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * value. */ forward_list(size_type __n, const _Tp& __value, - const _Alloc& __al = _Alloc()); + const _Alloc& __al = _Alloc()) + : _Base(__al) + { _M_fill_initialize(__n, __value); } /** * @brief Builds a %forward_list from a range. @@ -505,7 +499,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ template<typename _InputIterator> forward_list(_InputIterator __first, _InputIterator __last, - const _Alloc& __al = _Alloc()); + const _Alloc& __al = _Alloc()) + : _Base(__al) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } /** * @brief The %forward_list copy constructor. @@ -515,7 +515,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * The newly-created %forward_list uses a copy of the allocation * object used by @a list. */ - forward_list(const forward_list& __list); + forward_list(const forward_list& __list) + : _Base(__list.get_allocator()) + { _M_initialize_dispatch(__list.begin(), __list.end(), __false_type()); } /** * @brief The %forward_list move constructor. @@ -538,7 +540,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * in the initializer_list @a il. This is linear in il.size(). */ forward_list(std::initializer_list<_Tp> __il, - const _Alloc& __al = _Alloc()); + const _Alloc& __al = _Alloc()) + : _Base(__al) + { _M_initialize_dispatch(__il.begin(), __il.end(), __false_type()); } /** * @brief The forward_list dtor. @@ -585,7 +589,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * elements in the initializer_list @a il. This is linear in * il.size(). */ - forward_list + forward_list& operator=(std::initializer_list<_Tp> __il) { assign(__il); @@ -604,9 +608,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * that the resulting %forward_list's size is the same as the number * of elements assigned. Old data may be lost. */ - template<typename InputIterator> + template<typename _InputIterator> void - assign(InputIterator __first, InputIterator __last) + assign(_InputIterator __first, _InputIterator __last) { clear(); insert_after(cbefore_begin(), __first, __last); @@ -647,7 +651,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /// Get a copy of the memory allocation object. allocator_type get_allocator() const - { return _Base::get_allocator(); } + { return this->_M_get_Node_allocator(); } // 23.2.3.2 iterators: @@ -743,7 +747,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ size_type max_size() const - { return _Alloc().max_size(); } + { return this->_M_get_Node_allocator().max_size(); } // 23.2.3.3 element access: @@ -783,9 +787,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * and references. */ template<typename... _Args> - void - emplace_front(_Args&&... __args) - { _M_insert_after(cbefore_begin(), std::forward<_Args>(__args)...); } + void + emplace_front(_Args&&... __args) + { this->_M_insert_after(cbefore_begin(), + std::forward<_Args>(__args)...); } /** * @brief Add data to the front of the %forward_list. @@ -799,14 +804,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ void push_front(const _Tp& __val) - { _M_insert_after(cbefore_begin(), __val); } + { this->_M_insert_after(cbefore_begin(), __val); } /** * */ void push_front(_Tp&& __val) - { _M_insert_after(cbefore_begin(), std::move(__val)); } + { this->_M_insert_after(cbefore_begin(), std::move(__val)); } /** * @brief Removes first element. @@ -822,7 +827,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ void pop_front() - { _M_erase_after(&this->_M_impl._M_head); } + { this->_M_erase_after(&this->_M_impl._M_head); } /** * @brief Constructs object in %forward_list after the specified @@ -838,9 +843,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * and references. */ template<typename... _Args> - iterator - emplace_after(const_iterator __pos, _Args&&... __args) - { _M_insert_after(__pos, std::forward<_Args>(__args)...); } + iterator + emplace_after(const_iterator __pos, _Args&&... __args) + { return iterator(this->_M_insert_after(__pos, + std::forward<_Args>(__args)...)); } /** * @brief Inserts given value into %forward_list after specified @@ -856,28 +862,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ iterator insert_after(const_iterator __pos, const _Tp& __val) - { - _Fwd_list_node_base* __to - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); - _Node* __thing = _M_create_node(__val); - __thing->_M_next = __to->_M_next; - __to->_M_next = __thing; - return iterator(__to->_M_next); - } + { return iterator(this->_M_insert_after(__pos, __val)); } /** * */ iterator insert_after(const_iterator __pos, _Tp&& __val) - { - _Fwd_list_node_base* __to - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); - _Node* __thing = _M_create_node(std::move(__val)); - __thing->_M_next = __to->_M_next; - __to->_M_next = __thing; - return iterator(__to->_M_next); - } + { return iterator(this->_M_insert_after(__pos, std::move(__val))); } /** * @brief Inserts a number of copies of given data into the @@ -893,8 +885,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * does not invalidate iterators and references. */ void - insert_after(const_iterator __pos, - size_type __n, const _Tp& __val); + insert_after(const_iterator __pos, size_type __n, const _Tp& __val) + { + forward_list __tmp(__n, __val, this->get_allocator()); + this->splice_after(__pos, std::move(__tmp)); + } /** * @brief Inserts a range into the %forward_list. @@ -912,7 +907,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<typename _InputIterator> void insert_after(const_iterator __pos, - _InputIterator __first, _InputIterator __last); + _InputIterator __first, _InputIterator __last) + { + forward_list __tmp(__first, __last, this->get_allocator()); + this->splice_after(__pos, std::move(__tmp)); + } /** * @brief Inserts the contents of an initializer_list into @@ -928,7 +927,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * does not invalidate iterators and references. */ void - insert_after(const_iterator __pos, std::initializer_list<_Tp> __il); + insert_after(const_iterator __pos, std::initializer_list<_Tp> __il) + { + forward_list __tmp(__il, this->get_allocator()); + this->splice_after(__pos, std::move(__tmp)); + } /** * @brief Removes the element pointed to by the iterator following @@ -950,9 +953,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) erase_after(const_iterator __pos) { _Fwd_list_node_base* __tmp - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); + = const_cast<_Fwd_list_node_base*>(__pos._M_node); if (__tmp) - return iterator(_Base::_M_erase_after(__tmp)); + return iterator(this->_M_erase_after(__tmp)); else return end(); } @@ -980,8 +983,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) erase_after(const_iterator __pos, iterator __last) { _Fwd_list_node_base* __tmp - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); - return iterator(_M_erase_after(__tmp, __last._M_node)); + = const_cast<_Fwd_list_node_base*>(__pos._M_node); + return iterator(this->_M_erase_after(__tmp, __last._M_node)); } /** @@ -1012,7 +1015,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ void resize(size_type __sz) - { resize(__sz, _Tp(0)); } + { resize(__sz, _Tp()); } /** * @brief Resizes the %forward_list to the specified number of @@ -1039,7 +1042,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ void clear() - { _M_erase_after(&this->_M_impl._M_head, 0); } + { this->_M_erase_after(&this->_M_impl._M_head, 0); } // 23.2.3.5 forward_list operations: @@ -1055,18 +1058,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * Requires this != @a x. */ void - splice_after(const_iterator __pos, - forward_list&& __list) - { - if (!__list.empty() && &__list != this) - { - _Fwd_list_node_base* __tmp - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); - const_iterator __before = __list.cbefore_begin(); - __tmp->_M_transfer_after(const_cast<_Fwd_list_node_base* const> - (__before._M_node)); - } - } + splice_after(const_iterator __pos, forward_list&& __list); /** * @brief Insert element from another %forward_list. @@ -1079,8 +1071,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * inserts it into the current list after @a pos. */ void - splice_after(const_iterator __pos, - forward_list&& __list, + splice_after(const_iterator __pos, forward_list&& __list, const_iterator __it) { this->splice_after(__pos, __list, __it, __it._M_next()); } @@ -1098,18 +1089,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * Undefined if @a pos is in (before,last). */ void - splice_after(const_iterator __pos, - forward_list&& __list, - const_iterator __before, - const_iterator __last) - { - _Fwd_list_node_base* __tmp - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); - __tmp->_M_transfer_after(const_cast<_Fwd_list_node_base* const> - (__before._M_node), - const_cast<_Fwd_list_node_base* const> - (__last._M_node)); - } + splice_after(const_iterator __pos, forward_list&& __list, + const_iterator __before, const_iterator __last); /** * @brief Remove all elements equal to value. @@ -1151,7 +1132,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * the pointer is the user's responsibility. */ void - unique(); + unique() + { this->unique(std::equal_to<_Tp>()); } /** * @brief Remove consecutive elements satisfying a predicate. @@ -1230,8 +1212,24 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * Reverse the order of elements in the list in linear time. */ void - reverse() - { this->_M_impl._M_head._M_reverse_after(); } + reverse(); + + private: + template<typename _Integer> + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { _M_fill_initialize(static_cast<size_type>(__n), __x); } + + // Called by the range constructor to implement [23.1.1]/9 + template<typename _InputIterator> + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type); + + // Called by forward_list(n,v,a), and the range constructor when it + // turns out to be the same thing. + void + _M_fill_initialize(size_type __n, const value_type& __value); }; /** @@ -1247,26 +1245,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<typename _Tp, typename _Alloc> bool operator==(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) - { - // We don't have size() so we need to walk through both lists - // making sure both iterators are valid. - typename std::forward_list<_Tp, _Alloc>::const_iterator __ix - = __lx.cbegin(); - typename std::forward_list<_Tp, _Alloc>::const_iterator __iy - = __ly.cbegin(); - while (__ix != __lx.cend() && __iy != __ly.cend()) - { - if (*__ix != *__iy) - return false; - ++__ix; - ++__iy; - } - if (__ix == __lx.cend() && __iy == __ly.cend()) - return true; - else - return false; - } + const forward_list<_Tp, _Alloc>& __ly); /** * @brief Forward list ordering relation. @@ -1291,7 +1270,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) inline bool operator!=(const forward_list<_Tp, _Alloc>& __lx, const forward_list<_Tp, _Alloc>& __ly) - { return ! (__lx == __ly); } + { return !(__lx == __ly); } /// Based on operator< template<typename _Tp, typename _Alloc> @@ -1305,14 +1284,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std) inline bool operator>=(const forward_list<_Tp, _Alloc>& __lx, const forward_list<_Tp, _Alloc>& __ly) - { return ! (__lx < __ly); } + { return !(__lx < __ly); } /// Based on operator< template<typename _Tp, typename _Alloc> inline bool operator<=(const forward_list<_Tp, _Alloc>& __lx, const forward_list<_Tp, _Alloc>& __ly) - { return ! (__ly < __lx); } + { return !(__ly < __lx); } /// See std::forward_list::forward_swap(). template<typename _Tp, typename _Alloc> @@ -1339,4 +1318,4 @@ _GLIBCXX_END_NAMESPACE // namespace std #endif // __GXX_EXPERIMENTAL_CXX0X__ -#endif // _GLIBCXX_FORWARD_LIST_H +#endif // _FORWARD_LIST_H diff --git a/libstdc++-v3/include/bits/forward_list.tcc b/libstdc++-v3/include/bits/forward_list.tcc index 7a3a3d0beda..02b1a0d1d42 100644 --- a/libstdc++-v3/include/bits/forward_list.tcc +++ b/libstdc++-v3/include/bits/forward_list.tcc @@ -158,6 +158,20 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } template<typename _Tp, typename _Alloc> + template<typename... _Args> + _Fwd_list_node_base* + _Fwd_list_base<_Tp, _Alloc>:: + _M_insert_after(const_iterator __pos, _Args&&... __args) + { + _Fwd_list_node_base* __to + = const_cast<_Fwd_list_node_base*>(__pos._M_node); + _Node* __thing = _M_create_node(std::forward<_Args>(__args)...); + __thing->_M_next = __to->_M_next; + __to->_M_next = __thing; + return __to->_M_next; + } + + template<typename _Tp, typename _Alloc> _Fwd_list_node_base* _Fwd_list_base<_Tp, _Alloc>:: _M_erase_after(_Fwd_list_node_base* __pos) @@ -192,77 +206,35 @@ _GLIBCXX_BEGIN_NAMESPACE(std) return __pos; } - template<typename _Tp, typename _Alloc> - forward_list<_Tp, _Alloc>:: - forward_list(size_type __n) - : _Base() - { - _Fwd_list_node_base* __to = &this->_M_impl._M_head; - for (size_type __i = 0; __i < __n; ++__i) - { - __to->_M_next = _M_create_node(_Tp()); - __to = __to->_M_next; - } - } - - template<typename _Tp, typename _Alloc> - forward_list<_Tp, _Alloc>:: - forward_list(size_type __n, const _Tp& __value, const _Alloc& __al) - : _Base(__al) - { - _Fwd_list_node_base* __to = &this->_M_impl._M_head; - for (size_type __i = 0; __i < __n; ++__i) - { - __to->_M_next = _M_create_node(__value); - __to = __to->_M_next; - } - } - + // Called by the range constructor to implement [23.1.1]/9 template<typename _Tp, typename _Alloc> template<typename _InputIterator> + void forward_list<_Tp, _Alloc>:: - forward_list(_InputIterator __first, _InputIterator __last, - const _Alloc& __al) - : _Base(__al) + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) { _Fwd_list_node_base* __to = &this->_M_impl._M_head; - _InputIterator __curr = __first; - while (__curr != __last) + for (; __first != __last; ++__first) { - __to->_M_next = _M_create_node(*__curr); + __to->_M_next = this->_M_create_node(*__first); __to = __to->_M_next; - ++__curr; } } + // Called by forward_list(n,v,a), and the range constructor + // when it turns out to be the same thing. template<typename _Tp, typename _Alloc> + void forward_list<_Tp, _Alloc>:: - forward_list(const forward_list& __list) - : _Base(__list._M_get_Node_allocator()) - { - const _Fwd_list_node_base* __from = &__list._M_impl._M_head; - _Fwd_list_node_base* __to = &this->_M_impl._M_head; - while (__from->_M_next != 0) - { - const _Node* __temp = static_cast<_Node*>(__from->_M_next); - __to->_M_next = _M_create_node(__temp->_M_value); - __from = __from->_M_next; - __to = __to->_M_next; - } - } - - template<typename _Tp, typename _Alloc> - forward_list<_Tp, _Alloc>:: - forward_list(std::initializer_list<_Tp> __il, const _Alloc& __al) - : _Base(__al) + _M_fill_initialize(size_type __n, const value_type& __value) { _Fwd_list_node_base* __to = &this->_M_impl._M_head; - for (const _Tp* __item = __il.begin(); - __item != __il.end(); ++__item) - { - __to->_M_next = _M_create_node(*__item); - __to = __to->_M_next; - } + for (; __n > 0; --__n) + { + __to->_M_next = this->_M_create_node(__value); + __to = __to->_M_next; + } } template<typename _Tp, typename _Alloc> @@ -295,75 +267,49 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<typename _Tp, typename _Alloc> void forward_list<_Tp, _Alloc>:: - insert_after(const_iterator __pos, - size_type __n, const _Tp& __val) + resize(size_type __sz, value_type __val) { - _Fwd_list_node_base* __to - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); - _Fwd_list_node_base* __keep = __to->_M_next; - for (size_type __i = 0; __i < __n; ++__i) + iterator __k = before_begin(); + + size_type __len = 0; + while (__k._M_next() != end() && __len < __sz) { - __to->_M_next = _M_create_node(__val); - __to = __to->_M_next; + ++__k; + ++__len; } - __to->_M_next = __keep; + if (__len == __sz) + erase_after(__k, end()); + else + insert_after(__k, __sz - __len, __val); } template<typename _Tp, typename _Alloc> - template<typename _InputIterator> - void - forward_list<_Tp, _Alloc>:: - insert_after(const_iterator __pos, - _InputIterator __first, _InputIterator __last) - { - _Fwd_list_node_base* __to - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); - _Fwd_list_node_base* __keep = __to->_M_next; - _InputIterator __curr = __first; - while (__curr != __last) - { - __to->_M_next = _M_create_node(*__curr); - __to = __to->_M_next; - ++__curr; - } - __to->_M_next = __keep; - } - - template<typename _Tp, typename _Alloc> void forward_list<_Tp, _Alloc>:: - insert_after(const_iterator __pos, std::initializer_list<_Tp> __il) + splice_after(const_iterator __pos, forward_list&& __list) { - _Fwd_list_node_base* __to - = const_cast<_Fwd_list_node_base* const>(__pos._M_node); - _Fwd_list_node_base* __keep = __to->_M_next; - const _Tp* __item = __il.begin(); - while (__item != __il.end()) + if (!__list.empty() && &__list != this) { - __to->_M_next = _M_create_node(*__item); - __to = __to->_M_next; - ++__item; + _Fwd_list_node_base* __tmp + = const_cast<_Fwd_list_node_base*>(__pos._M_node); + const_iterator __before = __list.cbefore_begin(); + __tmp->_M_transfer_after(const_cast<_Fwd_list_node_base*> + (__before._M_node)); } - __to->_M_next = __keep; } template<typename _Tp, typename _Alloc> void forward_list<_Tp, _Alloc>:: - resize(size_type __sz, value_type __val) + splice_after(const_iterator __pos, forward_list&& __list, + const_iterator __before, const_iterator __last) { - iterator __k = before_begin(); - - size_type __len = 0; - while (__k._M_next() != end() && __len < __sz) - { - ++__k; - ++__len; - } - if (__len == __sz) - erase_after(__k, end()); - else - insert_after(__k, __sz - __len, __val); + _Fwd_list_node_base* __tmp + = const_cast<_Fwd_list_node_base*>(__pos._M_node); + __tmp->_M_transfer_after(const_cast<_Fwd_list_node_base*> + (__before._M_node), + const_cast<_Fwd_list_node_base*> + (__last._M_node)); } template<typename _Tp, typename _Alloc> @@ -375,7 +321,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) while (_Node* __temp = static_cast<_Node*>(__curr->_M_next)) { if (__temp->_M_value == __val) - _M_erase_after(__curr); + this->_M_erase_after(__curr); else __curr = static_cast<_Node*>(__curr->_M_next); } @@ -391,33 +337,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std) while (_Node* __temp = static_cast<_Node*>(__curr->_M_next)) { if (__pred(__temp->_M_value)) - _M_erase_after(__curr); + this->_M_erase_after(__curr); else __curr = static_cast<_Node*>(__curr->_M_next); } } template<typename _Tp, typename _Alloc> - void - forward_list<_Tp, _Alloc>:: - unique() - { - iterator __first = begin(); - iterator __last = end(); - if (__first == __last) - return; - iterator __next = __first; - while (++__next != __last) - { - if (*__first == *__next) - erase_after(__first); - else - __first = __next; - __next = __first; - } - } - - template<typename _Tp, typename _Alloc> template<typename _BinPred> void forward_list<_Tp, _Alloc>:: @@ -426,12 +352,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std) iterator __first = begin(); iterator __last = end(); if (__first == __last) - return; + return; iterator __next = __first; while (++__next != __last) { if (__binary_pred(*__first, *__next)) - erase_after(__first); + erase_after(__first); else __first = __next; __next = __first; @@ -462,6 +388,34 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } } + template<typename _Tp, typename _Alloc> + void + forward_list<_Tp, _Alloc>:: + reverse() + { this->_M_impl._M_head._M_reverse_after(); } + + template<typename _Tp, typename _Alloc> + bool + operator==(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { + // We don't have size() so we need to walk through both lists + // making sure both iterators are valid. + auto __ix = __lx.cbegin(); + auto __iy = __ly.cbegin(); + while (__ix != __lx.cend() && __iy != __ly.cend()) + { + if (*__ix != *__iy) + return false; + ++__ix; + ++__iy; + } + if (__ix == __lx.cend() && __iy == __ly.cend()) + return true; + else + return false; + } + _GLIBCXX_END_NAMESPACE // namespace std #endif /* _FORWARD_LIST_TCC */ diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc b/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc index 1489f9b9da5..e5ad77be917 100644 --- a/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc +++ b/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc @@ -39,7 +39,8 @@ test01() fld.resize(0); VERIFY(fld.empty() == true); - VERIFY(fld.max_size() == fld.get_allocator().max_size()); + VERIFY( fld.max_size() + == std::allocator<std::_Fwd_list_node<double> >().max_size() ); } int diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/modifiers/2.cc b/libstdc++-v3/testsuite/23_containers/forward_list/modifiers/2.cc index 9d79b22986b..a6283580586 100644 --- a/libstdc++-v3/testsuite/23_containers/forward_list/modifiers/2.cc +++ b/libstdc++-v3/testsuite/23_containers/forward_list/modifiers/2.cc @@ -51,7 +51,7 @@ test02() // Note: Calling l.insert_after(pos, 5, 42); without the long five // gets resolved to the iterator range version and fails to compile! - fl.insert_after(pos, 5L, 42); + fl.insert_after(pos, 5, 42); VERIFY(*pos == 1); ++pos; diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/1.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/1.cc new file mode 100644 index 00000000000..2650632e26c --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/1.cc @@ -0,0 +1,36 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2008 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// This file tests explicit instantiation of library containers + +#include <forward_list> + +// { dg-do compile } + +template class std::forward_list<int>; diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/3.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/3.cc new file mode 100644 index 00000000000..ca34423cc4d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/3.cc @@ -0,0 +1,37 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2008 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// This file tests explicit instantiation of library containers + +#include <forward_list> + +// { dg-do compile } + +// libstdc++/21770 +template class std::forward_list<int, std::allocator<char> >; |
